LinkedIn 如何用多智能体把 AI 代码审查做成生产级基础设施

2026-08-22 36 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:12 分钟

在 LinkedIn 这样的工程规模下,代码审查的难题不是“能否让大模型读懂一段 diff”,而是如何让系统理解组织内部的编码约定、稳定处理大量 PR,并且避免幻觉与低价值评论。LinkedIn 的做法不是在 GitHub 前面简单挂一个通用 AI 审查器,而是构建多智能体平台,把代码审查当作生产基础设施来运营。

为什么单个通用审查器不够

一个模型同时承担上下文检索、缺陷发现、安全分析、规范检查和评论生成,看起来简单,实际容易产生三个问题。

第一,输入上下文会迅速膨胀。除了 PR diff,系统还可能需要读取仓库规则、相关模块、测试、依赖关系和历史约定。把所有内容塞进一次请求,既昂贵,也会稀释模型对关键变更的注意力。

第二,不同审查任务需要不同证据。安全问题可能需要追踪未受信任输入,兼容性问题需要核对接口调用方,测试问题则要理解已有测试覆盖。一个宽泛的提示词很难为每类结论设置清晰边界。

第三,模型很容易给出“原则正确、当前 PR 无用”的评论,例如建议增加日志、补充文档或重构函数,却无法指出具体风险和触发路径。这类低信号反馈一旦大量进入 PR,会消耗开发者的注意力,并降低团队对系统的信任。

多智能体架构把这些职责拆开:上下文智能体负责收集组织知识,专项审查智能体分别寻找特定类型的问题,验证智能体检查证据,最终由汇总智能体决定哪些发现值得发布。重点不是智能体数量,而是让每一步都有明确输入、输出和失败边界。

组织上下文决定审查质量

通用模型知道常见语言规则,却不知道某个组织为什么禁止特定 API、哪些服务必须使用内部鉴权库,也不知道一个看似多余的兼容分支正在保护旧客户端。因此,平台需要把组织上下文变成可检索、可版本化的工程资产。

可用的上下文通常包括:

  • 仓库级贡献指南和编码规范;
  • 目录或模块所有权;
  • 内部框架与安全 API 的使用规则;
  • 相关源文件、测试和接口定义;
  • 与本次变更直接相关的静态分析结果。

上下文检索也需要克制。系统应优先读取被修改符号的定义、调用方和附近测试,而不是无差别索引整个仓库。每条评论还应携带证据,例如文件位置、规则编号或可复现的执行路径。没有足够证据的候选发现,可以留在遥测数据中,而不必出现在开发者的 PR 页面上。

可以这样实践:构建一个最小多智能体审查流水线

下面是一个可直接运行的 Python 示例。它不调用特定厂商的模型,而是用确定性函数模拟三个角色:规则审查、测试审查和证据验证。接入真实模型时,可以保留相同的数据契约,把 rule_agenttest_agent 替换成模型请求。

将代码保存为 review_pipeline.py,使用 Python 3.10 或更高版本运行:

from __future__ import annotations

from dataclasses import asdict, dataclass
import json
import re
import sys


@dataclass
class Finding:
    agent: str
    severity: str
    line: int
    message: str
    evidence: str
    confidence: float


def changed_lines(diff: str) -> list[tuple[int, str]]:
    """Return new-file line numbers and added lines from a unified diff."""
    result: list[tuple[int, str]] = []
    new_line = 0

    for raw in diff.splitlines():
        match = re.match(r"@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@", raw)
        if match:
            new_line = int(match.group(1))
        elif raw.startswith("+") and not raw.startswith("+++"):
            result.append((new_line, raw[1:]))
            new_line += 1
        elif not raw.startswith("-"):
            new_line += 1

    return result


def rule_agent(diff: str) -> list[Finding]:
    findings = []
    for line, text in changed_lines(diff):
        if "eval(" in text:
            findings.append(Finding(
                agent="security",
                severity="high",
                line=line,
                message="新增代码调用 eval;请确认输入是否完全受信任。",
                evidence=text.strip(),
                confidence=0.96,
            ))
    return findings


