同一个需求让 AI 跑三遍再挑一份,到底什么时候才划算

2026-07-29

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

**大多数人跑三份方案是因为第一份不满意,但真正决定跑三份有没有价值的,不是你满不满意,而是这个任务的输出分布够不够散、判定标准够不够硬。**这两个条件缺一个,多跑几份就只是把同一种错误复制三遍,再花时间从三份里选一份错的。我见过太多团队把「一次没做对」直接归因成模型手气不好,于是加大并发、换模型、反复重开会话,最后账单涨了,代码还是那个样子。归因错了,后面所有动作都白做。

这篇只谈同一个任务并行产出多份候选、再按统一口径选一份的做法。站内另外两篇是不同层面的事:Agent 效果评测方法 讲的是长期怎么度量一个 Agent 的能力基线,属于版本之间的横向比较;多模型 fallback 设计 讲的是主力模型不可用时怎么自动切换,属于可用性兜底。本篇夹在中间——同一次任务里、同一个时刻、多份候选之间怎么选。

一、先分清:你要的是多跑几份,还是重试一次

这两件事经常被混为一谈,但处置动作完全相反。

重试针对的是偶发失败:工具调用超时、返回结构被截断、某一步网络抖动。这类失败重跑一次大概率就好了,跑三份是浪费。

多方案针对的是输出分布本身很散:同一个需求存在多条合理路径,模型每次会落在不同路径上,而这些路径之间的优劣需要看到实物才判断得出来。典型的是「这个模块该拆成几层」「异常这里是抛还是返回」,你脑子里没有唯一答案,看到三份实现才知道自己想要哪种。

还有第三种情况最容易被误判:任务描述含糊。这时候三份候选会各错各的,而且错法五花八门。表面上看输出很散,符合「值得跑三份」的特征,实际上散的是需求理解而不是实现路径。这种散度是负资产,跑得越多你越难选。

判别方法很直接:把三份候选并排看,问自己一句「它们理解的是不是同一个需求」。如果三份在做不同的事,先回去补需求,别选。

二、现象到成因的判别表

现象大概率成因怎么验证处置动作
三份候选高度雷同,diff 差几行该任务在模型眼里只有一条路径,采样多样性接近零对三份跑 git diff --stat,看改动文件集合与行数是否几乎一致停止加份数,改为换模型或换切入角度重跑一轮
三份各做各的,改的文件都不一样需求描述含糊,缺少验收标准逐份写一句「它以为你要什么」,三句话对不上就是需求问题全部作废,先补验收条件和边界,再跑一份即可
三份都能编译,但测试全红上下文缺关键信息,比如接口签名、字段含义或既有代码约定没进上下文你自己只拿这份上下文写十行验证代码,如果你也写不对,那就是上下文缺而不是模型笨补上下文再跑,不要靠份数堆
有一份特别漂亮但改动面积巨大模型顺手重构,越界改动看 diff 中与需求无关的文件占比越界的直接淘汰,或把范围约束写进任务再重跑
每份都说自己通过了测试汇报与实际不符,或测试被改宽自己在干净环境跑一遍测试,并 diff 测试文件是否被动过参考 测试被改成永远通过怎么办 的排查路子
跑到一半几份互相覆盖文件共用同一个工作区看是否出现自己没写过的中间态文件隔离到独立 worktree 再跑
单次调用报 429 或 401这不是方案质量问题,是接入层问题看返回状态码而不是看内容按接入层排查处理,与多方案无关

表里最后一行是提醒:并发一上来,接入层的错误会被误读成「模型不行」。看到 429 就是限流,看到 401 就是凭证,别往质量上归因。

三、哪些任务跑三份真的划算

我的判断标准是三条同时成立,缺一条就别跑。

**第一,存在多条合理解法,且优劣要看到实物才判断得出。**接口设计、数据结构选型、复杂状态机的拆法、一段有多种边界处理策略的逻辑,都属于这类。反过来,改个字段名、加一条日志、按既定模式补一个 CRUD,这些任务的正确答案是唯一的,跑三份只会得到三份一样的东西。

