AI 写出来的东西总跑偏?多半是需求没问清就让它动了手

2026-07-29

数据截至 2026-07,各产品的额度与报错口径以官方最新说明为准。

大部分人把「AI 写出来的东西不对」归因成模型不够聪明或者那段指令写得不好,真正的原因通常在更前面一步:需求进入模型的时候本来就是模糊的,模型只是把这份模糊如实展开成了代码。 模型不会因为信息不够就停下来,它会补全。补全出来的东西语法通顺、结构完整、看着像那么回事,于是你在评审阶段才发现它假设了一堆你没同意过的前提。这不是幻觉,是信息缺口被默认值填上了。

这件事和另外两件事容易混。需求已经想清楚了,要把它写成机器和人都能执行的规格,那是规格驱动开发在管的事;东西已经产出来了,要判断它算不算交付合格,那是验收标准在管的事。本篇卡在这两者中间偏前的位置:需求还没成型、你自己也只有一个大概方向的时候,怎么把它从模糊逼到可执行,以及这条路上哪些坑会让你白干三轮。

一、先分因:四类现象对应四种不同的成因

返工发生的时候,先别急着重写指令。同样是「结果不对」,成因不同,动作完全不同。

第一类是你自己也没想清。表现是你看到产出物才知道自己不想要什么,但让你说出想要什么,你还是说不上来。这类最普遍,也最容易被误判成模型的问题。判别方法很直接:把产出物里让你不舒服的那处指出来,然后问自己「正确的应该是什么」——如果你要想超过半分钟,说明缺口在你这边。

第二类是它不肯问。你其实心里有明确的边界,但它一句都没确认就开写了。判别方法是回看整段交互,看它有没有提出过任何一个澄清性的问题。一个都没有,说明它进入了执行模式,把不确定项默认掉了。

第三类是上下文缺了一块。你说清楚了,它也理解了,但它看不到那份决定性的东西——既有的数据结构、上游接口的真实返回、团队约定的错误处理方式。表现是产出物本身逻辑自洽,一放进现有代码库就处处不合。

第四类是目标中途漂了。前几轮还对,聊到第五轮开始偏,越改越远。这类通常伴随对话变长、你自己也记不清最初的约定是什么,具体机制见目标漂移那篇。

把这四类摆到一张表里,排查顺序从上到下:

现象大概率成因怎么验证处置动作
产出物完整但方向不对,你说不清正确答案需求在你这边就是模糊的让它反过来问你 5 个问题,数一下你答不上来的有几个,2 个以上即命中停止生成,先做澄清问答,把答案落成文字再重启
它一个问题没问就直接开写交互进入了执行模式,不确定项被默认填充回看整段对话,统计澄清性提问数量为 0明确要求它先只提问不写代码,直到你说开始
逻辑自洽但和现有代码处处不合关键上下文没进去让它复述它认为的数据结构和调用约定,对照真实代码补喂真实文件片段与接口返回样例,而不是口头描述
前几轮对、越往后越偏目标漂移,早期约定被稀释让它复述当前目标与三条约束,对照你最初写的开新会话,只带定稿的需求文字重来
它把没要求的地方也改了改动范围没有约定git diff --stat 看改动文件数是否超出预期回滚,重新划定可改文件白名单,见下文
你改一句它推翻一片,反复循环需求内部本身自相矛盾把两条你提过的要求并排读,看是否互斥停手,人来做取舍决策,模型不该替你选

这张表的用法是从上往下走,第一条命中就先处理第一条,不要跳。跳过第一条直接去补上下文,是最常见的浪费方式:你把一堆文件喂进去,它把错误的方向做得更完整了。

二、这个环节 AI 能帮到哪一步,哪一步必须人来定

先把分工说死,后面的动作才有依据。

AI 在需求澄清阶段真正有用的能力有三个。一是穷举维度:你想到了主流程,它能把边界条件、并发情况、失败路径、权限差异这些容易漏的维度列出来问你。人在自己熟悉的领域反而容易漏,因为熟悉带来默认。二是发现矛盾:把你零散说的几条要求摆在一起,它能指出哪两条不能同时成立,这一点比人自查可靠。三是把口语转成可判定的句子:你说「响应要快」,它能追问是端到端还是服务端、是均值还是分位、超过多少算不合格——这一步是从模糊到可验收的关键跨越。

必须人来定的也有三个,交给模型就是灾难。第一是取舍:一致性和可用性冲突时选哪个,是业务判断不是技术判断,模型会给你一个折中方案,而折中方案往往两头不讨好。第二是范围:这一版做到哪里为止,剩下的留给下一版。模型的默认倾向是做全,它不知道你下周要上线。第三是代价接受度:某个方案会带来后续维护负担,愿不愿意承担是你的事。

