用JSON和Python命令行构建个人技能管理工具:从数据建模到实践

1. 为什么需要技能管理工具:需求拆解与设计取舍

上周末想更新简历,结果发现我根本说不清“现在到底会什么”。十几项技能分散在旧简历、脑图、收藏夹和一摞笔记本里,有的早已过期,有的只停留在“看过教程”的阶段,还有的写出来自己都心虚。于是我决定花一个周末做一个本地命令行工具,项目名就叫skills,专职维护个人技能清单和成长进度。

这个工具不打算做成知识管理库,也不做课程打卡,只解决三个问题:我拥有哪些技能?每项技能到了什么程度?下一步该学什么?最小可用版本就是“一个JSON文件加一个Python脚本”,但它要能支撑我未来几个月持续更新。如果你也经常被问到“你会什么”却答不上来,或者想系统规划学习路线,这篇文章的完整实现思路应该能给你不少启发。

1.1 痛点:技能信息散落各处,无法回答“我会什么”

先描述一个真实场景。多数人的技能信息至少存在四个地方:简历里写过“精通某种语言”,被追问后发现只是会写基础语法;笔记应用里收藏了几十个教程,但没记录学到哪一章节;个人网站的标签页很久没更新;项目仓库的README提到过技术栈,但已经是半年前的状态。当需要评估自己的竞争力或规划下一步时,只能靠记忆拼凑一个模糊答案。

更麻烦的是,技能之间有依赖关系。比如想学Spring Boot,应该先掌握Java基础和构建工具,可分散的记录根本不会表达这种关系。我经常跳级学习,结果效率极低。那时候我需要的不是又一个大而全的笔记应用,而是一个能记录“熟练程度”和“前置依赖”的轻量级清单,并且要足够快,让我愿意在每天结束时顺手更新几笔。

1.2 为什么不用电子表格、脑图或在线笔记

很多人第一反应是用电子表格。电子表格确实适合统计,但录入技能的体验很糟糕:新增一条要填很多列,输入熟练度时还会纠结填“高/中/低”还是数字。脑图适合展示层级和依赖关系,但每次更新都要拖动节点,而且条件查询非常费劲。在线笔记工具虽然方便分享,但打开慢、格式封闭,导出后数据很难被其他程序使用。

我最终选型是“JSON文件+Python命令行”。理由很直接:数据是纯文本,能放进版本管理工具里做每次修改的diff;命令行交互比打开应用快一个数量级;所有代码加起来不到两百行,完全可控。个人技能管理场景的数据量撑死几百条,用数据库反而小题大做。JSON作为中间格式的最大优点,是未来换任何语言都能无缝读取。

1.3 核心需求收敛:最小功能集就够了

为了避免过度设计,我只留了五个核心需求。一是新增技能时能记录名称、分类、标签、熟练度、目标熟练度、学习进度和前置依赖;二是能查看所有技能,并支持按分类和标签过滤;三是能更新技能状态,比如今天学了两小时就把进度从50改成65;四是能删除废弃技能;五是能输出技能树和统计信息,用来判断学习优先级。

其他需求全部砍掉,包括多用户、云同步、日历提醒、富文本笔记。这些功能加进来会显著拖慢开发,而且我在个人场景里根本用不到。一条最重要的原则是:工具越简单,坚持使用的概率越高。与其画一个功能满满的饼,不如先跑起一个每天愿意打开十次的命令行。

方案录入效率依赖关系表达条件查询数据迁移适合程度
电子表格中等弱中等一般偏低
脑图低强弱弱偏低
在线笔记低弱弱弱低
JSON+CLI高强高高高

2. 技能数据建模:用JSON撑起一个足够灵活的结构

确定选型之后,最关键的事就是设计数据结构。这套结构决定了工具后续能不能扩展。如果字段设计不好,每加一个功能都要改格式和数据迁移;如果设计得当,以后换语言、换界面,数据本身依然可以复用。我在动手前花了半天专门做这一步。

2.1 技能条目的字段设计

