Skip to content

代码审查智能体 ​

典型题:设计一个能阅读 PR diff、发现风险、给出审查意见的代码审查 Agent。

面试官真正想看什么 ​

一次 PR 只改了登录校验,却带进来一个秘密密钥。审查 Agent 既要读 diff 周边上下文,也要把高风险 finding 交给规则和人工复核;不能让模型直接把整仓库改一遍再说已经修好。

  • 你知不知道代码审查不能只看风格。
  • 你会不会补充上下文,而不是只喂 diff。
  • 你能不能控制误报、漏报和评论噪声。
  • 你是否知道自动改代码必须处理版本和冲突。

先问清楚 ​

Q1:设计代码审查 Agent 前先问什么? ​

参考答案

我会先问:

  • 审查对象是什么:小 PR、大型重构、后端、前端、数据脚本还是配置。
  • 是否只评论,还是允许生成补丁。
  • 是否接入 GitHub / GitLab / CI。
  • 目标是找 bug、补测试、看安全,还是统一风格。
  • 是否需要基于团队规范、历史代码和架构文档。

这些问题决定它是一个“辅助 reviewer”,还是一个能参与自动修复的系统。

最小架构 ​

核心流程 ​

Q2:代码审查 Agent 的最小闭环是什么? ​

参考答案

最小闭环是:

  1. 获取 PR diff、文件路径、行号和上下文。
  2. 收集相关函数、类型定义、测试和团队规范。
  3. 让模型按审查优先级分析问题。
  4. 把问题分级。
  5. 输出带文件、行号、原因和建议的评论。
  6. 记录 trace、误报反馈和采纳情况。

如果只把 diff 丢给模型,它可能因为上下文不足产生大量误报。

Q3:审查优先级怎么排? ​

参考答案

我会按这个顺序:

  1. 正确性 bug。
  2. 安全和权限问题。
  3. 数据丢失、并发、事务、边界条件。
  4. 缺失测试。
  5. 可维护性。
  6. 风格和命名。

代码审查 Agent 最忌讳评论很多小风格问题,却漏掉真正的 correctness 和安全风险。

Q4:输出格式应该长什么样? ​

参考答案

每条评论最好包含:

  • 严重级别。
  • 文件和行号。
  • 问题描述。
  • 为什么这是问题。
  • 建议修改方向。
  • 不确定时标成疑问,而不是断言。

示例:

text
[P1] 这里在 items 为空时会访问 items[0],可能抛异常。
建议在访问前判断长度,或给出默认返回。

上下文和规则 ​

Q5:只看 diff 够不够? ​

参考答案

很多时候不够。只看 diff 成本低,但容易漏掉上下文,比如:

  • 被调用函数的约束。
  • 类型定义。
  • 数据库事务边界。
  • 权限中间件。
  • 测试覆盖。
  • 历史规范。

比较稳的方式是:先看 diff,再按文件和符号补上下文。不要一上来把整个仓库都塞给模型。

Q6:如何接入团队规范? ​

参考答案

团队规范可以作为检索源或规则配置接入,包括:

  • 编码规范。
  • 安全规范。
  • 架构边界。
  • API 兼容性要求。
  • 测试要求。

模型审查时应该引用规则,而不是只说“我觉得这里不太好”。这样评论才更有说服力。

Q7:大型 PR 怎么处理? ​

参考答案

大型 PR 不应该一次性塞给模型。可以拆成:

  • 按文件分组。
  • 按模块分组。
  • 先总结改动意图。
  • 再审查高风险文件。
  • 最后做全局一致性检查。

如果 PR 过大,也可以要求先拆 PR。Agent 不应该为了“能审”就忽略上下文限制和成本。

误报、漏报和自动修复 ​

Q8:怎么减少误报? ​

参考答案

减少误报可以从几方面做:

  • 补足上下文。
  • 优先输出高置信问题。
  • 评论数量限流。
  • 不确定时用疑问句。
  • 用人工反馈回流评估集。
  • 让模型说明“为什么这是 bug”。

