site logo

Marico's space

为什么你的 AI 编程 agent 总能自信地交付略有偏差的代码(以及为什么改写 prompt 从来没用)

AI技术与应用 2026-06-29 11:27:57 5

你的 AI 编程 agent 写出来的东西看起来没问题。脑子里过一遍,编译通过了。然后你发现它调用了 user.getProfileById() —— 一个代码库里根本不存在的方法。

你从来没让它编造这个方法。它非常自信地在代码里塞了一个,中间部分反而写得挺正常。这就是最恶心的错误:不是明显崩溃,而是悄悄地、有偏差地不正确,你得自己抓出来。

如果你在真实项目里用过 Claude Code、Cursor 或者其他 agent,肯定遇到过这个情况。这篇说说为什么会出现这个问题——以及为什么改写 prompt 从来不是正确答案。

所有人都先尝试的"修复"(以及为什么没用)

你改写了 prompt。

加上"不要编造函数"。好了一小会儿,在某一个文件里。然后它又犯了。于是你加了一句"只使用代码中真实存在的方法"。好了一阵。然后又加了两句——现在你的 prompt 已经变成十五条规定了,但只要任务稍微复杂一点,它还是会编一个方法出来。

关键问题没人告诉你:改写 prompt 是在用词汇问题的方式解决结构问题。

prompt 不是一份合同,模型读一遍就遵守。它是模型在推理你真实任务时需要同时放在工作记忆里的东西。一个扁平的十五条规定是不可持续的。任务越难,模型越把注意力放在代码上,然后悄悄丢掉那条不是时时刻刻都在嘴边上的规则。"不要编造方法"通常是第 11 条。压力大的时候,它就掉了。

你是无法用更多的文字打赢这场仗的。第十六条规则只是给它多一条可以丢掉的东西。

真正的原因:结构问题,不是措辞问题

agent 编造方法是因为 prompt 的结构里没有任何东西要求它去核对。你告诉它不要做什么。但你从来没改变它实际一步步在做什么。

所以别再禁止坏事发生了。把机会本身去掉。

与其放一条它需要记住的规则,不如把"落地"做成它必须执行的步骤。

之前——一堆规则:

你是专家工程师。写干净的代码。
遵守规范。不要编造函数。
只用存在的方法。处理错误。
不要留 TODO。写测试。……

之后——一个有序的流程:

1. 首先,列出你计划调用的所有方法或 API。
对于每一个,引用它被定义的文件名和行号。

  1. 如果你找不到某个东西在哪里定义的,停下来告诉我——不要写使用它的代码。
  2. 只有当这个列表完整了,才开始写代码,只使用你在第 1 步中落地的那些方法。

同一套模型。没有新增任何"不要幻觉"的规则。但现在 agent 不可能编造 getProfileById() 了——因为结构要求它必须先找到真实的方法,才被允许写调用。而如果这个方法真的不存在,第 2 步会强制它说出来,而不是在那里瞎猜。

为什么这样能持久,而改写 prompt 不行

这才是关键。

当你改写 prompt 的时候,你只是在修补一个实例——这个文件里的这个编造的方法。下一个会以略微不同的形态漏过去。

当你改变结构的时候,你关闭了整一类问题:每个文件里的每个编造的方法,因为模型现在不可能绕过"落地"这个步骤就到达"写调用"这一步。你没有修症状。你去掉的是原因。

真正的 prompt 修复测试是这样的:同样的错误会不会换一种说法又回来?如果回来了,你只是修补了措辞。如果没有回来,你修复了结构。

(顺带说一句,因为原理一样:这也是为什么把 prompt 硬塞进 JSON schema 通常会降低质量。当你让模型填字段的时候,它停止了推理,开始走表单流程。用散文推理,用有序流程思考;严格的 JSON 只留在最后交接的时候,在思考完成之后。)

下一个 prompt 的检查清单

少禁止,多结构。每一条"不要做 X"都是模型可能丢掉的规则。把它变成它必须执行的步骤。
让验证成为步骤,而不是期望。"引用在哪里定义的"比"使用真实的方法"有效得多。
把落地前置。读在写之前——让模型在生成之前先收集真实的事实。
当它无法落地某样东西时,应该停下来问。一个问题比一个自信的错误答案便宜得多。

做到这四点,大部分"自信地错"的问题就消失了——不需要加任何额外的规则。