我的skills.json顶层只有两个字段:version和skills。skills是一个对象,键是技能ID,值是完整的技能条目。用对象而不是数组,是为了让查找和更新更快。一个技能条目大概长这样:

{ "version": 1, "skills": { "python-basics": { "name": "Python编程基础", "category": "编程语言", "tags": ["python", "基础"], "level": 4, "target_level": 5, "progress": 80, "status": "active", "depends_on": [], "resources": [], "note": "", "updated_at": "2025-01-15" }, "flask-web": { "name": "Flask Web开发", "category": "Web框架", "tags": ["python", "web"], "level": 3, "target_level": 4, "progress": 60, "status": "active", "depends_on": ["python-basics"], "resources": ["flask官方文档"], "note": "重点补一补RESTful设计", "updated_at": "2025-01-14" } } }

字段看起来多,但每个都有明确价值。id是机器可读的唯一标识,用短横线命名,比如python-basics。name是展示用的完整名称,随时可以改。category是大的分类,比如编程语言、Web框架、DevOps、软技能。tags数组用于跨分类筛选,比如python这个标签会同时命中Python基础和Flask开发。level和target_level记录当前熟练度和目标熟练度,progress是学习进度百分比。depends_on保存前置技能的ID列表,这是生成技能树和学习路径的关键。note字段留给临时想法,比如“记得补RESTful设计”。

2.2 熟练度分级与进度分离:为什么不用百分比表示level

熟练度我坚持用0到5的整数等级,而不是百分比。原因很简单:熟练度是等级概念,不是精确度量。我给五级分别定了一个可对照的行为锚点:0代表完全不会,1代表只听说过或看过,2代表能照着教程做,3代表能独立完成常见任务,4代表能灵活解决复杂问题,5代表能给别人讲清楚、可以输出教学级内容。打分时只要对照这些描述,几秒钟就能完成,不会因为今天心情好就乱打高分。

progress字段则是“当前学习进行到哪里”。比如我正在学Flask,基础入门部分已经完成60%,但熟练度可能只有2,因为还没做完整项目。这两个维度各有用途:level反映“我现在的能力是多少”,progress反映“我计划中的学习路径完成了多少”。分开存储后,统计模块就能回答两类问题:一类是“我的熟练度分布是否均衡”,另一类是“手头进行中的学习计划平均完成度如何”。如果只用百分比,后一类问题根本算不出来。

2.3 用id做对象键与依赖关系表达

我花了一点时间纠结skills到底用数组还是对象。数组的好处是顺序自然,但删除和改名时会很麻烦:删掉一个元素,后面所有索引都会变;按名字查找要遍历整个列表。对象的好处是key唯一,直接data['skills']['flask-web']就能定位到目标。最终我当然选了对象。

依赖关系依赖depends_on字段。这个字段里存的是前置技能的ID,而不是名字。为什么不用名字?因为名字可以改,ID才是稳定标识。比如我把“Flask Web开发”改名为“基于Flask的RESTful服务开发”,所有依赖它的技能依然能通过flask-web找到它。在输出技能树时,不是简单从上往下打印,而是先构建一个“反向依赖表”,从没有依赖的根技能开始,一层层列出依赖它的后续技能。这其实就是一个简化版拓扑遍历,但代码量很少,却解决了“先学什么后学什么”的核心问题。

2.4 数据校验:防止脏数据进入

既然数据文件用手工维护,那就一定会产生脏数据。我在load_data之后会跑一个validate_data函数,专门检查几个硬规则:level必须在0到5之间,progress必须在0到100之间,target_level不能小于level,depends_on里引用的ID必须真实存在。如果违反规则,工具会给出明确提示并拒绝保存。

这些校验一开始没有,直到有一天我把level写成了6,统计图里直接出现了一个异常柱状条。后来我意识到,个人工具虽然小,但也要在入口处设一道防线。校验逻辑不复杂,却能让未来一个月的数据都是干净的。如果确实存在循环依赖,比如A依赖B、B依赖A,tree命令也能通过visited集合避免无限递归。

3. 从零实现一个skills命令行工具

