AI Coding 的反脆弱:为什么追求完美 Prompt 的人注定失败

AI Coding 的反脆弱:为什么追求完美 Prompt 的人注定失败

I. 脆弱性的伪装

现代技术工作者中流行着一种特别危险的幻觉:他们相信,只要找到一个足够聪明的 AI 模型,再配上一条足够精巧的 prompt,就能一次性得到正确的代码。

这种信仰和赌场里相信”必胜公式”的赌徒没有本质区别。他们都犯了同一个错误:把一个根本上不确定的系统当作确定性系统来对待。

OpenAI 自己的文档都白纸黑字地写着:生成式 AI 是可变的,同样的输入有时会得到不同的输出。换言之,你面对的是一个非确定性过程。你能做的不是消灭波动,而是学会在波动中存活。

但大多数工程师不愿意面对这个事实。他们更愿意相信”模型的下一个版本会解决这个问题”。这就像暴风雨前加固房屋和祈祷明天放晴的区别——前者是工程,后者是迷信。


II. 三副透镜

在中文学术圈,人们把系统论、控制论、信息论合称”三论”。这个并称粗糙,钱学森批评过它,学界对此有争议。但这不妨碍我使用它们。我不关心学科划界的政治,我关心的是:这三套理论是否能帮我们看清 AI coding 中的脆弱性来源。

答案是肯定的。

系统论揭示结构性脆弱:你的系统由哪些部件组成?部件之间有没有隐藏的耦合?边界是不是模糊到任何部件都可以越界?

信息论揭示传输性脆弱:你的意图在传递给模型的过程中丢了多少?噪声从哪些缝隙钻进来的?模型”理解”的那个东西,和你脑子里的那个东西,距离有多远?

控制论揭示动态脆弱:当系统开始偏离目标——它一定会偏离——你有没有机制去发现、去量化、去修正?还是说你只有在灾难发生后才知道出了问题?

脆弱的 AI coding 系统,通常在这三个维度上同时失守。而那些看起来”很先进”的系统——多 agent、长 prompt chain、花哨的编排层——往往恰恰是最脆弱的,因为复杂度本身就是脆弱性的温床。


III. 系统脆弱性:为什么更强的模型可能让你更脆弱

这是一个大多数人不愿意听的论点:在一个结构糟糕的系统中,模型越强,你越危险。

为什么?因为强模型会产出看起来极其专业的代码。它的语法完美,注释详尽,命名规范。你看了以后会觉得”太好了”,然后合并进主干。两周后你发现架构被无声地破坏了——异常处理链路断了,日志格式被改了,一个关键的不变式被违反了。

弱模型犯的错误是显性的:编译不过、测试挂了、语法有问题。你一眼就能看出来。强模型犯的错误是隐性的:代码能跑、测试能过、review 时看着很顺眼,但系统的长期一致性正在被侵蚀。

这和 Nassim Taleb 在《反脆弱》中的核心论点完全一致:真正的风险不是那些波动很大的东西,而是那些看起来很稳定、实际上在暗处积累偏差的东西。 大波动你会注意到,小偏移你不会——直到它们突然以灾难的形式爆发。

系统论在这里的启示很明确:不要把精力花在选”最强模型”上。花在定义清晰的边界上。花在划清可改区域与不可改区域上。花在让接口契约不可绕过上。OpenAI 的 agent 指南说得很对:先用最强模型建立性能基线,再逐步替换成更小模型。这是因为在好的系统结构中,模型是可替换的部件——而如果你的系统只有在搭配最强模型时才能工作,那你的系统就是脆弱的。


IV. 信息脆弱性:你的信号在到达模型之前就已经面目全非

Shannon 的信息论从来不关心”意义”。它只关心一件事:信号在经过有噪声的信道之后,还剩下多少可以被正确解码的内容。

把这个模型套到 AI coding 上:你脑子里有一个需求(信源);你把它写成 prompt 和文档(编码);这些材料经过上下文窗口、工具调用链、检索管道(信道)到达模型;在这个过程中,模糊措辞、缺失约束、矛盾文档、过长上下文都在注入噪声;模型根据收到的信号进行”解码”并输出代码。

问题是:大多数工程师根本不知道自己的编码质量有多差。

他们写了一句”重构这个模块”,脑子里有五十个隐含假设——保持接口不变、不破坏下游、不改日志格式、不碰那个丑但正确的 hack、输出格式跟之前一致。这五十个假设一个都没写出来,全靠默会知识。然后模型做了一个”重构”,破坏了其中十五个假设,他们却怪模型蠢。

模型不蠢。你的信号蠢。