误报太多会让工程师不再看 Agent 评论,所以宁可少而准,也不要像风格检查器一样刷屏。

Q9:如果允许 Agent 自动生成补丁,怎么保证安全? ​

参考答案

自动补丁要满足几个条件:

  • 基于明确版本生成。
  • 应用前检查文件是否变化。
  • 只改与问题相关的最小范围。
  • 保留 diff 给人 review。
  • 跑测试或静态检查。

默认我会让代码审查 Agent 只评论,不直接改。只有在低风险、可自动验证的场景下,才允许生成补丁。

Q10:怎么避免覆盖用户代码? ​

参考答案

要做版本检查和 patch 合并:

  • 补丁声明 base commit 或 base file hash。
  • 应用前确认目标文件没有变化。
  • 如果变化了,重新生成或人工合并。
  • 不使用直接覆盖整文件的方式。

这和多 Agent 编辑同一文件的冲突处理类似,本质上都是保护已有变更。

CI 与安全 ​

Q11:如何接入 CI? ​

参考答案

可以把 Agent 放在 CI 或 PR bot 流程里:

  • PR 打开或更新时触发。
  • 读取 diff 和相关上下文。
  • 生成审查结果。
  • 高置信问题直接评论。
  • 低置信问题汇总成报告。
  • 结果进入评估和反馈系统。

但要控制噪声,不能每次都发一堆无价值评论。

Q12:如何处理私有代码和密钥? ​

参考答案

要做几层保护:

  • 不把密钥、凭证、生产数据发送到不可信模型。
  • 日志脱敏。
  • 限制模型可访问文件范围。
  • 对输出做敏感信息检查。
  • 企业场景优先考虑合规部署或受控 API。

代码审查 Agent 能看到大量敏感资产,这一点必须在系统设计里主动讲。

评估 ​

Q13:代码审查 Agent 怎么评估? ​

参考答案

可以看这些指标:

  • 真实问题命中率。
  • 误报率。
  • 漏报率。
  • 人工采纳率。
  • 每个 PR 平均评论数。
  • 平均成本和延迟。
  • 是否影响 CI 时长。

还可以建立带标准答案的 PR 样本集,比如空指针、权限遗漏、SQL 注入、事务缺失、测试缺失等。

Q14:如果面试官问“这个系统最难的点是什么”,怎么答? ​

参考答案

最难的是上下文选择和误报控制。代码问题通常依赖上下文,只看 diff 容易误判;但上下文放太多又贵、慢、噪声多。所以要在“补足必要上下文”和“控制成本”之间取平衡。

30 秒收口 ​

Q15:你会怎么总结这个方案? ​

参考答案

text
我会把代码审查 Agent 定位成辅助 reviewer,优先找 correctness、安全和测试缺口。
默认只评论不直接改代码;如果生成补丁,也要基于版本检查和人工确认。

本题常见扣分点 ​

  • 只讲风格检查,不讲 correctness。
  • 只喂 diff,不补上下文。
  • 评论太多,没分级。
  • 自动改代码但不做版本检查。
  • 不考虑私有代码和密钥。
  • 不知道怎么评估误报和采纳率。

深入追问:把代码审查做成工程能力 ​

代码审查 Agent 的回答重点不是“模型能不能看懂代码”,而是如何把一次 PR 事件可靠地变成低噪声、可定位、可审计的审查结果,同时保护源代码和开发者已有修改。

Q16:PR 审查的容量、延迟和触发架构怎么设计? ​

回答脉络

区分 webhook 接收、异步审查和评论发布,给出峰值估算与用户可感知的时间点。

完整参考答案

我会让 Git 平台 webhook 只负责快速验签、去重和创建审查任务,然后立即返回;真正的上下文收集、静态分析和模型调用放到队列 worker。假设每天 5,000 个 PR、峰值每分钟 100 个更新事件,每个 PR 平均 20 个文件,系统要按事件而不是按用户数做容量规划,并用 repo_id + pr_id + head_sha 去重。