现在开始最令人兴奋的部分:动手写代码。整个项目只有两个文件:一个Python脚本skills.py,一个数据目录。不需要第三方依赖,只用Python标准库里的argparse、json、datetime和pathlib。只要机器上有Python 3.8以上就能跑。下面完整展示实现思路和关键代码。

3.1 项目结构与存储初始化

项目目录保持极简:

skills/ skills.py data/ skills.json backup/

data/skills.json在首次运行时自动创建,不需要手动编辑。我在skills.py里定义两个辅助函数load_data和save_data。load_data会检查文件是否存在,不存在就返回初始结构;save_data会在写入前自动把现有skills.json复制成带时间戳的备份文件。这个设计后来真的救了我,第4部分会详细说。

初始化相关代码是这样的:

import json, argparse, datetime, re, sys from pathlib import Path BASE_DIR = Path(__file__).resolve().parent DATA_DIR = BASE_DIR / 'data' SKILLS_FILE = DATA_DIR / 'skills.json' BACKUP_DIR = DATA_DIR / 'backup' def init_storage(): DATA_DIR.mkdir(exist_ok=True) BACKUP_DIR.mkdir(exist_ok=True) if not SKILLS_FILE.exists(): save_data({'version': 1, 'skills': {}}) def load_data(): if not SKILLS_FILE.exists(): init_storage() with open(SKILLS_FILE, 'r', encoding='utf-8') as f: return json.load(f) def save_data(data): init_storage() ts = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') backup_name = BACKUP_DIR / f'skills_{ts}.json' if SKILLS_FILE.exists(): with open(SKILLS_FILE, 'r', encoding='utf-8') as src: with open(backup_name, 'w', encoding='utf-8') as dst: dst.write(src.read()) with open(SKILLS_FILE, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2)

save_data每次写入都先备份当前文件,虽然会留下许多备份文件,但个人使用完全无所谓。这段代码的价值在于:万一改坏了数据,只要把backup目录里最近一份文件拷贝回来,就立刻恢复。相信我,这个习惯能避免很多崩溃时刻。

3.2 核心命令:add、list、update、rm

命令解析用argparse,标准库自带,能自动生成帮助信息。main函数里定义四个子命令,并在调用前加参数校验。先看add命令的实现:

def make_id(text): return re.sub(r'[^a-z0-9]+', '-', text.strip().lower()).strip('-') def normalize_tags(tag_str): if not tag_str: return [] tags = [] for t in tag_str.split(','): t = t.strip().lower() if t: tags.append(TAG_ALIASES.get(t, t)) return tags def cmd_add(args): data = load_data() skill_id = args.id or make_id(args.name) if not skill_id: print('错误:无法根据名称生成id,请用--id参数指定') return if skill_id in data['skills']: print(f'技能已存在: {skill_id},请用update命令修改') return data['skills'][skill_id] = { 'name': args.name, 'category': args.category or '未分类', 'tags': normalize_tags(args.tags), 'level': int(args.level), 'target_level': int(args.target_level) if args.target_level else 5, 'progress': int(args.progress) if args.progress else 0, 'status': 'active', 'depends_on': [x.strip() for x in args.depends_on.split(',') if x.strip()] if args.depends_on else [], 'note': args.note or '', 'updated_at': datetime.date.today().isoformat() } save_data(data) print(f'已添加技能: {args.name}')

make_id函数会把英文名转成短横线形式,如果是纯中文名则可能生成空字符串,所以我允许用户用--id手动指定。中文技能的id建议用英文或拼音缩写,比如“Flask Web开发”的id是flask-web,这样在命令行里不会出现编码问题。

使用方法示例:

python skills.py add \ --name "Flask Web开发" \ --id flask-web \ --category "Web框架" \ --tags python,web \ --level 3 \ --target 4 \ --progress 60 \ --depends-on python-basics

list命令默认展示全部技能,支持按分类、标签、状态过滤,并按level从高到低排序。输出用表格形式,但不用第三方库,直接做字符串格式化。代码核心就一句列表推导加格式化输出,这里不展开。update命令支持部分字段更新,用户传哪个字段就改哪个字段。rm命令按ID删除,但删除前会检查是否有其他技能依赖它,如果有,会给出警告并要求输入--force确认。