**第二,判定成本远低于生成成本。**这是最容易被忽略的一条。如果有测试、有 lint、有类型检查,机器几秒钟就能淘汰掉两份,那么多方案的边际成本几乎只有生成部分。如果三份都得你逐行读三十分钟才知道哪个好,那你的时间才是瓶颈,跑三份等于给自己派三倍的阅读量。

**第三,返工代价高。**这段代码要活很久、被很多地方依赖、改起来会牵一大片,那么前期多花一点选一个好结构是值得的。一次性脚本不配拥有三份候选。

成本这一侧要算的不只是生成费用。并行几个会话同时跑,额度消耗、上下文占用、你的注意力都在同步烧。如果你还没有对日常消耗建立感知,先把 Agent 成本失控的排查 那套做起来,再谈并行。

顺带说一句多样性来源:有人喜欢用不同厂商的模型来拉开候选之间的差异,思路本身没问题。但要清楚部分海外服务官方对中国大陆有区域限制、不支持直连,市面上确实存在第三方中转,我不做任何推荐,也不评估其稳定性与合规性。至少要意识到,接入方式不同会引入额外的失败面,把这部分失败算进你的判别流程里。

四、评分口径:先定否决项,再定加权项

口径必须在看到候选之前定好并落盘。这不是形式主义——人看到具体代码之后,标准会不自觉地向着自己已经读顺的那一份漂移,尤其是写得流畅、注释齐全的那份。

我的做法是分两层。

**第一层是否决项,二元判定,机器执行,不给分只给过或不过。**典型的几条:能否编译或通过类型检查;既有测试是否全绿;改动是否越出约定范围(比如动了不该动的目录);是否新增了未经批准的依赖;是否留下调试残留。这一层能刷掉大部分候选,而且不需要你参与。

落地上就是一个薄脚本,对每个候选跑同一套命令,把结果收成一张表。有一点要先说死:别在同一个工作目录里来回 checkout 切分支来跑,切换过程本身会打乱构建产物和依赖目录,前一份留下的中间态会影响后一份的测试结果,跑出来的三行数据根本不可比。候选必须各自待在独立工作区,隔离怎么开在第五节。

# 三个候选分别位于 ../work-a ../work-b ../work-c 三个独立工作区
# npm test 换成你项目实际的测试命令
for d in ../work-a ../work-b ../work-c; do
  echo -n "$(basename "$d") "
  if (cd "$d" && npm test) >/dev/null 2>&1; then echo -n "test:pass "; else echo -n "test:FAIL "; fi
  git -C "$d" diff --stat main -- . | tail -n 1
done

输出是三行「候选名 + 测试结论 + 改动规模」。第一层的价值就在这三行:没过测试的直接出局,改动规模离谱的先打问号,剩下的才轮到你读。

**第二层是加权项,只用于活过第一层的候选,也只覆盖机器判不了的维度。**我常用五个维度:与既有代码约定的一致性、边界与错误路径的处理是否完整、改动面积是否克制、可读性、扩展点是否留得合理。每个维度给一到五分,权重按项目实际情况定。关键是维度和权重写在文件里,每次照着打,不要临场发挥。

如果你想让模型来打这一层的分,有三个动作必须做,否则分数没有参考价值:把候选的来源标识去掉,让评判方不知道哪份是谁写的;每次打分都把候选顺序随机打乱,否则排在前面的那份天然占便宜;强制按维度逐项给分并附一句理由,不要问「哪个更好」这种整体性问题——整体性提问会让评判方被篇幅和措辞牵着走,长的、注释多的那份容易赢。

还有一条底线:模型给出的分数是筛选辅助,不是决策。最终采纳哪份由你签字,因为出了问题背锅的是你。把人放在不可省略的那一环上,这条在任何自动化程度下都不该松。

五、什么时候别再折腾:止损点与回滚点

我给自己定了几条硬线,触发就停手,不再加份数。

**止损线一:三份全废就不许再加份数。**三份候选全部没过否决项,说明问题不在采样,在输入。此时跑第四份、第五份的期望收益接近零。正确动作是回到需求和上下文,把缺的东西补上,然后只跑一份。

**止损线二:候选之间差异小于某个程度就换路。**如果三份 diff 几乎重合,说明模型对这个任务只有一种模式,你要的多样性根本没产生。继续跑是重复付费。换路的选项有三个:换一个模型来源、把任务换个角度描述(比如从「实现这个功能」改成「先给出三种实现取舍」)、或者你自己写骨架让模型填。