延迟上区分“收到事件到开始审查”“静态检查完成”“首条高置信评论”和“完整报告完成”。小 PR 可以在 1 到 3 分钟内返回结果,大型 PR 则先发布进度和高风险文件结果,剩余部分异步完成。diff 获取、代码图查询和静态扫描可以并行;模型调用要设置并发、超时和每 PR token 预算,避免一个巨型 PR 拖垮整个 worker 池。

为什么这样设计、替代方案和扣分点

  • 同步 webhook 适合内部 Demo,但 Git 平台通常要求快速响应,且模型延迟不可控;生产环境应使用队列和可重试任务。
  • 小团队、低并发可以先用单 worker;当仓库多、更新频繁时,按仓库或租户限流比简单全局限流更公平。
  • 常见扣分点是只说“部署多个 Agent”,没有说明 webhook 去重、峰值、PR 更新导致的重复任务和大 PR 的延迟策略。

Q17:从 diff 到模型上下文,具体如何选择代码? ​

回答脉络

先以 diff 为入口,再沿符号、调用和测试关系补上下文,并设置 token 预算和优先级。

完整参考答案

任务输入至少包括 base commit、head commit、diff、文件路径、变更行号和 PR 描述。上下文收集器先解析新增、删除和修改的符号,再查找被修改函数直接调用的函数、类型定义、配置、数据库模型、权限中间件和相关测试。对跨模块调用可以只补摘要、接口签名和关键实现,不把整个仓库放进 prompt。

上下文按风险排序:安全相关文件、数据库迁移、鉴权、并发和公共 API 优先;普通命名修改靠后。代码块必须带仓库、commit、路径和行号,防止模型把不同版本的代码混在一起。超过 token 预算时保留 diff 和高风险依赖,舍弃低相关历史内容,并在输出中标记“上下文不完整”。

为什么这样设计、替代方案和扣分点

  • 纯 diff 成本低、速度快,适合格式和局部逻辑;复杂 correctness 问题需要符号级上下文和测试。
  • 代码向量检索可帮助找相似实现,但不能替代编译器、类型检查和调用图;不要把“代码库做 embedding”当成全部方案。
  • 常见扣分点是把整个仓库塞给模型,或者只说“做代码 RAG”,却没讲上下文选择依据、版本绑定和超长处理。

Q18:审查任务的状态和接口应该怎么设计? ​

回答脉络

把事件、快照、分析结果和评论发布分开,支持幂等、取消和重跑。

完整参考答案

我会设计类似下面的审查任务状态:received -> snapshotting -> analyzing -> validating -> publishing -> completed,另有 cancelled 和 failed。任务记录 review_id、仓库、PR、base_sha、head_sha、规则版本、模型版本、状态、预算、尝试次数和 trace_id。所有分析结果都关联 head_sha,不能把旧 commit 的评论发布到新 PR 上。

接口可以包括:创建任务、查询任务状态、获取问题列表、重跑指定规则、确认或忽略问题、发布评论。发布评论使用外部评论 ID 做幂等键,重复 webhook 不会造成重复评论。PR 新 push 到来时,旧任务可以取消或标记过期,只有最新 head_sha 的任务有权发布;已经发布的旧评论可更新为“该问题基于旧版本”。

为什么这样设计、替代方案和扣分点

  • 只做一次性脚本适合本地试验;需要 CI 重试、用户反馈和审计时必须持久化状态。
  • 复杂平台可以用工作流引擎管理超时和补偿;简单场景用数据库状态机加队列即可。
  • 常见扣分点是只有一个“审查接口”,没有版本、幂等、取消和重跑设计。

Q19:如何把静态分析、测试和大模型结合起来? ​

回答脉络

确定性工具负责硬约束,模型负责上下文理解和解释,三者结果需要统一去重。

完整参考答案

我会先运行编译、类型检查、lint、SAST、依赖漏洞扫描和已有测试。能被规则确定判断的问题优先由这些工具发现,例如 SQL 注入规则、未使用变量或类型错误;大模型再分析业务语义、异常路径、事务边界、接口兼容和测试缺口。模型输出的问题要和静态工具结果统一成标准 finding,按规则 ID、文件、行号和相似描述去重。

