与 AI 模型协作的两种美好设想,一天的架构与补丁,以及一个小模型答不上来的问题:你在跟谁说话?
摘要。我想从 AI 辅助工程里得到两样东西。一是省流模式:Claude 额度快用完时,活儿转到便宜模型上继续干,Claude 几乎不花钱。二是稳定工程模式:强模型(Claude Opus)只把力气花在判断上——写规格、做终审——体力活交给便宜模型(DeepSeek)。我们为这两种模式设计了一套分层架构,每一块都测了,结果到处是问题。每个问题都配一个新机制,每个机制又配一个补丁。一天之内,派发规则换了六版;大约 36 个机制来了又走,同时存活的最多时有 22 个。最后压垮它的事情很简单:守在门口的小模型(Claude Haiku)分不清我是在跟它说话,还是想让它把话转给 Opus——这不能用规则解决,因为“做判断”正是它被禁止做的事。我们把架构拆了。剩下的只有几行规则、一个脚本和三个机制。
核心想法:不要想太多架构。它很有可能对强模型是妨碍;流程设计在纸上再合理,也很有可能是未经验证的空想。
我在 Claude Code 桌面版里做工程。Opus 很好用,但额度有限。DeepSeek 提供 Anthropic 兼容的 API,所以同一条 Claude Code 命令行可以直接跑在 DeepSeek 上,几乎不占我的 Claude 额度。Haiku 又快又便宜。于是就有了两种模式。
两种设想共用一个当时觉得理所当然的前提:只要盒子画对了、箭头连对了,我们就能把每类工作都路由给负担得起它的最便宜的模型。这份报告剩下的部分,讲的就是这个前提后来怎么样了。
这套设计(“V2”)借鉴了两个相当靠谱的来源:DeepSeek Harness 的 super-agent 模式(前面一个轻量路由器,后面是强力的 worker,异步事件,外加一个看门狗),以及 Anthropic 的 orchestrator–worker 模式(由强模型监督大任务)。点一下某一层,看看每种模式在那一层放了什么——以及后来它们都怎么样了。
层之上还压着模式开关本身:用一个只报整数百分比的工具读额度,选一档,允许带过期日期的手动覆盖,并在每份计划的第一行打印当前档位——由 hook 强制执行,第一行格式不对的计划会被直接拒绝。
这套设计值得夸一句的是,我们真的测了。一天里做了七个实验(T0–T6)。下面所有数字都来自当天的日志、账本和数据表。
| 测试 | 问题 | 结果 |
|---|---|---|
| T0 | DeepSeek 的 agent 能自己拉起子代理吗? | 通过 |
| T1 | hook 能拦住主对话、不许它自己改文件吗(“结构化路由器”)? | 通过 |
| T2 | 账本和完成闸门能用吗? | 通过 |
| T3 | hook 能把子代理打回去,直到它干完吗? | 通过 |
一道真实的题(任务队列的收尾逻辑),两条路线。A:DeepSeek Pro 写规格。B:Opus 根据 Flash 的摘要写规格。两条路线相同的部分:Flash 执行,Flash 初审,Opus 终审。另外单独写了五个隐藏验收测试。
规划和“拷问”(就需求对我做访谈)都在主对话里进行——而在省流模式下主对话是 Haiku,于是设计判断力恰好在最需要它的地方变弱了。修法是再加一层:Haiku 负责转达,由 Opus 子代理或 DeepSeek 来提问。
每个测试都暴露一个问题。每个问题都用同一种方式回应:加一个新机制。一步步看补丁日志。
选一个版本。划掉的是已删除的,描边的是该版本新增的,红色圆点表示这个机制从未在真实任务上测过,或从未上线。
到 v0.5,主对话已经被压缩成纯粹的转达。它的全部工作就是:把我的话交给新开的 Opus 总管,把总管的回答带回来,自己从不动脑。任何工程或项目类请求——哪怕只是一个问题——都必须转发。没有“小事”例外(早先的一个例外让 Haiku 可以悄悄自己干活)。
它失败的原因听起来微不足道,事后看却是致命的。你来当一次转达者试试。下面每条消息都可能是我会发的;其中两条是我真实发给 Haiku 会话的话。
规则说“不要判断”,可“这条该不该转发”本身就是判断——而规则把这件事交给了系统里最弱的模型。hook 可以阻止模型去做某件事(T1 已经证明了);但它拦不住模型该转发而不转发,也拦不住它在压缩时丢掉意思。转达也没有省下什么:每个新总管都要重读一遍上下文;而当主对话本来就是 Opus 时,再开一个 Opus 总管纯属重复。用了一阵之后,我的评价很直白:Haiku 干不了这个活。但换一个更强的转达者,也只是把缺陷藏起来:架构已经把守门人变成了意图路由器,而意图是整段对话里最难判断的东西。
v1.0 又试了一次,做减法:按主对话当前跑的模型分档;Haiku 只需要把消息分进三个筐(改代码 / 问项目 / 闲聊);脚本负责写任务卡、跑闸门,最多三轮就停。它有 30 个单元测试,全绿。
sub 函数。写卡的模型抄来了一条需要 tests/__init__.py 的测试命令;同一张卡又禁止添加 __init__.py。第 1 轮:验收失败。第 2 轮:文件加上了,验收通过,闸门却判它越界。第 3 轮:卡住,被手动终止。两项检查互相矛盾,再能干的执行者也没法同时满足。架构到此为止。v2.0 删掉了闸门、验收命令、返工轮次、写卡步骤、账本、模板、测试和转达层。同一个任务,7 轮、11 秒做完。
| 省流:承诺 | 省流:现在 | |
|---|---|---|
| 主对话 | Haiku 转给一个 DeepSeek Pro 总管 | Haiku 聊天;遇到工程请求,把我的原话一字不改地塞进一条命令,再原样转达回复 |
| 检查 | 闸门 + Flash 初审 + Pro 终审 | 没有了——我自己看结果 |
| 稳定:承诺 | 稳定:现在 | |
| Opus | 短暂调用,写规格和终审;从不读代码 | 直接干活;能交给 DeepSeek 的就交;自己读 diff |
| 执行 | Flash,跑在带闸门和沙箱的流水线里 | Flash,带着完整工具集,一个 80 轮的上限 |
| 节省 | 80–90%(估计) | 未知(额度表看不出来) |
最后一点讽刺。活下来的那个脚本,启动 DeepSeek 时仍带着 --bare 这个“隔离”标志,它会悄悄把 agent 削到只剩三个工具,并剥夺它拉起子代理的能力。T0 早就发现了这一点,还写进了两份笔记。没有人回去重读那两份笔记;这个限制被当成 DeepSeek 的固有事实记了下来。直到我问了一句为什么,它才被修掉。就连这次简化,也继承了一小片挡在模型路上的旧架构。
Rich Sutton 的 The Bitter Lesson 指出:长远来看,利用算力的通用方法,会赢过人手编码进去的人类知识。这一次,是同一个小尺度、一天、一个人的翻版。