3.3 进阶能力:搜索、统计与依赖树输出

工具做到这里已经能用,但“好用”是从加了search和stats开始的。search命令在name、category、tags、note四个字段里做不区分大小写的子串匹配,结果按level排序。stats命令会输出总技能数、分类分布、熟练度分布、进行中学习项和平均学习进度。

stats的实际输出大概长这样:

技能总数: 23 分类分布: 编程语言: 8 Web框架: 5 DevOps: 4 软技能: 6 熟练度分布: level 0: 1 level 1: 3 level 2: 5 level 3: 8 level 4: 4 level 5: 2 进行中的学习项: 5 平均学习进度: 47%

我再加了一个很实用的判断:如果某个技能level小于3,且它依赖的前置技能里有任何一项level也小于3,就把这个技能标记为“前置未达标”。在训练自己的学习规划时,这个标记帮我及时发现跳级问题。比如我发现“RESTful API设计”被标成前置未达标,原因就是它的前置技能“Flask Web开发”只有level 2。于是我把学习顺序调整到先巩固Flask基础,再深入RESTful设计。

tree命令则生成Markdown格式的技能树。核心思路是先构建反向依赖表,从没有任何前置技能的根节点开始递归输出。代码里用visited集合防止循环依赖死循环。输出结果可以直接贴进个人网站或周报:

- Python编程基础 (level 4, 进度 80%) - Flask Web开发 (level 3, 进度 60%) - RESTful API设计 (level 2, 进度 20%) - 数据分析基础 (level 3, 进度 50%)

有了这个输出,每周复盘就变成了一次命令调用。我通常会在周五跑一遍skills tree,然后结合stats决定下周重点补什么。

3.4 参数校验、错误处理与效率技巧

参数校验在命令行工具里很容易被忽略,但我吃过亏。为了让level不能超过5,progress不能超过100,我写了一个简单的validate_args函数。如果校验失败,立即打印错误并退出,不会把坏数据写进JSON。

def validate_skill_args(level, target_level, progress): level = int(level) target_level = int(target_level) progress = int(progress) if not (0 <= level <= 5): sys.exit('level必须在0到5之间') if target_level < level: sys.exit('目标熟练度不能低于当前熟练度') if not (0 <= progress <= 100): sys.exit('progress必须在0到100之间') return level, target_level, progress

使用上也有一个提高效率的小技巧:为常用命令设置shell alias。比如在.zshrc里加:

alias skills='python3 ~/tools/skills/skills.py' alias skills_add='python3 ~/tools/skills/skills.py add' alias skills_tree='python3 ~/tools/skills/skills.py tree'

这样我每天更新学习进度时,只需要敲skills update --id flask-web --progress 65,一个命令十秒钟就完成。工具的价值在于“它是你愿意用的工具”,而不是“功能最多的工具”。

4. 真实使用中的翻车记录与排查思路

工具写出来不难,难的是连续使用三个月后还能保持数据可靠。这一段我整理了自己踩过的五个真实坑,每一个都值得后来者注意。我会把问题和解决过程写清楚,方便你直接避坑。

4.1 数据文件被误删之后:备份策略是必需品

有一次我重命名了data目录,脚本还在引用旧路径,save_data直接新建了一个空的skills.json。等我发现时,原来的技能清单已经变成版本1的空文件。还好save_data每次写入前都会备份到backup目录,我通过最近一份备份恢复,整个过程不到两分钟。从那以后,我把“任何修改前必须备份”这句话刻在了脑子里。

个人工具的容灾设计很容易被忽略,因为你觉得“只有我一个人用,不会出问题”。实际上,一个rm -rf、一次路径写错,就足以让几个月的数据瞬间蒸发。我的方案是双保险:脚本自动做时间戳备份,同时整个data目录放进版本管理工具,每次修改后手动提交一次。

4.2 标签大小写和同义词混乱