分工不清带来的典型后果是:你把取舍问题也丢给它,它给了一个看起来周全的答案,你没意识到那是它编的默认值,等到上线才发现和实际业务对不上。所以我的做法是,凡是模型给出的答案里带「建议」「通常」「推荐」这类词的地方,都要停下来自己确认一遍——那往往就是它在替你做决定。

三、可执行的做法:把它从答题模式切到提问模式

模型的默认姿态是答题。你给一段描述,它给一段代码,这是训练出来的行为。要让它先问,需要显式改变这个姿态,而且要给约束,否则它会问二十个不痛不痒的问题。

我用的动作分四步,每步都有对应的验收。

第一步,先禁止产出。 开场就把话说死:这一轮不要写任何代码,只列出你需要我确认的问题。数量控制在 5 到 8 个,按对最终结果影响从大到小排。验收动作:看它第一轮回复里有没有代码块,有就重来一次,别姑息。看问题排序是否真的按影响度排,如果第一个问题是「用什么命名风格」,说明它没理解什么叫影响大,需要提醒它优先问会导致整体推翻的那些。

第二步,逼出非目标。 澄清问答做完之后,让它写出「我理解这次不做的事情有哪些」,列 5 条以上。这一步的价值高于列做什么。做什么你自己心里有,不做什么往往是你没意识到自己默认排除了的东西。验收动作:逐条读这 5 条,如果有一条你看了心里一紧、觉得「这个其实要做」,恭喜,你刚捞回一次返工。

第三步,把答案落成文字,脱离对话。 澄清的结论必须写进一个文件,不能留在对话历史里。对话会漂,文件不会。文件里至少三块:要解决的问题一句话、约束条件列表、明确不做的事。写完之后新开一个会话,只带这个文件重新开始。验收动作:新会话里第一句先让它复述这个文件的核心约束,复述不全说明文件本身写得不够硬,回去改文件而不是改指令。

第四步,划改动边界。 开写之前约定可以碰哪些文件、不能碰哪些。这一步做不做,直接决定你后面 review 的痛苦程度,展开逻辑见改动范围失控验收动作:产出后先看统计,不看内容:

git diff --stat
git status --short

文件数超出约定,先不读代码,直接问它为什么动了这些文件。多数时候答案是「顺便优化了一下」,这类顺便是返工的主要来源之一。

四步里最容易被跳过的是第三步。跳过的理由通常是「都聊清楚了何必再写一遍」,代价是三天后你想不起当初为什么定了那条约束,然后在第二轮开发里把它推翻。

四、什么情况下别再折腾了

澄清这件事有边际效益递减,甚至会变成负收益。下面几个信号出现,就该停手换路。

信号一:同一处反复改三轮仍不对。 第一轮不对是正常的,第二轮不对说明你的描述有歧义,第三轮还不对基本可以判定为需求内部有矛盾,或者你要的东西超出了当前上下文能承载的复杂度。继续改只会消耗额度并把上下文搅浑。此时的动作是回滚到最后一个干净点,人来把矛盾那条捋直。三轮的产物里往往有一两段还想留着参考,所以先整体收起来再说:

git stash push -u -m "clarify-round3-废弃"

push -u 会把新建但还没被跟踪的文件一并收进去,这一点很关键——AI 这三轮里大概率新建过文件,不加 -u 它们会被留在工作区,你以为回到干净状态了,其实没有。收完用 git status --short 确认输出为空。想找回其中某一段,git stash show -p stash@{0} 看内容,git stash pop 整体恢复。真的确认一点都不要,再单独清掉,不必在同一步里既留档又丢弃。

信号二:你开始在指令里写实现细节。 当你发现自己在写「用一个哈希表存中间结果,然后在第三步之前判空」的时候,说明你已经想清楚了,此时打字描述给它听的成本大于自己写。转成人写主干、AI 补细节更划算。

信号三:它开始重复道歉并给出几乎相同的方案。 这是典型的思维循环,模型已经陷在自己的上下文里出不来,具体识别方法在思维循环那篇讲得更细。此时任何追加说明都没用,唯一有效的动作是丢弃当前会话,从定稿文件重开。

信号四:澄清问答本身超过了两轮。 第一轮它问、你答,第二轮它就应该能给出一个你认可的理解复述。如果第三轮还在问基础性问题,说明你给的初始材料太少,或者这个需求本身就该先做一次人和人之间的对齐——那不是模型能替代的环节。

