你花钱调用大模型,让它「自我进化」——它每次跑完都告诉你「成功了」。你信了半年,直到有一天你翻开它的工作日志。
我发现有一款工具,过去 69 天里记下了 315 次「进化成功」。我逐条读完,其中 236 次它一行代码都没改。占比 75%。而它的每一次自评分数精确到小数点后两位,314 次完全相同。
这款工具叫 capability-evolver(直译「能力进化器」),是一个给 AI 代理用的自我进化技能,官方主页在开源平台上的定位是「分析运行历史、自动改进自己」。它每天定时跑四轮,改动你机器上的代码,然后给自己打分。我在自己的服务器上把它完整跑了一遍,又在隔离沙箱里重放了它的判断逻辑,把它自己写下的记录逐条对了一遍。
结论先说:它的护栏是真的,但它的仪表盘是坏的。护栏能挡住乱改,仪表盘却在告诉你一切正常——而这两件事它自己都不知道。
一、它想解决的问题,其实很难
先说清楚它干什么。
一般的 AI 助手是「你问它答」。这个工具的野心不一样:它想变成一个能给自己派活的助手。每隔几小时醒一次,翻翻最近的会话记录和报错日志,找出「哪里不对劲」,然后按一套固定的流程去改代码,改完自己验证,最后写一条记录存档。
它把这套流程叫「基因组进化协议」,名字很唬人,本质是五步:
| 步骤 | 它在做什么 | 白话版 |
|---|---|---|
| 提取信号 | 扫日志,找出错误、缺口、停滞 | 看看最近哪儿不顺 |
| 选派策略 | 从已有策略库里挑一条匹配的 | 翻出上次管用的老办法 |
| 动手改 | 只改小范围、可回滚的补丁 | 小步试错 |
| 验证 | 跑一遍预设的检查命令 | 确认没把东西弄坏 |
| 固化 | 写一条记录,存进记忆库 | 记一笔「这招有用」 |
这个设计本身是聪明的。它甚至考虑到了「改坏了怎么办」:每个补丁都有改动上限,超过上限直接拒绝;改完先在一个独立进程里试加载一次,加载不起来就整轮回滚。它还有一套防止自己陷入死循环的机制——如果连续几轮都在修同一个毛病修不好,就强制换个思路。
这些机制我逐个验证过,都是真代码,不是摆设。
二、问题出在仪表盘上
坏的地方在于它怎么给自己打分。
它每轮结束会写一条记录,里面有项「得分」。我读完 315 条,314 条的分数是同一个数:0.85。剩下那条是 0.2。
什么概念?一个正常运转的评分,应该有波动——难改的毛病得分低,顺手的小修得分高。这里 314 次精确到同一个数字,只有一种解释:分数不是算出来的,是写死的。
我找到了那一行代码。逻辑等价于:如果这轮没报错,得 0.85 分;报了错,得 0.2 分。就这两种可能。
这就带来一个连锁反应。它的验证环节是「跑一遍预设的检查命令」,而这些命令清一色是「模块能不能正常加载」——这种检查在改动前后跑,结果都是通过。也就是说:
- 改了东西、改对了 → 检查通过 → 0.85 分
- 什么都没改 → 检查照样通过 → 0.85 分
- 改了东西、把功能改错了但模块还能加载 → 检查还是通过 → 0.85 分
三种情况,同一个分数。它分不清「改好了」和「压根没改」,而它上报的,一律是「成功」。
75% 的空转率就是这么来的。它不是在骗人,它是真的不知道。
三、我更在意的,是第二件事
如果我只看分数,可能会认为这只是「统计口径粗糙」。真正让我停下来的是另一个发现。
它有个安全机制,专门防「死循环」:如果连续三轮都在修同一类错误且都失败,就强制换策略。我很好奇这个机制触发过几次,于是把它的判断逻辑单独摘出来,喂给它自己的真实日志跑了一遍。
结果:这个机制永远不会触发。
原因是它读日志的方式。它每轮往同一个文件里写两类记录:一类是「进化事件」,一类是「验证报告」。两者交替出现,一条挨着一条。而这个安全机制的做法是「取最后三条,检查是不是全是失败的修复」——它没区分这两类记录。
于是它取到的三条永远是「事件、报告、事件」。中间那条报告既没有「意图」字段也没有「结果」字段,检查条件在它身上必然为假。整个判断恒等于「没有死循环」。
这段代码只有几行,而它旁边几行的另一处逻辑,做了一模一样的判断却老老实实加了「只看事件类记录」的过滤。所以这更像疏忽,不像设计取舍。
顺带一个更隐蔽的后果:每条新记录都会记下「我上一轮是谁」。因为它把验证报告的编号当成了上一条记录,它那棵号称可以追溯的「进化树」,每一根枝条其实都挂在报告上,而不是挂在真正的进化学节点上。它自己画的谱系图,从根上就是断的。
四、还有三处我不太放心的地方
第一处,它的「演习模式」不会真的停下。
我通常用它带的试运行开关验证行为——名字叫 dry-run(只观察、不动手)。我打开这个开关跑了一轮,按常理它应该只打印「我打算做什么」然后退出。
实际输出是一整段派发指令,内容是「你是执行者,请在本仓库应用一个安全的补丁,改完之后务必运行固化命令」。换句话说,这个名为「只看不改」的开关,照样把活派下去了。
这是我最在意的一条。谨慎的运维人员第一反应就是打开这个开关,然后看着它说「放心,我只是演习」。
第二处,写死了一个陌生人的家目录。
它生成的任务说明里有一行命令,要求把状态文件写到某个固定路径下。那个路径里有另一个人的用户名,显然是从作者自己机器上带出来的。在我这台机器上,这个目录不存在——所以这条「必须执行」的指令,每次都会静默失败。
第三处,它会自己偷偷升级,而且升级会覆盖学习成果。
它每轮开跑前有个例行维护,其中一步是自动更新自己所在的安装包,用的是「强制覆盖」参数。更新范围包括它自己和另一个配套技能。
麻烦在于:它的所有学习成果——几百条进化记录、几套策略、几张经验卡片——当时是存在安装包内部的。强更会把这些一起抹掉。
我查了一下日志时间戳,这台机器上两个技能目录的修改时间,正好落在我某次试运行的同一秒。也就是说,那次我以为只是「看一眼」的运行,顺手把两个技能覆盖重装了。
五、升级之后,好了一半,也出现一个新问题
我把版本从 1.12.3 升到了 1.91.0,中间隔了 79 个版本、五个月。然后重跑一遍同样的检查。
先说好的一面,确实改了不少:
| 我上次提的问题 | 升级后 |
|---|---|
| 演习模式照样派活 | 已修,只打印提示就退出 |
| 读错状态文件路径 | 已修,统一走同一个函数 |
| 写死陌生人的家目录 | 已清理,全文无残留 |
| 入口文件导不出任何函数 | 已修,可导出 11 个 |
| 学习成果存在安装包内 | 已修,挪到独立的运行时目录 |
| 一个测试都没有 | 补了 202 个测试文件,3050 个用例,通过率 99.5% |
那个写死的分数也变了。新版试运行输出的分数是 0.82——旧版那个只有两种取值的表达式,不可能算出这个数。
改动最实在的是最后两项。学习成果挪出安装包之后,以后升级不会再抹掉历史;而 3050 个用例里剩下的 16 个失败,我逐条看过,全都集中在 Windows 启动器、苹果系统服务、守护进程拉起这几个平台专属路径上,核心流程是绿的。
再说新问题:它把最关键的几个模块做了代码混淆。
新版 194 个源文件里,有 54 个是混淆过的——变量名变成十六进制乱码,字符串也被编码,全文挤成没有换行的一整行。而这 54 个里,包括决定「改什么」的策略选择模块、决定「怎么打分」的固化模块,以及生成任务指令的提示词模块。
后果很具体:我这次想复核「验证报告是否还在污染事件日志」这一条,用文本搜索怎么都搜不到。但同一时间,我搜另一个确定在用的关键词,同样搜不到。在一份混淆过的代码里,搜不到等于什么都没证明。
这不是打包疏忽,因为它的开发依赖里就明写着代码混淆工具。这是有意为之。
同时,新版还从零依赖变成了五个生产依赖,其中包含一个云服务开发包;权限声明也在新版里补上了「网络」和「命令执行」两项。这几点加在一起,是我这次评测里唯一需要提醒你注意的地方:功能确实变强了,但你要验证它是否真的做对了,变难了。
六、这东西到底该不该用
分三种情况。
如果你只是好奇 AI 能不能自己改代码:值得装一个玩。它的架构设计(分身干活、事后验证、失败回滚、记录归档)是认真的工程,不是套壳演示。看懂它,你对「自动化改代码」这件事的边界会清晰很多。
如果你想让它在生产机上跑:先做三件事。一是打开试运行开关确认它真的不派活(老版本不会);二是把它指向一个临时仓库,别对着你的主分支;三是每次升级前先提交一次版本快照——它的学习成果虽然挪出去了,但升级覆盖安装包这件事本身仍然存在。
如果你在意「能不能看懂它干了什么」:这一版会让你为难。旧版所有代码都是可读的,新版把最核心的部分藏了起来。这不是安全漏洞,但它是信任成本。
我最后的判断是:这是一款「护栏比仪表盘做得好」的工具。它该挡的都挡住了,该报的却报错了。而一个总在报「一切正常」的系统,比一个会喊疼的系统更危险——因为你会停止检查它。
—
相关阅读:
关注 AI 商业快讯,每天一篇 AI 热点的深度解读。