当模型认为存在 bug 时,可以要求它给出触发条件和最小复现路径;对高风险问题再自动生成测试或交给沙箱执行。测试失败日志只能作为证据输入,不能被模型文本中的命令覆盖。这样组合的原因是静态工具稳定可回归,模型适合解释跨文件语义,但模型不应替代编译器和测试。

为什么这样设计、替代方案和扣分点

  • 纯静态分析适合规则明确、合规要求高的仓库;纯模型适合早期探索但误报和漏报都更难控。
  • 如果 CI 很慢,可以先跑增量静态检查,再异步做深度模型审查;核心分支可以设置阻断门槛。
  • 常见扣分点是把模型当成“万能测试器”,没有说明确定性工具的职责和结果去重。

Q20:如何保护私有代码、密钥和执行环境? ​

回答脉络

回答数据最小化、密钥检测、模型边界、沙箱和日志脱敏五层保护。

完整参考答案

代码进入模型前先扫描 API key、私钥、连接串和生产数据,按策略脱敏;但脱敏要保留语义和变量关系,不能把所有内容替换成无法分析的空白。模型只获得本次 PR 必需的文件和固定 commit 的只读快照,工具凭证由服务端托管,绝不放进 prompt。

如果需要运行测试或应用 Agent 生成的补丁,必须在隔离沙箱中执行:无生产网络和云凭证,限制 CPU、内存、磁盘、进程和执行时间。模型输出、输入、测试日志和评论都要做二次敏感信息检查,日志按仓库权限隔离。企业有严格合规要求时,可以选择自托管模型或供应商的零留存配置,但这不能替代权限和沙箱。

为什么这样设计、替代方案和扣分点

  • 自托管模型适合代码不能出域的场景,但会带来模型运维和质量成本;受控 API 适合快速上线。
  • 仅依赖供应商“不会训练数据”承诺仍不够,因为错误日志、工具访问和内部权限可能在自己系统里泄露。
  • 常见扣分点是只说“对 prompt 做脱敏”,没有讲代码执行沙箱、凭证隔离和日志权限。

Q21:如果 PR 在审查期间更新,或者模型结果发布失败,怎么恢复? ​

回答脉络

以 commit 快照为一致性边界,区分临时错误、过期任务和不可重试错误。

完整参考答案

任务开始时固定 base/head SHA,并在分析和发布前再次向 Git 平台确认 head 没变。若发生新 push,旧任务停止发布,保留结果用于诊断但标记为 stale,重新创建新 SHA 的任务。模型超时、供应商 5xx、队列暂时不可用可以指数退避;代码权限不足、仓库被删除、规则配置错误则直接失败并通知管理员。

评论发布采用幂等键和有限重试,避免网络超时后重复评论。若只发布了部分文件评论,任务状态应记录已发布评论 ID,恢复时跳过已成功项。模型不可用时可以降级为静态分析结果或排队等待,不能假装审查完成。

为什么这样设计、替代方案和扣分点

  • 小型 bot 可以直接按最新 SHA 重新跑;高并发平台需要可取消任务、租约和部分结果。
  • 常见扣分点是遇到错误就“重试三次”,却没有区分 head 变化、权限失败、重复评论和降级结果。

Q22:如何定义 finding 的严重级别,降低评论噪声? ​

回答脉络

严重级别要和业务影响、触发确定性和处置动作绑定,而不是让模型随意生成 P0/P1。

完整参考答案

我会先定义统一等级。例如 P0 是确定会造成重大安全或数据损失且应阻断合并;P1 是高概率 correctness、安全或稳定性问题;P2 是中等风险或需要补测试;P3 是建议性改进。等级判定由规则和模型共同提供,但高等级必须满足可解释证据,例如触发路径、受影响范围、敏感操作或已有测试失败。

评论发布策略可以是 P0/P1 直接 inline,P2 汇总后评论,P3 默认不发或只在报告中展示;每个 PR 设置评论上限和相同根因去重。模型不确定时使用“疑似问题 + 验证建议”,不要把猜测写成阻断性结论。