回滚点的设置是这几件事里成本最低、收益最高的一个。开始澄清之前先建一个分支,再给当前这个提交打一个自己看得懂的标记,任何时候判定跑偏都能一步退回:

git checkout -b feat/clarify-round1
git tag clarify-start

这里用打标记而不是先提交一次,是因为工作区本来就是干净的,git commit -am 在没有改动时会直接以「nothing to commit」退出,什么也不会留下。标记指向的是当前这个已存在的提交,不需要产生新提交就能作为退回坐标。后面任何时候想退回,git reset --hard clarify-start 一步到位——这条命令会丢弃工作区里未提交的改动,执行前先确认该留的东西已经提交或已经 stash。

有了这个点,你才敢放手让它试,也才敢在第三轮果断放弃。没有这个点,人会因为舍不得已经改的东西而在错误方向上继续投入,这是沉没成本在作祟,和技术无关。

五、避坑清单

坑一:让它一次问二十个问题。 为什么会踩——你以为问得越多越清楚。实际是问题一多,就会掺进大量无关紧要的细节,你答得烦躁,注意力被稀释,真正致命的那两个问题反而被淹没。怎么避——限定数量并要求按影响度排序,只认真回答前三个,剩下的直接回复「你按常规做法定,做完告诉我你定了什么」。这条要和第二节的分工对上,别放过头:可以扔给它自己定的,只限那些改起来是局部替换的项,命名风格、日志措辞、目录层级这类;凡是牵扯到取舍、范围、后续维护代价的,哪怕排在第八位也得你自己答。判断标准是问一句「它定错了,我改回来要动几处」——只动一处的可以放,要动一片的不能放。

坑二:口头描述现有代码结构。 为什么会踩——你觉得自己描述得挺准,省得贴代码。实际是你记忆里的结构和仓库里的真实结构永远有偏差,字段名、可空性、默认值这些细节尤其容易记错,它按你的描述写,一编译全是错。怎么避——凡是涉及既有代码的地方,贴真实片段,哪怕只贴类型定义那十几行。

坑三:把澄清结论只留在对话里。 为什么会踩——当下聊得顺,觉得没必要重复劳动。实际是对话轮次一多,早期约定的权重会被后来的内容稀释,而你自己也不会去翻上百条历史。怎么避——落成文件,新会话只带文件。

坑四:在同一个会话里既澄清又实现。 为什么会踩——切换会话麻烦,而且觉得上下文连续有好处。实际是澄清阶段会产生大量被否决的中间方案,这些废弃内容留在上下文里,会持续干扰后面的实现,时不时冒出一个你早就否掉的做法。怎么避——澄清和实现分成两个会话,中间隔一个文件。

坑五:把「不做什么」当成可选项。 为什么会踩——列不做的事看起来像形式主义。实际是绝大多数范围失控都源于没有明确的排除项,模型的默认倾向是把它认为相关的都做掉。怎么避——非目标列表当成必填,写不出 5 条说明需求还没想清。

坑六:需求变了却不重写文件。 为什么会踩——中途改主意是常态,口头说一句「刚才那条不算了」感觉就够了。实际是文件和实际约定开始分叉之后,文件就失去了权威性,你下次不敢信它,只好又回到翻对话历史。怎么避——每次变更都回去改文件,改完让它重新复述一遍。

坑七:拿模型的追问当结论。 为什么会踩——它问「是不是应该按用户维度做隔离」,语气笃定,你顺口答「是」。实际上这是它在提供一个默认值,你的「是」只是没反对而已,并不是真的做过判断。怎么避——凡是它给出带倾向性的问法,反手让它把两个选项的代价各写两行,你看完再选。

六、收束

这个环节的核心不难:让模型进入提问姿态,把答案固化成文件,划清改动边界,设好回滚点。难的是忍住不在需求还糊着的时候就让它开写——那种「先跑起来看看」的冲动,在需求清晰时是效率,在需求模糊时是把模糊固化成了几百行代码,后面每一轮修改都要先拆掉它。

一份可以贴在手边的自检清单,开写之前逐条过:

  • 这次要解决的问题,能不能用一句话说清,句子里有没有形容词性的模糊表述
  • 明确不做的事情,写满 5 条了吗,其中有没有一条让你犹豫
  • 关键的既有代码结构,是贴了真实片段还是靠嘴描述的
  • 可以改动的文件范围约定了吗,产出后你打算用什么命令核对
  • 回滚点建了吗,判定跑偏的时候你退得回去吗
  • 澄清结论落进文件了吗,还是只躺在对话历史里
  • 这一轮里有没有哪个决定,其实是模型替你做的取舍

七条里有两条答不上来,就先别开写。这几分钟省下来的,通常是后面半天的返工。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。