tags字段用了几天就开始失控。同一门技术会在不同时间被写成Python、python和PYTHON;同义词也乱七八糟,web、website、后端、DevOps混在一起。后来我在normalize_tags函数里统一做小写、去空格处理,并维护一个标准标签别名表:

TAG_ALIASES = { 'website': 'web', '后端': 'back-end', 'devops': 'devops', }

add和update写入tags前都会先过一遍别名映射。这个改造让按标签筛选变得可靠。数据治理不只是在数据库设计阶段考虑,个人工具同样需要。输入天然是混乱的,最好在入口处就做好规范,而不是事后清洗。

4.3 熟练度标准漂移:从“熟练”到“精通”的口径统一

初版工具的熟练度定义写在代码注释里,但实际操作时总会忘记“3级到底是什么水平”。有一阵我信心爆棚,给某项技能打了4分,过一周再看发现连基础原理都说不清,又改回3分。这种前后不一致会直接误导学习计划。

我的解法是把熟练度标准单独放在项目根目录的SKILL_LEVEL_GUIDE.md里,每次打分前扫一眼。现在我的标准是:能独立完成常见任务就是3级,能灵活应对复杂问题才是4级,能整理成教程教会别人才是5级。把标准写下来,是控制主观漂移最有效的手段。工具只能帮我们记录数据,定义好尺子的人始终是我们自己。

4.4 多设备同步冲突的本地解法

skills没有云同步,但我希望在公司电脑和家里电脑之间保持一致。最初我把skills.json放进同步盘,结果两台电脑同时修改时产生了冲突副本,搞得数据出现分叉。后来改成“单写主设备”策略:所有更新都在一台设备上完成,再通过同步盘把最新版本推送到其他设备。这个限制对个人项目完全可接受。

如果你确实需要多端修改,也可以给每个操作打时间戳,同步时按“后改获胜”规则合并。但合并逻辑会变得复杂,不建议在最小工具里实现。对我来说,单写主设备加时间戳备份已经足够。

4.5 常见问题速查表

最后把高频问题整理成一张速查表,方便对照解决:

问题可能原因解决方案
技能重复出现name或id不符合预期用list查看id,用rm删除后重新add
标签筛选不准标签大小写、别名不统一检查normalize_tags和TAG_ALIASES配置
level数字越界手动编辑JSON时写错运行stats看分布,手动改回0到5区间
progress累计超过100频繁update且不检查原值在update里增加上限校验
tree命令出现死循环存在循环依赖检查depends_on字段,删除形成环的引用
backup目录越来越大每次保存都生成备份写一个小脚本,保留最近30份即可

这套工具用到现在已经进入第四个月,唯一一次数据回滚就是因为备份机制,其余问题基本都靠入口校验解决了。如果你也要做类似的项目,我的建议是:从最简单的add和list开始,不要一上来就做花哨的网页和图表。技能管理的本质不是“记录工具有多强”,而是“你能多频繁地掏出它更新一行状态”。数据结构和备份策略看起来不起眼,却比任何炫酷功能更值得用心设计。

相关新闻

企业微信回调验证与AES加解密:.NET开发者接入指南

企业微信回调验证与AES加解密:.NET开发者接入指南

接手过几个企业微信自建应用的项目&#xff0c;每次新人对接时几乎都会卡在同一个地方&#xff1a;管理后台保存“接收消息服务器”配置时提示URL验证失败&#xff0c;或者明明验证过了&#xff0c;消息却一直推送不进来。这个环节看着只是填几个参数&#xff0c;背后实际上是一…

2026/10/20 20:20:51 阅读更多 →
vLLM Prefix Caching 原理:如何用 Paged KV 消除重复计算

vLLM Prefix Caching 原理:如何用 Paged KV 消除重复计算

先说一个我遇到过的情况。某个线上推理服务&#xff0c;所有请求都带着同一段两千多字的 system prompt&#xff0c;并发一上来&#xff0c;GPU 利用率看着很高&#xff0c;但真正对用户有用的计算没多少——大部分算力在一遍遍重复计算同一段内容的 K 和 V。很长一段时间里&am…