**止损线三:你已经读了两轮还选不出来。**这通常意味着候选之间的差别对你来说不重要,或者你的验收标准里少了真正在意的那一条。停下来,把「我到底在意什么」写成一句话,很多时候写完就知道选哪个了。

**回滚点的准备要在开跑之前做完。**每份候选必须落在独立分支或独立工作区,主干全程保持干净,这样任何一份都可以整份丢弃而不留痕迹。用 worktree 做隔离的具体操作在 用 worktree 并行跑多个任务 里讲过,多方案场景直接复用那套即可。

git worktree add ../work-a -b cand-a
git worktree add ../work-b -b cand-b
git worktree add ../work-c -b cand-c
# 选定之后
git worktree remove ../work-b --force
git branch -D cand-b

选定一份之后,另外两份要立刻删干净。留着「以后可能有用」的分支,下次有人基于它继续开发,就会引入一份没人评审过的实现。

六、避坑清单

**看到结果再定标准。**会踩是因为人有强烈的事后合理化倾向,读顺了的那份自然显得更好,你会不知不觉调整权重去迁就它。避法是把评分表写成文件并先提交,跑完只填分不改表。

**同一个模型既生成又评判,还知道哪份是自己的。**会踩是因为这套流程看起来很省事,一个会话全包了。问题是评判方对自己的产出有偏好,对靠前的候选也有偏好。避法是去掉来源标识、打乱顺序、按维度逐项打分。

**三份跑在同一个工作区。**会踩是因为图省事没做隔离,尤其是用同一个编辑器窗口切来切去的时候。结果是几份互相覆盖文件,最后 diff 里出现谁都没写过的中间态。避法是开跑前就 worktree 隔离,一份一个目录。

**只看 diff 不跑测试。**会踩是因为读代码有种「我看懂了所以它是对的」的错觉,而写得漂亮的那份最容易骗过阅读。避法是把机器门放在人工评审之前,没过门的根本不给你看。

**把多方案当成需求含糊的兜底。**会踩是因为需求没想清楚时,人会本能地希望「多试几个总有一个对」。实际结果是三份错三样,你还得挨个读完才发现全错。避法是先写验收条件,写不出来就说明还不到开跑的时候。

**从三份里东拼西凑一份新的。**会踩是因为每份都有一两个亮点,拼起来看着最优。问题是拼出来的第四种方案没有任何一次完整验证覆盖过它,接缝处最容易出问题。避法是要么整份采纳,要么把你想要的那几点写成约束条件重跑一份完整的。

**忘了给这一轮设时钟。**会踩是因为并行跑的时候等待感不强,你会一边等一边刷别的,不知不觉一上午过去。避法是开跑前写一句「这轮最多到几点,到点没结论就按第一层分数最高的那份走」。

**用多方案掩盖模型在这个任务上确实不行。**会踩是因为不愿承认某类任务超出了当前工具的能力边界。如果同一类任务连续几次三份全废,那不是运气问题,是任务类型的问题,该自己写就自己写。判断依据很简单:把最近几次的失败记录摊开看,如果失败点集中在同一类逻辑上,那就是能力边界而不是运气。

收尾

多方案生成加评判是一个有明确适用边界的工程手段,不是提升质量的通用开关。它在「解法多、判定便宜、返工贵」的任务上回报明显,在其余任务上就是三倍浪费。真正让它跑得动的是前置的判定能力——没有能自动跑的测试和检查,多方案就退化成让你读三倍的代码。

开跑之前过一遍这几条:

  • 这个任务真有多条合理解法吗,还是答案唯一
  • 我有没有一条能机器执行的否决线,能自动刷掉不合格候选
  • 评分表写下来了吗,是不是在看到结果之前写的
  • 三份是不是各自隔离,主干干净,任何一份都能整份丢弃
  • 这轮的止损点是什么,到什么条件我就停手回去补需求
  • 选定之后,没用的分支和工作区会不会被立刻清掉

六条里有两条答不上来,就别开三个会话,老老实实跑一份,把省下来的时间花在写清楚需求上。

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