Anthropic 有一条原则说得极其精准:把 prompt 给一个对任务没有背景的同事看,如果他困惑了,Claude 也会困惑。这其实是信息论的工程化表述:如果你的编码连同类型解码器(人类同事)都解不对,凭什么指望异类型解码器(LLM)能解对?

信息论还暴露了一个被所有 multi-agent 爱好者忽视的问题:每多一跳 handoff,信号就多衰减一次。

你的 manager agent 给 specialist agent 传达了一个任务。传达的过程本身就是一次编码-信道-解码。如果描述不够精确,specialist 理解的东西就已经偏了。它做完以后把结果传回来,又是一次编码-信道-解码。两跳之后,原始信号可能已经走样得不成样子了。

所以,多 agent 系统成功的前提不是”角色分工看起来合理”。前提是每一跳的信息协议必须极其清楚——清楚到你在人类之间做 handoff 时都不需要这么清楚的程度。如果做不到这一点,多 agent 只是在用架构复杂度换来了信息衰减。你不是在解决问题,你是在把问题藏进了一个更难调试的结构里。


V. 动态脆弱性:没有反馈回路的系统注定崩溃

控制论的核心洞见只有一个:任何会运动的系统都会偏离目标,所以你需要的不是完美的初始条件,而是持续的修正机制。

恒温器不需要第一次就把温度设对。它只需要:(1)知道目标温度是多少,(2)能测到当前温度是多少,(3)能根据偏差决定加热还是制冷。

导弹不需要一开始就对准靶心。它只需要反馈够快、修正够及时,就能在飞行过程中不断逼近目标。

AI coding 也一样。你不需要一次 prompt 说清一切。你需要的是:

  1. 一个明确的目标定义(什么算”正确”——测试用例、验收标准)
  2. 一个快速的测量机制(跑测试、lint、trace)
  3. 一个及时的修正手段(再提示、补约束、换策略、人工介入)

TDD 之所以在 AI 时代焕发第二春,不是因为工程师们突然变保守了。而是因为 TDD 恰好就是一个控制回路:

  • 写一个 fail 的测试 = 设定参考值
  • 让 AI 写实现 = 让系统运行
  • 跑测试 = 测量
  • 红变绿 = 偏差归零

这比”请帮我把这整个功能写完”高明得多。后者把控制回路的周期拉到了极长——你要等整个功能写完才能知道它对不对。而在这段时间里,偏差在高速累积。前者把回路缩短到了函数级、行为级,偏差刚出现就被捕获。

反馈回路的速度是系统存活率的决定性因素。 这是控制论的铁律,没有例外。

在 AI coding 中,这意味着反馈应该层层前置:lint 在本地拦,单测在提交前跑,契约测试在 CI 里拦,smoke test 在部署前做,trace grading 在运行时监控。把反馈点放在”PR 合并后线上出事故”的工程师,和把体检放在”进 ICU 以后”的人,犯的是同一种错误。


VI. 反脆弱的 AI Coding

脆弱的系统害怕波动。鲁棒的系统承受波动。反脆弱的系统从波动中获益。

大多数 AI coding 实践还停留在”脆弱”阶段:一次 prompt 赌一次结果,赌赢了沾沾自喜,赌输了怪模型。

少数实践达到了”鲁棒”阶段:有测试、有 CI、有 review,模型波动了也能兜住。

极少数实践触及了”反脆弱”:

  • 每次模型犯的错都被捕获、分类、转化为新的测试用例或文档约束——系统因为失败而变得更强。
  • 每次 prompt 失效都触发一次信息编码的优化——文档越来越精确,默会知识加速外显化。
  • 每次控制回路发现的偏差都反馈到系统设计中——边界越来越清晰,接口越来越严格。

在反脆弱的 AI coding 系统中,模型的每一次”犯错”都不是纯损耗,而是一次免费的压力测试。它暴露了系统的薄弱环节,给你改进的机会。你应该感谢这些错误——前提是你有足够的传感器来捕获它们,有足够的结构来消化它们。

这就是三论合在一起的真正力量:

  • 系统论告诉你在哪里布防线(结构)
  • 信息论告诉你在哪里防衰减(信号)
  • 控制论告诉你在哪里装传感器(反馈)

三者合力,你就能把一个脆弱的”生成 + 祈祷”流程,变成一个反脆弱的工程系统——它不只是”抗住”波动,而是利用波动变得更好。


VII. Guardrails 不是官僚主义,是保险丝

很多工程师讨厌限制。他们觉得 guardrails、review gates、部署门禁是”管理层加的官僚主义”。

这种想法非常脆弱。

在电路里,保险丝不是”对电流的不信任”,而是”对过载的现实主义”。你不知道过载什么时候来,但你知道它一定会来。保险丝是便宜的、局部的、快速的失败点——它烧断自己来保护整个系统。