def test_agent(diff: str) -> list[Finding]:
    added = [text for _, text in changed_lines(diff)]
    changes_behavior = any("def " in text or "if " in text for text in added)
    touches_test = any("test_" in text for text in added)

    if changes_behavior and not touches_test:
        return [Finding(
            agent="testing",
            severity="medium",
            line=0,
            message="变更引入了新的控制路径,但当前 diff 中未看到对应测试。",
            evidence="added function or branch; no added test_ symbol",
            confidence=0.72,
        )]
    return []


def verifier(findings: list[Finding], threshold: float = 0.85) -> list[Finding]:
    """Publish only findings with concrete evidence and enough confidence."""
    return [
        item for item in findings
        if item.confidence >= threshold and item.evidence.strip()
    ]


def main() -> None:
    diff = sys.stdin.read()
    candidates = rule_agent(diff) + test_agent(diff)
    published = verifier(candidates)
    print(json.dumps([asdict(item) for item in published], ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()

可以用下面的 diff 验证流水线:

python review_pipeline.py <<'DIFF'
@@ -1,2 +1,5 @@
 def parse_expression(value):
-    return value
+    if value:
+        return eval(value)
+    return None
DIFF

这个示例体现了一个重要原则:专项智能体可以提出候选问题,但只有携带具体证据并通过阈值的结果才会发布。测试智能体给出的置信度是 0.72,因此默认不会打扰 PR 作者;安全智能体定位到了新增行并给出直接证据,可以进入最终结果。

接入真实大模型时,建议要求每个智能体返回结构化 JSON,而不是自由文本。例如可以采用以下输出契约:

{
  "category": "security",
  "severity": "high",
  "file": "src/parser.py",
  "line": 42,
  "claim": "Untrusted input may reach eval().",
  "evidence": ["request.body.expression", "parse_expression(value)"],
  "confidence": 0.94
}

验证阶段应检查文件和行号是否存在、证据是否出现在可见上下文中、结论是否只针对本次修改,以及同一问题是否已被其他智能体报告。不要让模型仅凭自己声明的置信度决定是否发布。

把审查系统按生产服务运营

“生产基础设施”意味着平台需要面对普通后端服务都会面对的问题:延迟、容量、失败隔离、版本发布、可观测性和成本控制。

PR 更新后,系统可以按提交 SHA 建立幂等任务。检索和专项审查并行执行,单个智能体超时不应阻塞整个 PR。模型、提示词、规则库和检索器都要记录版本,这样团队才能解释某条评论为何出现,并在质量下降时回滚。

比“发布了多少评论”更有价值的指标包括:开发者接受或修复的比例、被标记为无效的比例、重复评论率、每个有效发现的推理成本,以及从 PR 更新到审查结果出现的延迟。团队还需要保留一组经过人工确认的 PR 作为回归集,在升级模型或提示词之前离线评估。

隐私和权限同样不能交给模型自行处理。检索层必须继承代码托管平台的访问控制;日志应避免保存密钥和完整源码;发送到外部模型之前,需要明确数据保留、训练使用和地域合规边界。

采用时先追求可信度,而不是评论数量

落地这类系统时,可以从一个高价值、证据容易验证的场景开始,例如危险 API、资源泄漏或组织内明确禁止的调用方式。让系统先以旁路模式运行,比较 AI 发现与人工审查结果,再逐步开放自动评论。

上线前至少检查以下事项:

  • 每条评论是否指向本次变更中的具体代码;
  • 是否能展示规则、调用路径或测试缺口等证据;
  • 低置信度结果是否默认不发布;
  • 智能体失败是否能够隔离和重试;
  • 模型、提示词与上下文版本是否可追踪;
  • 是否有人工反馈、离线回归集和快速回滚机制;
  • 代码访问权限和数据保留策略是否得到执行。

多智能体并不会自动消除幻觉。它真正提供的是一套可治理的分工方式:缩小每个模型调用的任务范围,引入独立验证,并把最终评论视为需要质量门禁的生产输出。在大规模代码审查中,少量可证实的发现通常比大量听起来合理的建议更有价值。


相关推荐