Newshot
Account

LinkedIn 用 AI 每周审查 4 万个拉取请求

AI summary

LinkedIn 拥有超过 1 万个活跃代码仓库,每周有数万个拉取请求被提交。随着编码智能体编写更多代码,瓶颈从写代码转向审查代码,LinkedIn 因此自建 AI 审查器,典型一周内覆盖大部分拉取请求。

Translation(model translation, not the source's own text)

扩展 LLM 应用的 4 个关键洞察(赞助内容)

在生产环境中运行 LLM 应用的挑战在于:故障是静默的,成本是不可预测的,而安全漏洞往往直到为时已晚才被发现。

下载这本 Datadog 电子书,获取端到端监控、调试和保护 LLM 应用工作流的实用策略。你将获得 4 个关键洞察,了解如何克服大规模部署 LLM 的挑战——从追踪多步骤链式执行和检测提示注入攻击,到跟踪 token 成本和实时评估输出质量。

下载电子书

LinkedIn 拥有超过 10,000 个活跃代码仓库,每周有数万个拉取请求(PR)被创建 [1]。随着编码智能体编写越来越多的代码,软件交付的慢环节已经从编写代码转移到了审查代码。

为了克服代码审查瓶颈,LinkedIn 构建了自己的 AI 审查器。在典型的一周内,这个内部审查器覆盖超过 40,000 个 PR,而且它的大部分审查意见在第一位人类审查者打开 PR 之前就已经发布 [1]。

为了更好地理解 AI 审查器的整体格局以及 LinkedIn 如何构建自己的审查器,我们采访了 Min Chen(LinkedIn 首席主任工程师)和 Balaji Srinivasan(LinkedIn 工程高级总监)。感谢二人抽出时间,并坦诚分享哪些做法没有奏效。

在本文中,你将了解到:

  • 什么是 AI 代码审查器,以及为什么如今审查成了瓶颈
  • 团队和公司应对代码审查瓶颈的三个主要方向
  • 如何构建一个能在生产环境中运行的多智能体 AI 审查系统
  • AI 审查器的评估是什么样的
  • 未来展望以及新瓶颈会转移到哪里

什么是 AI 代码审查器?

软件开发有两个主要步骤。工程师编写一个变更,其他工程师在它合并到主代码库之前进行审查。

当工程师编写代码时,这个变更会变成一个 PR。然后审查者阅读它的 diff,也就是它添加、删除或修改的行。以下是从作者打开 PR 到 PR 合并回代码库的典型步骤:

  • 作者从一个包含变更的分支打开 PR。
  • 代码托管平台(如 GitHub)通知审查者并启动持续集成(CI),运行测试和 linter(用于标记风格问题和简单错误)。
  • 审查者阅读 PR 并对特定行发表评论。
  • 作者推送修复。然后审查者再次查看。
  • 审查者批准,PR 合并。

AI 正在改变这个开发流程,因为它现在可以帮助完成其中的一些步骤。工程师把这些步骤交给 AI 智能体,把更多时间花在关注意图和判断上。这就是 AI 原生开发。

具体到编写步骤,前沿编码智能体最近展现出了前景。给定一个任务,智能体实现功能、编写测试、运行这些测试,并迭代直到通过。最后,它打开一个 PR 供审查。

像 {{NAME_ab12cd34}} 这样写的值是真实值的占位符。在回复和工具调用中都完全按原样使用它们:它们会在任何内容运行之前被替换为真实值。不要要求验证它们,也不要用示例替换它们。

LinkedIn 如何利用 AI 每周审查 40,000 个拉取请求

借助编码代理,编写(第一步)现在可以在很大程度上自动化,并且完成得快得多。工程师不再需要花数小时或数天编写一项变更,代理只需几分钟就能写完。但如果仍要由真实人类审查所提议的变更,流程依然会很慢,因为工程师的工作时间仍然是固定且有限的。

解决办法是一个能够可靠审查代码的系统,最好在人类之前进行审查。这个系统被称为 AI 审查器。它会像人类审查者那样阅读 PR,并对需要关注的代码行发表评论。一旦自动代码审查完成,作者——在这里是编码代理——会处理这些评论,这样人类审查者就能把有限的时间花在判断修复上。

由于模型在阅读代码方面也越来越强,更多团队正通过这种方式实现审查自动化 [2]。它们的主要区别在于希望把审查流程自动化到什么程度。完全自动化会让 AI 自行批准变更。这很难,大多数实验室还没有做到。

部分自动化保留人类对变更的批准,并让 AI 先审一遍。这能让流程更快,同时让真实人类留在流程中,以降低合并有缺陷或不安全代码的风险。如今部分自动化更可行,已经部署 AI 审查器的公司(如 LinkedIn)通常采用部分自动化。本文余下部分,我们聚焦部分自动化。

但为什么构建 AI 审查器具有挑战性?为了让 AI 审查器可靠,它必须具备四个属性:

  • 有依据:它标记出变更行中的真实问题。
  • 高信号:它产生的问题都是真实缺陷和高风险代码行(而不只是 linter 能捕获的细微风格问题)。
  • 了解代码库:它遵循代码库自身的约定。
  • 及时:它在作者仍能采取行动时发表评论。

同时做到这四点才是难点。LinkedIn 经过多次迭代构建了自己的系统才达到目标。我们来看看他们是如何构建的。

停止在每次 CI 运行时重新安装工具链(赞助)

AI 代理会打开更多拉取请求,而每个拉取请求都会从零重新安装相同的依赖。这浪费了 CI 时间和金钱。

WarpBuild 把这部分工作保留下来:

  • 快照运行器从已保存的机器镜像启动,工具链已存在于磁盘上
  • 每个作业仍然获得一个全新的临时运行器
  • WarpBuild 缓存在作业之间恢复依赖
  • 速度是默认运行器的两倍,成本只有一半

受到 Braintrust、Raycast、OpenRouter、Comcast 和 Jane Street 团队信赖。

使用代码 START50 获得 50 美元免费额度。

试用快照运行器

如何构建 AI 代码审查器

回想前面所说,目标是部分自动化。PR 仍然会得到人类审查,但 AI 审查先进行。作为一家公司,你有多种选择来部署 AI 审查器。有些选项更容易设置但不够灵活,而另一些需要更多构建工作,但能让你更好地控制评论质量。

三个常见方向是:

  • 使用供应商的审查器
  • 使用现成模型并配合你的规则
  • 构建自定义多代理审查系统

方向一:使用厂商的评审器

要让 AI 评审器快速到位,一个办法是直接从厂商购买托管系统。评审器连接到代码托管平台,并对此后每个新 PR 发表评论。这样你就不必在内部自建系统。

这个方向搭建简单,不需要特别的专业知识,大概也是最快的选择。但它有两个主要局限。第一,它是通用的。你可以添加规则文件,但提示词和 harness 由厂商控制,因此很多评论都很泛泛,放到任何项目上都成立。

第二个局限是控制权。系统归厂商所有,所以模型或指令何时变更由他们决定。你无法在工程师看到更新之前先做测试,也无法逐步灰度发布某项变更。

LinkedIn 最先尝试的就是这个方案。在一次 AI-native 试点中,团队被要求自愿启用某厂商的托管评审器。但团队观察到,评论嘈杂且泛泛。它们不符合 LinkedIn 的代码库和每个仓库的规则。评论一嘈杂,工程师就会失去信任。

很快,工程师们要求退出,这意味着完全人工评审又回来了。团队对厂商的变更也毫无控制权。Min 这样总结:“你什么都不拥有。他们做点什么、改点什么,你只能被动应对。”

方向二:用现成模型搭配自己的规则

既然托管评审器过于通用,下一步自然就是使用现成模型,但在它周围自建 harness。这样你可以自己选择提示词,并把代码库自己的规则写进指令。有了这些指令和对 harness 更强的控制,评论会更贴合你的约定。

这个方向听起来很有希望:评论会针对具体代码库,而且很可能在人评审之前就快速到达。但它有两个主要问题。

第一个问题是幻觉。因为系统依赖单一模型且没有任何校验机制,一旦模型产生幻觉,就没有东西能拦住它。作者最终会收到一条关于并不存在的问题的评论,或者一个真实问题却被挂在错误的行号上。

第二个问题是知识盲区。模型从训练数据中学习好代码和坏代码长什么样。只有单一模型时,它在与训练数据重叠的领域表现良好,但在分布外输入或训练数据中出现较少的输入上就会失效。这意味着单个评审模型会反复漏掉同一类问题,也可能对同一批低价值问题反复过度标记。

当团队用仓库专属规则构建评审系统时,LinkedIn 也观察到了同样的问题。模型给出了不错的结果,但产生大量幻觉,有些评论甚至与 diff 中的行号对不上。评审用一个模型、写代码用另一个模型,并没有解决幻觉问题。但这个想法让团队提出:能否让第二个模型来检查和验证第一个模型,这正是多智能体设计背后的思路。

方向三:构建自研的多智能体评审系统

这一方向依赖多个智能体来生成有依据的评审。多智能体系统有不同的设计模式,但一种流行的模式是编排器-子智能体模式 [3],其中一个智能体把工作交给若干子智能体并合并它们的结果。对于代码评审,子智能体独立评审同一个 PR,通常各自使用不同的模型,并返回带有行号的发现项。然后编排器合并重叠的发现项,按置信度排序,并且只发布可靠的评审。

这种设计可以缓解前面几个方向的大部分局限,因为你拥有整个系统,不同模型可以互相覆盖知识缺口,而且不同智能体的发现项必须由其他智能体验证后才能保留并发布。

要加入你的规则和代码库约定,有两种方式。一种是上下文注入,也就是在仓库中添加一个规则文件,让 AI 评审器在每次 PR 时读取。这在简单的代码库中可行,但不是一个灵活的方法,因为有些规则适用于每个仓库,有些适用于某一个仓库,还有些适用于某一类变更。作为上下文注入的单个文件无法包含所有这三类规则,也无法为每个 PR 组合出正确的规则。

另一种方式是分层设计,LinkedIn 采用的正是这种方式。你设计若干层级,每个层级都有自己的范围、负责人和规则。然后由一个专门的子智能体使用这些规则执行独立评审。LinkedIn 使用了以下三个层级:

  • 公司级规则适用于每个仓库。这些规则可以是 YAML 文件,说明模型应该检查什么。
  • 仓库规则覆盖一个代码库。这可以是一个 markdown 文件,包含团队的约定,比如编码标准和评审标准。
  • PR 规则只适用于某一类变更。

为了更好地理解这个系统如何评审一个 PR,我们来看一个具体例子,看看每一步如何处理它。假设作者打开了一个 PR,其中有一个名为 cache.py 的新 python 文件,为一个 Python 服务实现内存缓存。但代码有两个问题。它有一个竞态条件和一个 bare except。

作者可能是一个编码智能体,它编写变更并打开一个 PR。然后这个 PR 被交给 AI 评审器,由它按以下三个步骤进行评审。

步骤 1:运行并行的独立评审

编排器获取 diff 和代码库上下文,然后把它们一次性分发给若干子智能体。每个子智能体构建自己的提示词,在代码库及其近期变更的上下文中评审完整的 diff,然后返回其结构化的发现项。

注意,子智能体在评审时从不会看到彼此的发现项。如果子智能体 A 能先读到子智能体 B 的发现项,它往往会同意,但由于子智能体独立工作,它们的一致意见可以作为证据。

步骤 2:合并评审

上一步中的独立子智能体会产生发现项。其中许多发现项可能重叠,指向相同的问题。例如,如果三个子智能体发现了同样的五个问题,作者就会为五个问题收到十五条评论。因此,编排器必须合并重复项。

这可以分为两个阶段。首先,确定性检查将行范围重叠的发现项标记为候选,这是一个低成本步骤,可将搜索限制在同一段代码内。其次,由 LLM 判断每对候选是否描述同一个问题。第二个阶段对于从语义上发现重叠是必要的,因为两个模型通常不会以相同方式表述同一个问题。

重叠也指示审查置信度。如果多个发现项合并为一条评论,工程师更有可能接受它,因此代码审查器可以将其排在更高位置。

这一步的结果是一个更短的发现项列表,其中重叠的发现项合并为单条高置信度评论。然而,我们仍然需要检查仅由一个子代理提出的发现项,这是最后一步的重点。

步骤 3:验证审查

仅来自一个子代理的发现项更难判断。它可能是另一个模型遗漏的真实问题,但也可能是幻觉。为了查明,编排器将这些发现项发送给另一个模型,对照代码进行验证。根据 LinkedIn 的文章,这通常能挽救真实问题 [1]。一个遗漏了问题的模型,在被要求验证另一个模型的发现项时,会确认该问题是真实的。经过验证的发现项随后会评估重要性。

当验证模型与发现项矛盾时,其置信度分数会下降。然后,低分发现项成为过滤的候选。此外,表面性的、在后续提交中已修复的,或违反仓库既定模式的发现项,在发布前会被抑制。

通过多个代理、分层规则和三步工作流,系统具备了前面描述的所有特性。它将多个独立审查合并为一个,验证发现项,并发布审查结果。

如何评估 AI 代码审查器

拥有 AI 审查器系统的实验室和团队会不断改变它。他们可能会更换模型、编辑提示词,或在测试框架中添加内容。要判断某项更改是否会让 AI 审查器变得更好,你必须运行评估(evals),即对 AI 审查器质量的可重复测试。

在本节中,我们介绍为 AI 审查器运行评估的两个阶段:更改发布前,以及代码合并后的生产环境中。

发布前的评估

在更改发布之前,你需要知道该更改是否会改善情况。典型流程是在相同的 PR 上运行生产版本和候选版本,并比较它们的审查结果,可以使用 LLM 裁判,或对照由人工标签构建的金标准数据集。

使用 LLM 裁判时,一个单独的模型将同一 PR 的两个审查结果作为输入,并对它们评分。这运行成本低,且不需要人工标签。你主要需要一个固定的评分标准,以便 LLM 遵循更可预测和可靠的路径来对审查结果评分。LinkedIn 有一个包含六个加权是/否标准的评分标准,并在每次提示词、模型和测试框架更改发布前都通过它运行。

LLM 作为裁判在比较方面效果很好 [4],但它无法可靠地决定哪些评论实际上正确。金标准数据集用已知的正确答案填补了这一空白。

LinkedIn 如何利用 AI 每周审查 40,000 个 Pull Request

一个典型流程是:在发现 bug 的位置收集真实 PR,并由人工标记哪些评审评论是正确的。这成为我们的黄金数据集。我们可以根据这些标签给候选打分,并衡量精确率和召回率等传统指标。LinkedIn 已经构建了这样一个数据集,现在正在其之上构建评估,作为其 LLM-as-a-judge 的补充。

生产环境中的评估

预发布评估在 PR 样本或固定数据集上运行,因此无法展示评审者在数千个真实 PR 上的表现,也无法展示工程师是否觉得它的评论有用。这类度量只能从生产环境获得。在生产环境中评估 AI 评审者依赖两件事:正确的指标和反馈闭环。

正确的指标决定你的系统在生产环境中表现如何。通常有太多不同的指标需要跟踪,例如首次评审时间、每次评审成本,以及工程师对评论的反应。但有些指标比其他更有洞察力。例如,表情符号反应噪声很大,因为它们几乎不能说明一条评论是否有帮助。另一方面,接受率是一个好指标,因为它检查代码是否因为一条评论而改变。Balaji 解释了在 LinkedIn 什么算作接受:“不是有人点赞或点踩,而是代码实际发生了改变。”

LinkedIn 在生产环境中评估了他们的系统,并测量了数千条 AI 评论的接受率。如下图所示,工程师接受了其中 63.9% [1]。这些数字表明,工程师会处理 AI 评审者的大多数评论,其中并发 bug 和死代码的接受率最高(100%),逻辑错误为 80%。

我们谈到了指标,但生产环境中评估更重要的部分是拥有反馈闭环:一种将这些度量转化为实际修复的机制。

当你用不同指标度量系统时,你会了解差距在哪里。如果你每天运行并度量系统,你就可以缩小这些差距。例如,LinkedIn 现在每天运行接受检查,并生成哪些规则和提示词的接受率在上升或下降的趋势报告。团队用它来决定禁用哪些规则、更改哪些提示词。

这就是评估。预发布评估检查一项变更是否可以安全发布,而每日循环度量生产环境中的系统并随时间改进它。

下一步

在 Balaji 看来,评审之后的下一个

文章标题:LinkedIn 如何用 AI 每周审查 40,000 个拉取请求

正文: [1] 高信噪比的 AI 代码审查:可大规模适配你的代码库:https://www.linkedin.com/blog/engineering/ai/high-signal-ai-code-review-that-adapts-to-your-codebase-at-scale

[2] 6000 万次 Copilot 代码审查,且仍在增长:https://github.blog/ai-and-ml/github-copilot/60-million-copilot-code-reviews-and-counting/

[3] 我们如何构建多智能体研究系统:https://www.anthropic.com/engineering/multi-agent-research-system

[4] 用 MT-Bench 和 Chatbot Arena 评估 LLM-as-a-Judge:https://arxiv.org/abs/2306.05685

The translation is machine-generated and individual terms may be off. Nothing is rewritten or cut; the original is authoritative.

Published by ByteByteGo
This site only summarises and aggregates; copyright stays with the original author. Headlines and summaries follow the source — where they differ, the original wins.
Read the original ↗