我埋了 3 个 bug 让 AI 审
同一个 Claude,换三种问法审同一段代码,各跑 10 次,结果差很多。下面是三套提示词,还有那段埋了 bug 的代码,复制过去就能自己试。
那段埋了 bug 的代码
一个聚餐 AA 分账的小函数:输入账单、小费、名单和买单的人,算出每个人该转多少钱。我埋了三个 bug:名单上最后一个人不用付钱;每人先四舍五入,零头对不上;名单里有两个同名的人只收一份。
// 聚餐 AA:算出每个人该转给付款人多少钱
function splitBill(total, tipPercent, people, payer) {
const tip = total * tipPercent / 100;
const share = Math.round((total + tip) / people.length * 100) / 100;
const owes = {};
for (let i = 0; i < people.length - 1; i++) {
const name = people[i];
if (name !== payer) {
owes[name] = share;
}
}
return owes;
}
方法一:随口问
帮我看看这段代码有没有问题? (贴代码)
- 10 次里 8 次三个 bug 都找到了(Opus 5.5 五次全中,Haiku 5.5 漏了两次「同名」)。
- 但 Opus 一次给 6~9 条意见,真会把钱算错的只有 3 条,剩下是「加个检查」「写得更优雅」;有 4 次还说空名单会算出 NaN,真跑一下其实不会。
方法二:给规矩(REVIEW.md 的写法)
Claude Code 团队会给 AI 审查员写一份 REVIEW.md:在这个项目里什么叫出错、哪些不用报、每条要拿出什么证据。括号里换成你自己的。
你是代码审查员。这段代码是:(一句话说清它是干什么的)。 在这里,「出错」的意思是:(比如:有人少付或多付了钱 / 页面显示的数字不对 / 文件被删了)。 规则: - 只报会让结果出错的问题。代码风格、命名、注释、「可以写得更优雅」一律不报。 - 每个问题都要给:在第几行;一组具体的输入;按现在的代码会得到什么、正确应该是什么。给不出具体输入的,不报。 - 最后一行写「共 N 个问题」。没有问题就直接说没有问题。 代码: (贴在这里)
- 效果:每次只报 2~3 条,没有一句废话,也没有说错的。
- 坑:「同名」这个 bug 10 次只抓到 1 次。规矩写得越死,它越不往外多想一步。
方法三:几个 AI 一起审,再投票
照 Claude Code 团队审代码的思路做的缩小版:开 3 个新对话,各自用「审查员」提示词找 bug;每条意见附的例子你真跑一遍;再把结果交给另外 3 个新对话用「投票」提示词判断,过半数说是才留下。
你是代码审查员。这段代码是:(一句话说清它是干什么的)。 找出会让结果出错的 bug(在这里「出错」是指:……)。多想想各种真实会遇到的输入:空的、重复的、特别大的、从网页输入框读进来的。风格、命名、「可以写得更好」不报。 每个 bug 必须附一个能直接运行的例子,并写出正确结果应该是什么。 代码: (贴在这里)
下面是一段代码、一条审查意见,以及把审查员给的例子真跑一遍得到的结果。 判断这条意见说的是不是真 bug(会让结果出错)。只回答:是 / 不是,再加一句理由。 代码: (贴在这里) 意见:(审查员的那一条) 例子:(它给的例子) 真跑的结果:(你跑出来的结果) 审查员说正确应该是:(它写的正确结果)
- 10 次全部三个 bug 一个不漏;「1.005 会舍错半分钱」这类站不住的意见,大多被投成 0 票。
- Opus 5.5 五次都多找到一个我没埋的:金额从网页输入框读进来是文字,「100」加 10 块小费变成「10010」,三个人每人要付 3336.67。
- 投票只看跑出来的结果,例子没选好的时候,对的意见也会被投掉一次,所以审查员要多开几个。
- 我用的是 Claude Opus 5.5 和 Claude Haiku 5.5,默认推理设置;Haiku 便宜很多,用方法三也能三个全抓到。