为什么这样设计、替代方案和扣分点

  • 安全敏感仓库可以把某些规则设为硬阻断;普通业务仓库更适合只告警不阻断,避免误报阻塞交付。
  • 常见扣分点是只说“让模型判断严重程度”,没有定义等级、发布策略、评论限流和不确定表达。

Q23:如何评估审查质量,而不是只看模型分数? ​

回答脉络

建立带真实缺陷的 PR 集,分别评估发现、定位、解释、采纳和系统代价。

完整参考答案

离线集应包含真实历史缺陷、人工构造的安全问题、正常但容易误报的代码,以及不同语言、仓库规模和 PR 类型。每条 finding 记录标准文件/行号、根因、严重级别和可接受的解释范围。指标包括按严重级别的 precision、recall、漏报率、行号定位准确率、建议有效率和重复问题率。

线上还要看开发者采纳率、忽略率、误报反馈、每个 PR 评论数、从发现到修复的时间、CI 增量延迟和模型成本。采纳率不能单独当准确率,因为开发者可能懒得点击;应结合人工复核和修复后回归。高风险规则要单独设安全门槛,不能被整体平均数掩盖。

为什么这样设计、替代方案和扣分点

  • LLM-as-a-judge 可以批量评估解释质量,但“是否真是 bug”最好由人工标注或测试复现确认。
  • 常见扣分点是只说准确率、BLEU 或用户点赞,没有定义 finding 级别的标注和误报/漏报成本。

Q24:一次 PR 审查的成本怎么计算?怎么优化? ​

回答脉络

按 PR 维度归集模型 token、工具计算和重试,使用分层策略控制大 PR 成本。

完整参考答案

每次审查用 review_id 关联所有模型调用,记录输入 token、输出 token、缓存输入 token、模型单价、上下文文件数、静态检查耗时、沙箱 CPU、重试次数和评论发布次数。模型成本是输入、输出和缓存 token 分别乘供应商对应价格,再加代码托管 API、队列、对象存储、日志和计算资源的分摊。不能只用 PR 文件数估算,因为一个大文件可能远贵于十个小文件。

优化时先使用静态工具筛掉明显问题,再按风险选择模型;稳定的系统指令、审查规范和固定规则前缀放在 prompt 前面,提升 token cache 命中率;对相同 commit、相同规则版本的重复审查复用结果。上下文做摘要和分层加载,大 PR 先审高风险文件。质量回归通过后,再比较“便宜模型初筛 + 强模型复核”和全程强模型的成本曲线。

为什么这样设计、替代方案和扣分点

  • 代码内容变化频繁,整份报告缓存容易过期;更适合缓存静态分析、仓库规范摘要和不变的上下文。
  • 常见扣分点是忽略缓存 token、重试和沙箱成本,或为了省钱把高风险安全审查也降级到小模型。

Q25:如何灰度、阻断和回滚?何时不该让 Agent 参与 CI 门禁? ​

回答脉络

先 shadow,再只评论,最后才对少量高置信规则设置门禁,并保留人工绕过和回滚。

完整参考答案

新模型、prompt、上下文策略或规则版本先在历史 PR 集回归,再对真实 PR 做 shadow,不发布评论,只比较 findings。接着在少量仓库开启“建议评论”,观察误报率、采纳率、评论数量、CI 延迟和开发者反馈。只有经过验证的高置信安全规则才适合阻断合并,模型自由生成的低置信意见最多做提示。

门禁决策必须记录规则版本、证据、操作者和绕过原因。出现误报激增、CI 延迟超标、敏感数据泄露或评论接口异常时,立即关闭 Agent 门禁并回退到静态检查或旧版本;已有代码不能因为服务不可用而全部无法交付,除非该仓库明确要求 fail-closed。

为什么这样设计、替代方案和扣分点

  • 安全合规仓库可对确定性规则 fail-closed;普通研发仓库更适合 fail-open 加告警,避免模型故障阻塞交付。
  • 常见扣分点是上线就让模型直接阻断合并,没有 shadow、可绕过机制、回滚条件和故障时的交付策略。

持续学习,持续实践。