今天我们来聊聊如何审核 AI 的代码。现在用 AI 写代码越来越普遍了,可到底怎么审,大家一直都还没有一个统一的说法。一行一行看吧,根本看不过来,AI 分分钟就可以给你写出几千行代码;全部看完呢,要花费大量的时间。不看吧,又不放心,谁知道 AI 写东西是不是跟你想象的一样的呢?那既然两个极端都不行,要不就走个中庸之道,只审重要的部分。听起来好像可行的样子,可问题就在于,谁知道哪部分重要、哪部分不重要呢?
很多时候啊,问题恰恰就出现在那些看起来不起眼的地方。所以到底该怎么审核 AI 的代码?这个问题到现在也没有一个定论。最近 Anthropic 发了一篇文章,叫做《How the Claude Code team does code review》,它是介绍了 Claude Code 团队是怎么做代码审核的。文章一开头就提到,Claude Code 自身大概 90% 的代码都是用 AI 写的。那这问题就来了:AI 写了这么多代码,他们是怎么保证代码质量的呢?
这个就是这篇文章需要回答的问题。不过需要留意的一点是,虽然文章标题讲的是代码审核,但它介绍的内容其实远远不止代码审核这么简单。因为代码审核不是一个孤立的环节,它和整个发布流程都是紧密的联系在一起的。所以 Anthropic 在介绍他们在怎么做代码审核的时候,也把整个发布流程都介绍了一遍。下面我就结合我自己的理解,带大家把这个流程从头到尾走一遍,看看 Claude Code 团队到底是怎么做的。
不过在这之前,我们先稍微回顾一下通常一段代码是怎么发布上线的。首先我们要写代码,写完之后呢,要把代码合并到主分支,也就是 main 或者是 master 分支。不过呢这个合并并不是一步到位的,一般呢我们需要先提交一个 PR(Pull Request)。你可以把 PR 理解成这段代码合并到主分支的一个申请。提交到 PR 之后,一般情况下呢后面还会做两类检查:一个是自动检查,比如说是运行一些相关的测试看看代码有没有问题;另外一个呢是审核。
这一步呢一般是让其他的开发者看一下代码写的对不对,有没有一些潜在的风险。等这些检查都通过了之后,代码就可以合并到主分支了。不过合并到主分支呢也并不代表用户马上就能够用到这些代码,通常情况下呢还需要发布这个环节。发布了之后,代码对应的功能才会真正被用户使用到。这个就是传统软件开发过程中一段代码从编写到发布上线的大致流程。
我们可以把这个流程大体分为四个阶段:第一个是 PR 前,也就是提交 PR 之前所发生的事情;第二个是 PR 中,这个是指提交 PR 之后到合并代码之前所发生的事情;第三个是合并时,这个是指合并的时候所发生的事情;第四个是合并后,这个当然是指合并完成之后所发生的事情了。Claude Code 团队的流程呢同样是这四个阶段,大框架没什么变化,变的呢是每个阶段里面具体做的事情好适应现在 AI 写代码的情况。
接下来我们就按照这四个阶段一个一个来看一下,每个阶段里面他们具体是做了什么事情。我们先看第一个阶段 PR 前。PR 前这个阶段呢大致可以分成两个步骤:第一步是确保产品能够正常运行,这一部分我们可以交给 AI 来处理。既然交给 AI,我们就必须要给 AI 一些方法让它能够自己来验证产品是否真的能够正常运行。比如说我们可以给 AI 相关的工具,像是什么运行程序啊、查看网页啊、截图啊、操作电脑之类的。
这样 AI 写完代码之后就可以自己把产品运行起来,并且用相关的工具来检查产品的运转是否正常。所以这一步最重要的地方就在于要让 AI 具备能够验证产品效果的能力,确保能够正常运行之后,第二步就是要检查代码质量了。也就是确认代码本身的编写有没有问题,比如说是是否符合规范、架构是否合理等等。这一步我们也可以让 AI 来检查,那具体该怎么做呢?
有些小伙伴们可能就在想:我们原来不就是在用 AI agent 写代码吗?我们当初把要完成的需求发给它,它根据需求写完了相关代码。它的上下文里面还存着之前的思考和相关的对话记录,这样的话这个 agent 应该是对这个代码知根知底的。那让它检查就再合适不过了,这个想法听起来很自然的样子。不过实际操作下来你就会发现它会遗漏很多问题。
你想这个 AI 本来就知道自己是怎么想的,那它回头检查的时候还是会顺着原来的思路走。这样呢就很容易以为自己已经写对了,那这样的话很多问题就查不出来了呀!所以 Anthropic 采取的办法呢就是再创建一个全新的 AI agent,并且只把目标和相关的代码改动发给它。让这个新的 agent 来判断这些代码能不能完成既定目标,有没有什么潜在的风险。
这么做的好处在于这个 agent 有着一个全新的上下文,它不知道之前写代码的时候发生了什么。这听起来像是一个缺陷,但恰恰就是这种缺陷能够让这个 agent 保持客观不容易遗漏问题。所以检查代码质量的这一步的重点就在于要使用一个新的 agent,因为它有着全新的上下文不包含原来的各种思考和实现过程。这样呢反而更适合审核代码好这个就是 PR 前的两个步骤了:一个呢是确保产品能够正常运行,这一步的重点是让 AI 具备验证产品效果的能力;第二点是检查代码质量,这一步的重点在于使用一个全新的 agent 来检查代码。
接下来是第二个阶段 PR 中。在这个阶段,一个 PR 要先后经过 CI、AI 审核、安全审核和按风险审批这四个环节。其中前三个环节呢都是机器检查,最后一个呢是人工检查。下面我们来一个一个看先看第一个 CI 呢就是每次提交代码之后自动运行的一整套检查,比如说我们可以在这个环节里面做 Lint 检查、类型检查、多平台测试或者是尝试构建一下项目看看有没有什么问题。当然这里面只是举了几个例子,除了这几项之外这个阶段呢还可以有其他非常多的检查基本上那些不需要 AI 而且能够自动跑的检查呢都可以放到这里面。
CI 检查过了之后下一步要做的就是 AI 审核了。AI 审核的过程呢大致可以分成三个步骤,分别是发现问题、筛选问题和处理问题。第一步是发现问题在这一步 AI 会从三个方面来检查:有没有达到目标、跟现有系统合不合得来、会不会影响别的地方。这样查起来就比较全面了发现了问题之后第二步就是筛选问题,简单来说这一步就是筛选掉无关紧要的问题。比如说是代码风格不一致或者是存在冗余代码之类的这类问题一般不太会影响程序的正常运行如果大部分的开发者都觉得无所谓不需要改的话那就可以把它们写成一个筛选规则交给这一步对应筛选的 AI。
这样的话这个 AI 就可以根据给定的规则把这些无关紧要的问题去掉这样这些问题在这一步就会被过滤掉开发者也就不用在他们身上浪费时间了。做完了筛选问题之后第三步自然而然就是处理问题了留下的问题呢会被分成三类分别是重要问题、小问题和已有问题。所谓的已有问题就是说这个问题并不是这次改动所带来的它原来就有不管是哪一类问题每一条问题都必须要回应要么改掉要么写明理由关掉只要是还有问题没有处理这个 PR 就不能够继续走下去。
好这个就是 AI 审核的三个步骤了这三步合在一起其实就是在做一件事情找出 PR 的问题并且处理掉没错就是这么简单那给 AI 审核的具体流程呢我们就讲完了除了介绍这个流程之外 Anthropic 还讲了他们对这个流程的优化方案我稍微总结了一下他们优化主要是围绕三点展开的第一要找出真正的问题第二要少提没用的意见第三审核要能正常结束。下面我们就来挨个看一下我们首先来看第一点:要找出真正的问题既然要找出真正的问题那最好的办法就是拿真正出过的问题来考一考它。
所以 Anthropic 的做法就是用线上问题来做评测然后再用这个评测来优化审核流程的效果具体来说就是每一次出现的线上问题都收集起来然后记下两个东西分别是出现了什么问题以及是哪一个 PR 引入的这两个东西结合起来就可以作为一个完整的案例那好几个案例放在一起就组成了一个评测集下面我们要做的就是使用这个评测集给当前的这个审核流程打个分。比如说我们可以先把案例 1 里面的 PR 拿出来过一遍 AI 审核让 AI 审核找找这个 PR 的问题然后呢我们再把这个案例里面的真实问题拿过来跟 AI 审核找到的问题对比一下看审核流程有没有找到真正的问题如果找到了那就得 1 分没找到的话呢就得 0 分。
之后我们可以使用这个方法给每一个案例打一个分加起来的总分呢我们可以把它叫做基准分。接下来我们对 AI 审核做一些调整比如说是改改提示词啊换换工具啊甚至换换模型之类的然后用同一个评测集再打一次分如果分数提升了就说明这次调整是有效的那对应的修改呢就可以留下来这样有了可以量化的分数用的又都是真实的线上案例我们就能够一步一步稳定的提升 AI 审核的效果。
再来看第二点啊:要少提没用的意见前面的评测只看 AI 审核有没有把真的问题给找出来至于它还报了多少别的问题其实是不怎么管的这样一来 AI 审核报的越多就越容易得分不过报的问题越多没用的意见往往也会越多的话开发者就需要花大量的时间一条一条的去看非常的浪费时间所以啊想要全面提升 AI 审核的效果我们还得确保 AI 审核尽量少提没用的意见那想让它少提意见的话首先就得知道它提的意见里面哪一些是没用的占的比例呢大概是多少。
所以啊 Anthropic 围绕这一点着重做的一件事情就是识别无效意见文章里面提到了两种识别无效意见的方法。第一种呢是看 PR 的作者是怎么处理每条审核意见的 Anthropic 会根据 PR 作者的反馈把 AI 审核给出的每条意见分成四类分别是作者改了、作者说它错了、作者说它是故意这么写的还有一些是作者觉得无所谓。第一类呢是说明意见是有用的不过后面三类呢就是无效意见了这样一统计就知道 AI 审核的意见里面有多少比例是无效的。
第二种呢是拿没有问题的 PR 去测他们会专门挑一些确认没有问题的 PR 拿去做一遍 AI 审核既然这些 PR 本来就没有问题那 AI 审核所提出的意见呢基本上也都是无效的 Anthropic 就用这两种方法来统计 AI 审核的无效意见比例有了这个数字以后每次调整 AI 审核的时候呢就不光要看评测分数有没有提升还要看无效意见呢有没有变少这样才能够全面提升 AI 审核流程的可靠性。
最后来看第三点:审核要能正常结束你可能会比较奇怪审核怎么会结束不了呢?其实有些时候啊 AI 审核可能会没完没了的提意见。比如说 AI 审核先提了一些意见交给写代码的 AI,写代码的 AI 就根据这些意见去修改代码然后把修改好的代码再交给 AI 审核这呢是第一轮。接下来第二轮呢 AI 审核又提了一些新的意见写代码的 AI 又改了一遍再交回去就这样来来回回没完没了。文章里面有个例子有一个 PR 一晚上来回改了 50 多轮为什么会这样呢?
一般情况下原因无非是两种要么是审核流程本身有问题每一轮都能挑出一些新的毛病;要么是写代码的 AI 有问题怎么改都改不对。为了解决这个问题 Anthropic 的做法呢是控制审核轮数具体来说啊他是对审核流程做了几点调整我们一起来看一下。第一个调整啊是超过三轮就需要停下来想一想思路具体来说如果一个 PR 来回改了三轮还没有通过就需要提醒 PR 的作者先停一停不要再一点点改了好好想一想是不是整体思路有问题。
第二点是前几轮之后只改新改动的部分这条可能有点难理解我来稍微解释一下。PR 提交了之后 AI 审核会结合整个项目去看这个 PR 会带来什么影响比如说我们假设一个 PR 改了一个函数在第一轮审核的时候 AI 审核流程不仅会去看这个改动本身有没有问题还会去看项目里面有哪些地方用到了这个函数并且检查这些地方会不会也受到影响。然后呢作为一个综合的评估这样做虽然比较花时间但是检查得非常全面相关的地方都能够查出不容易有疏漏。
就这么审核完了之后 AI 审核会给出它的意见然后呢写代码的 AI 就会根据这些意见去修改代码比如可能在源文件里面多修改一部分内容改完了之后会再交给审核流程下面第二轮审核就开始了。在这一轮审核流程还是会用相同的方式把 PR 的改动和被影响的地方都整体看一遍并且给出新的审核意见这个过程可能会重复好几轮。不过几轮之后审核的方式就发生变化了这个时候写代码的 AI 再改几行审核流程呢就会只看这几行了它不会再去整体看一遍了之前已有的改动呢也会忽略掉。
那为什么后面就只看改动的那几行了呢?如果每一轮都从头看的话几乎每一轮都能够挑出一些新问题但是这些问题大多数并不是这次改出来的而是第一轮的时候就已经在那里了只是因为看的范围大所以每一轮就会又多翻出几个这样一来每一轮都有新的意见审核就会一直停不下来。要想让审核停下来的话我们就必须要把范围收窄后面那几轮呢只看新改的那几行就行。不过这样的话会不会漏掉一些问题呢?其实基本不太会因为前几轮已经把 PR 的改动和它影响到的地方看过好几遍了这样的话大部分的问题都已经找出来了所以不太有可能会漏掉问题。
这个就是第二点的具体做法了,这个做法稍微有些复杂所以我们在这里简单总结一下:前几轮的时候审核流程会把 PR 的改动和它影响到的地方都看一遍;等到后面几轮的时候呢审核流程就会只看新改的那几行。这样的话既不容易漏掉问题审核呢也能停的下来好第二点讲完了我们再来看看第三点是同类问题一次全部指出。比如同一类错误在代码里面出现了好几次 AI 审核呢不会只标出其中的一处而是把这几处一次全部指出来这样后面就能够一次全部改掉不会改完这一处下一轮又被挑出另外一处。
第四点是不提重复意见已经提过的意见呢后面几轮就不要重复再提了不然同一条意见每一轮都出现一次作者就得一遍一遍的去回应。好这就是控制审核轮数的四条规则了那效果怎么样呢?答案是很有效根据 Anthropic 文章给出的数据在用上了上面这四条规则之后他们只需要审一轮就能够通过的 PR 比例从 65% 涨到了 78%。Anthropic 的优化方案呢我们就先讲到这里现在我们回头来看一下啊整个 AI 审核呢我们一共是讲了两块内容一块呢是具体的流程那一块呢是优化方案那 AI 审核就这些内容了。
下面我们来看第三个环节安全审核。安全审核是单独的一轮自动审核专门去检查代码里面有没有安全问题跟 AI 审核一样它找到的问题只要还有一条没有处理 PR 就不能合并。原文呢对这块写的也不是很多所以呢我们就不展开了大家知道这里面有这么一道关卡就行然后我们再看最后一个环节按风险审批。
大家想一下就是改一个文档里面的错别字和改计费相关的功能那风险显然是不一样的需要的审批策略也不一样。所以 Anthropic 按风险把改动分成了三档:第一档是低风险,比如说是改文档、改文案或者是修改一些只有内部员工才能够用到的功能。对于这类改动只要是前面的自动审查通过了就不需要人去批准了。第二档呢是中风险,比如说是普通的产品改动或者是涉及缓存、自动更新这些比较敏感的地方。
这些改动呢需要一个人来批准。第三档呢是高风险,也就是风险最高的那些代码。这些代码呢需要两个人来批准以便能够保障稳定性好 PR 中这个阶段呢就讲到这里了整体回忆一下 PR 中有四个环节分别是 CI、AI 审核、安全审核和按风险审批。一个 PR 经过了这四个环节之后就可以准备合进主分支了这样的话我们就来到了第三个阶段合并时。在这个阶段有两个东西比较重要:第一个是主分支一般就是 main 或者是 master 分支这个大家应该都比较熟悉了;第二个呢是合并队列。
准备合并的 PR 一般不会直接合进主分支而是会先进入到合并队列里面排好队
每次轮到一个 PR 的时候,系统就会把它和最新的主分支合在一起,再跑一遍测试。如果说测试通过,这个 PR 才会真正合进主分支里;下一个 PR 也是一样,只不过这一次跟它合在一起的是已经包含了上一个 PR 的主分支。测试通过之后,第二个 PR 也合了进去。这样做的好处就是每个 PR 都是在最新的主分支上测过的。有些时候,一个 PR 单独测试没有问题,但是一旦和最新的主分支合在一起,就会出现测试未通过的情况。我们现在所展示的这种合并方法,就可以把这些有问题的 PR 拦下来退回给作者,从而保证主分支始终都能够正常运行。
那合并时讲完了,最后一个阶段就是合并后。代码进入到了主分支,那接下来要做的就是让它能够安全地到达用户的手里。这里啊一共是有三件事情要做,分别是设置功能开关、逐步上线还有观察和回滚。先说设置功能开关啊,新功能的代码虽然已经发出去了,但会先藏在一个功能开关的后面。这个开关一开始只对 Anthropic 自己的员工打开,普通用户还用不了;等内部员工用了一段时间确实没有问题了,才会把开关对所有的用户打开。
那为什么先给内部员工使用呢?因为 Anthropic 的员工每天都在大量使用 Claude Code,很多问题在普通用户碰到之前就已经被他们发现并解决了。所以说等功能真正到了用户手里的时候,就已经是一个比较稳定的状态了。再说逐步上线啊,Claude Code 有两个发布渠道:latest 是最新版,stable 是稳定版。新版本会先发到 latest 让喜欢尝鲜的用户用起来;然后过一段时间,一般是一个周左右的时候,Claude Code 团队确认这个版本没有什么大问题了,才会把它推送到 stable 渠道上。
最后是观察和回滚,也就是尽快发现、尽快撤回。如果上线之后出了问题,一般有两种处理方法:一种呢是关闭开关。前面说过新功能上线的时候大多数是带着功能开关的,所以如果出现了问题我们可以直接远程关闭开关,这个呢是最快的修复方案。第二种呢是重新发布:当开关解决不了的时候我们就需要重新构建一个没有问题的版本,然后发布上线。
好,四个阶段讲完了,我们回头看一下:PR 前有确保正常运行、检查代码质量;PR 中有 CI、AI 审核、安全审核和按风险审批;合并时呢有合并队列;合并后有设置功能开关、逐步上线还有观察和回滚这几个功能。我们来做个假设,假如一个改动里面藏着一个 bug,我们看一看它要闯过多少的关才能够真正跑到用户手里。
首先是在 PR 前这个阶段,AI 会先跑一遍测试确保产品能够正常运行,然后再开一个全新的 agent 检查代码质量。如果这两步都没有发现的话,那到了 PR 中这个阶段 CI 会把几十项检查跑一遍。如果 CI 没有拦住的话,还有 AI 审核;AI 审核也没有发现的话后面还有安全审核。接着呢还要按风险审批,如果改的是重要代码那还得有人亲自来看一看。
就算这些都过了到了合并时,合并队列还会在最新的主分支上再测一遍把那些和别人改动合在一起才会出现的 bug 给拦下来。要是这一步也没有拦下来的话到了合并后,首先会设置功能开关先对每天大量使用 Claude Code 的内部员工开放。很多问题呢在这个阶段就会被暴露出来,如果内部使用也没有发现的话接下来还会逐步上线:先发布到 latest 渠道用一段时间确认没有问题之后,再推送给 stable 渠道的用户。
哪怕这个 bug 一路漏到了用户手里最后呢还有观察和回滚,团队呢会持续观察运行情况一旦发现问题马上就能够关掉功能开关。如果开关解决不了的话我们还可以通过回滚来处理。走完这一圈啊你会发现,在这些关卡里面其实没有哪一道是绝对完美的,单看任何一步的话都有可能会漏掉问题。但是把它们串在一起层层把关,一个 bug 想一路混到用户的手里就非常难了。
而且你看啊这些关卡里面除了重要的代码需要人来审批之外其他几乎都是机器和 AI 在自动完成。所以看完全文我的感受就是他们设计的这一整套流程其实都是围绕同一个目标那就是在保证产品质量的前提下尽量减少人的参与。毕竟无论怎样,人的时间和注意力才是最宝贵的东西。好既然人的时间和注意力如此宝贵那它们花在哪里才最合适呢?换句话说在整个流程里面人最需要做的到底是什么呢。
这个文章里面列举了五点我们来挨个看一下:第一点判断哪些事该做,像是产品的方向啊、品味啊还有功能的范围啊这些东西都是机器判断不了的还是得人来做决策。第二点审核高风险代码,比如说是计费、自动更新还有一些 CI 的配置这些地方一旦是出现问题影响就非常大了所以呢还是得有人亲自盯一下才行。第三点把关架构设计,架构这个东西啊一旦定下来就像是给后面的代码立了一个样板以后不管是人还是 AI 在写类似的功能的时候呢都会照着它来写。
如果这个样板本身就定错了那这个错误就会被照抄到一处又一处很快就能蔓延开来。所以啊这种会被别人照着写的架构改动必须由人来把关。第四点阅读相关的证据,以前审核的时候啊人要看的是每一行代码但是现在主要看的是相关的证据。比如说是什么测试的输出啊、运行的命令啊、返回的结果啊、产品的截图啊还有 AI 的发现啊之类的。人要做的就是看这些证据够不够充分然后呢再根据这些证据决定下一步要做什么。
第五点为结果负责,现在代码虽然都是 AI 写的但是呢不管代码是谁写的一旦发布上线肯定都是要有一个人为它负责的。AI 肯定不能帮人来背锅嘛!好到这里整套流程呢我们就讲完了,最后我再随便聊几句。我记得去年的时候很多人还在讨论 AI 写代码到底靠不靠谱,很多人当时还觉得 AI 写出来的代码基本都是垃圾真正代码还是得靠人来写。但是到了今年这样的声音已经少很多了因为 AI 写代码的能力确实一天比一天强。
如果你还在坚持用古法编程的话你是很难跟那些用 AI 写代码的人竞争的。在这种情况下大家发现写代码不难了真正让人头疼的变成了另外一个问题那就是该如何审核 AI 的代码,如何能够保证 AI 写出来的产品质量是符合预期的。Anthropic 的这篇文章呢我感觉是给出了一个比较实在的答案,而且从结果上来看这套流程确实还是挺靠谱的。Claude Code 团队提供了一组数字他们是说在 6 月到 9 月的这段时间里面他们合并的 PR 呢翻了一倍还多但是呢需要回滚的比例呢反而是下降了 40% 以上。
换句话说就是代码合得更多了但出问题的比例却更少了。我们仔细想想虽然这篇文章讲了很多不过我感觉它最核心的一个方向就是重新划清人和 AI 的分工。AI 是负责大量的执行工作比如说是什么写代码呀、跑检查呀、找问题呀之类的;而人呢只负责最关键的决策比如说是这个需求该不该做、要用什么架构或者是出了问题谁来负责等等。
这个让我想起了我之前出的一个讲 Harness 的视频,在那个视频里面我给大家详细解释了 OpenAI 写的那个 Harness Engineering 的文章。这篇文章里面有一句话说的特别好我当时呢也给大家着重强调了一下这句话就是 "Humans steer, Agents execute",翻译过来就是人来掌舵 AI 来执行。你看不管是 Anthropic 还是 OpenAI 最后走的都是同一个方向。所以再回到开头的那个问题:如何审核 AI 写代码?表面上它好像是在问审核的方法,但是往深了一层想它真正想问的可能是怎么把人有限的注意力用在最关键的地方。
Anthropic 给出的这套流程可能不是最终的答案,随着大模型越来越强流程可能还会发生一些变化。但是我觉得总体的方向应该是不会变那就是能交给 AI 的尽量交给 AI,人呢就把时间花在那些最重要的决策上。这或许不光是代码审核的答案也是整个软件开发接下来的方向。好本期视频到这里就结束了,我是马克我们下期再见拜拜