AI coding 中的 guardrails 也一样:

  • 禁止直接改主干分支:一根保险丝。
  • 高风险文件必须人工 review:一根保险丝。
  • 数据库迁移前生成回滚脚本:一根保险丝。
  • 部署前 smoke test 不通过则阻断:一根保险丝。
  • Trace 显示 agent 在仓库里反复打转则暂停:一根保险丝。

没有保险丝的系统不是”更自由”的系统,而是”更脆弱”的系统。自由和脆弱之间,中间只隔着一层缺失的约束。

OpenAI 的 agent 指南建议给工具按风险分级——根据是否可逆、是否写入、权限等级和财务影响,决定是自动执行、暂停确认还是升级到人工。这不是过度谨慎,这是工程师对现实的尊重。

凡是你不愿意为之设置保险丝的地方,就是你最终会为之付出灾难性代价的地方。


VIII. 对”多 Agent”的怀疑

当前技术圈有一种倾向:一谈 AI coding 就要上 multi-agent。好像代理越多,系统越高级。

这让我想起金融领域的一个经典陷阱:把一个简单产品层层打包成复杂衍生品,每层打包都有”合理理由”,但最终没有人能说清风险在哪里。2008 年的金融危机就是这么来的。

多 agent 不是免费午餐。每多一个 agent 就多一次编码-解码,多一个可能失真的信道,多一组需要管理的状态。你获得了”概念分离”的好感,但你支付了”信息衰减 + 调试难度 + 同步复杂度”的代价。

OpenAI 自己的建议其实很克制:先把单 agent 能力用满,只有当 prompt 条件分支太多、工具选择持续出错时,才考虑拆分。

这是对的。复杂度不是成就,是负债。 每一层复杂度都需要用等量的结构清晰度来偿还,否则它就会变成脆弱性的温床。

好的多 agent 系统不是因为”分了很多角色”而好,而是因为每一跳的信息协议极其清楚、每个节点都有独立的反馈回路、故障可以被定位到具体环节。做到这些极其困难。如果做不到,你的多 agent 系统就只是一个”分布式的混乱”——比集中式的混乱更难修。


IX. 五条原则

  1. 假设模型会犯错——然后据此设计系统。 不是因为模型差,而是因为非确定性系统不可能不犯错。你的工作不是消灭错误,而是确保错误被快速捕获、廉价修正。

  2. 投资信号质量,而非 prompt 技巧。 花哨的 prompt engineering 是在末端做优化。真正的杠杆在上游:清晰的需求定义、完整的接口契约、无歧义的验收标准。信息论告诉你:输出的质量上限取决于输入的信噪比。

  3. 把反馈回路做到极短。 每一层反馈——lint、单测、契约测试、trace——都在缩短偏差的累积时间。反馈越快,系统越反脆弱。

  4. 对复杂度持怀疑态度。 多 agent、长 chain、花哨的编排——它们是不是真的必要?能不能用更简单的结构达到同样的效果?复杂度是需要被证明的奢侈品,不是彰显技术力的装饰品。

  5. 把每一次失败变成系统改进。 脆弱的团队复盘时说”模型今天状态不好”。反脆弱的团队复盘时问:是边界没划清(系统问题)?是文档失真了(信息问题)?还是测试没覆盖(反馈问题)?然后把答案变成新的约束、新的测试、新的文档。


X. 结语

软件工程正在发生一次深层的范式转移:从”制造代码”到”治理生成”。

治理什么?治理一个高能力但高波动的非确定性系统。

用什么治理?用系统论的结构思维来划边界、定接口;用信息论的信号思维来降噪声、保真;用控制论的反馈思维来测偏差、做修正。

那些追求”一条完美 prompt 解决一切”的人,犯的是和追求”一次完美预测解决一切”的金融分析师同样的错误。他们不理解不确定性的本质——不确定性不是一个可以被消灭的障碍,而是系统运行的永恒背景音。

真正的工程智慧不是消灭波动。是在波动中建立秩序。是让系统因为暴露于压力而变得更强,而不是更脆弱。

这就是三论给 AI coding 的终极启示:

别做预言家。做舵手。

舵手不预测风浪。舵手面对风浪。舵手有罗盘(目标)、有传感器(反馈)、有舵(执行修正的能力)。风浪越大,好舵手与坏舵手的差距越明显。

AI 时代最稀缺的,不是生成代码的能力——这个能力正在变得像电一样廉价。最稀缺的,是让生成收敛为可靠产物的能力。而这种能力的底层逻辑,恰恰就是七十多年前那三个理论家所奠定的:看清结构、守住信号、闭合回路。