SkillLite 自进化代码思路解析:从 `decisions` 到 prompts / memory / skills 三臂
副题:代码实现在 crates/skilllite-evolution 模块;调度、统计、冷却与审计类型都和 SQLite 里的决策记录强绑定——这层,意味着不能把「没改文件」当成 bug,也不会把「开了进化」误解成「一定产出 diff」,最终还是由对话过程的数据质量以及模型能力决定。
写文章也是为了复盘和记录skilllite开发过程中的架构思路和思考。
一、为什么要把「进化」拆成数据问题,而不是 UI 开关问题
很多助手产品把「自动优化」做成黑盒:用户只知道「开了」。SkillLite 选择把学习样本落在本地 decisions 表里——每条对应一次任务型对话回合,带上工具次数、成败、可选的 tool_sequence_key、重规划次数、反馈等。
进化引擎读的是这张表在最近 N 天窗口里的统计,再决定本轮要不要提案、开哪几条进化的「臂」、写不写盘。
这样做的好处很朴素:
- 可解释:时间线、NoScope、SkippedBusy 都能对上「样本够不够 / 锁没占住」。
- 可回放:
evolution_log记 scope、提案与结果,不等于替代decisions,但能把「这轮发生了什么」串起来。 - 可治理:调阈值本质是调「统计量 → 行为」的映射,而不是调一句营销文案。
二、五句话跑通一整条链路(读完能给别人讲清楚)
- 聊天里每次任务在本地 DB 记一条
decisions。 - 闹钟或「最近折腾够了」(A9 生长调度等)时,系统判断要不要 spawn
skilllite evolution run。 - 真正跑的时候:先看 「有没有值得做的提案」;没有就记 NoScope 结束。
- 有提案且允许执行:可能改 提示词 / 记忆 / 技能(Skill) 里你打开的那几臂。
- 新 Skill 往往先进
_evolved/_pending,需要你再确认——不是静默覆盖全仓库技能树。
三、三臂各自改什么、吃什么数据(与实现对齐的心智模型)
一轮 run_evolution 里,prompts / memory / skills 可以并行开多臂,每一臂有自己的 learner 与落盘位置(以下为「典型」路径,具体以代码为准):
| 方面 | 常见产出 / 落盘 | 主要输入 |
|---|---|---|
| 规划提示(规则 + 示例) | chat/prompts/rules.json、chat/prompts/examples.json 等 |
decisions 中成功/失败摘要、高工具样本,经 L1/L2/L3 类门禁后合并 |
| 记忆 | memory/evolution/ 下按维度分卷(如 YYYY-MM.md) |
近期窗口内的决策抽取;偏可检索事实,与「何时做何事的规则句」分工 |
| 技能 | chat/skills/_evolved/(含 _pending/) |
重复成功模式、失败模式、轨迹等;还有更重校验,故常见「臂开了但本轮无落盘」 |
另外还有 可选第四臂:外源学习(默认关闭,需显式环境条件),避免与「本地 decisions 驱动」混谈。
四、Passive / Active / 协调器:谁在「拍板」
- Passive(
should_evolve_impl):看窗口内的 meaningful(够「有工具摩擦」的条数)、failures、replans、repeated_patterns(高成功率重复模式组数) 等;各臂独立判断是否该开。 - Active:在「稳定成功」的未进化决策达到门槛后,用低风险提案在一维上推进;与
EvolutionMode组合相关——若你读到EvolutionMode::All下优先只开 memory 的分支,以scope.rs为准。 - 协调器:在 Passive / Active 两条提案里选一条执行;
force=true可绕过被动侧冷却/阈值,但 learner 仍可能因无样本或门禁而不写文件。
产品预期(避免误解):「开了多臂」≠「一定有 diff」。LLM 认为不必改、查询为空、测试未过,都会出现「本轮无新规则/技能」——助手侧文案会刻意弱化,避免用户以为系统在摸鱼。
五、审计类型:为什么要把「空跑」从 evolution_run 里拆出来
这是一个很关键的工程语义:
evolution_run:本轮产生了至少一条 changelog 类变更(有「材料」)。它会推进被动冷却里「距上次有产出跑」的时钟,并参与 A9 里「多久没真正进化过」的判断。evolution_run_noop:已进入 learner,但合并结果为空。它不应假装成「刚完成一次有产出进化」——因此不推进上述冷却时钟,但仍可计入每日上限(防止无意义子进程被刷爆)。evolution_run_outcome:未进入完整执行(NoScope、Busy 等)的调度结果;与「跑满一轮」的计数语义不同。
把 noop 拆清之后:时间线仍有记录,冷却只认真有落盘的轮次,用户也不会被「明明没改文件却在冷却」误导。
六、一张总览图(把「表 → 调度 → learner → 落盘」串起来)
七、和 spec/capability-gap-evolution.md 不是一回事(防概念串台)
仓库里还有一份 spec/capability-gap-evolution.md:讲的是 contributor 在本 git 仓库里写小脚本、把重复劳动晋升到 scripts/ 或 Skill 的工程习惯,不是产品运行时「自动进化引擎」的配置模型。
读进化机制时,把这两层分开,讨论会干净很多。
八、三件事
- 对照
crates/skilllite-evolution/src/scope.rs里should_evolve_impl:把 meaningful / repeated_patterns 的 SQL 语义和自己业务里的「什么叫重复」对齐。 - 看日志类型:区分 material / noop / outcome,再解释「为什么这轮没改文件」。
- 修改阈值:改阈值时同步想清楚——动的是「开不开臂」还是
skill_synth/query.rs里「喂给 LLM 的模式列表」(二者查询并不完全相同)。
版权声明:本文描述的是 SkillLite 开源仓库在撰写时的实现思路;转载请注明项目与文档出处。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)