2026/10/20 20:20:51 阅读更多 →
用Design.md构建符合产品风格的原型设计:设计令牌实战指南

用Design.md构建符合产品风格的原型设计:设计令牌实战指南

上周跟某团队聊原型评审&#xff0c;对方把三个页面的设计稿拍在我面前&#xff0c;主色蓝就出现了五种&#xff0c;没有两个颜色值相同。评审会开了一个小时&#xff0c;快一半时间在争论“这个蓝到底是不是我们品牌那个蓝”。原型阶段最让人心累的从来不是画得快不快&#xf…

2026/10/20 20:19:47 阅读更多 →

最新新闻

TensorFlow鞋类识别实战:Fashion MNIST图像分类全流程

TensorFlow鞋类识别实战:Fashion MNIST图像分类全流程

前段时间重新整理之前的深度学习实验笔记&#xff0c;翻到鞋类识别&#xff08;Fashion MNIST&#xff09;这个项目时&#xff0c;觉得特别值得拿出来单独写一篇。原因很简单&#xff1a;很多人入门深度学习时&#xff0c;都会被建议先跑通手写数字识别&#xff08;MNIST&#…

2026/10/20 20:57:37 阅读更多 →
用AI辅助Kamailio路由排错:一场人机讨论实录与故障切换实践

用AI辅助Kamailio路由排错:一场人机讨论实录与故障切换实践

最近接手一套老的SIP通信平台&#xff0c;核心信令是Kamailio撑着。业务要新增一个较复杂的路由策略&#xff1a;同一个主叫号码&#xff0c;在不同时间段、针对不同被叫前缀&#xff0c;要分别走不同的网关&#xff1b;而其中一路网关做故障切换时&#xff0c;还要保证已经建立…

2026/10/20 20:57:37 阅读更多 →
LibVLC轻量级视频播放模块:嵌入C/C++工程的硬件解码方案

LibVLC轻量级视频播放模块:嵌入C/C++工程的硬件解码方案

简介&#xff1a;本资源是一份基于C/C与VLC开源库开发Windows视频播放器的完整工程实践包&#xff0c;面向具备基础C编程能力、希望掌握多媒体开发技能的中级开发者及高校课程设计学习者。资源聚焦于在Visual Studio 2022环境下集成libvlc实现视频加载、播放控制、窗口渲染等核…

2026/10/20 20:57:37 阅读更多 →
AI Agent创业团队如何配置一支高效的Harness Engineering团队

AI Agent创业团队如何配置一支高效的Harness Engineering团队

1. 为什么需要一支专门的Harness Engineering团队先从一个很现实的场景说起&#xff1a;你所在的创业团队花三个月做出了一个基于大模型的Agent产品Demo&#xff0c;演示给投资人看时效果炸裂&#xff0c;但真正进入客户试用阶段&#xff0c;问题接踵而来——模型给出正确意图却…

2026/10/20 20:57:37 阅读更多 →
视觉语言模型与RGB-D感知融合:三条进化主线与工程实践

视觉语言模型与RGB-D感知融合:三条进化主线与工程实践

1. 从 Transformer 到多模态感知的演进逻辑视觉语言模型和 RGB-D 感知这两个方向&#xff0c;过去几年基本是各走各的路。做 VLM 的人盯着图文对齐、指令跟随、视觉问答这些任务&#xff0c;做 RGB-D 的人则埋头于点云配准、深度补全、SLAM 建图。但最近一年&#xff0c;这两条…

2026/10/20 20:57:37 阅读更多 →
VTI介质地震波数值模拟:MATLAB实现与各向异性正演避坑指南

VTI介质地震波数值模拟:MATLAB实现与各向异性正演避坑指南

简介&#xff1a;这份资源面向地震勘探与地球物理方向的学习者和研究者&#xff0c;提供一套基于Matlab的VTI介质地震波场数值模拟程序&#xff0c;用于分析各向异性介质中地震波的传播规律。VTI介质在垂直与平行层理方向上纵波速度存在差异&#xff0c;是实际地壳中常见的各向…

2026/10/20 20:56:32 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →