Skip to content
返回项目教程

AI 代码审查机器人

构建 GitHub/GitLab 机器人,用显式规则、落地上下文和质量追踪审查 PR。

设计与审查策略

选择模型、从团队历史定义审查规则、设计 PR 评论格式。

为什么

AI 审查者的价值在规则而非模型。无显式规则(函数最大长度、禁用 API、安全模式),LLM 给泛泛'考虑...'评论,开发者忽略。精确规则加落地上下文(diff + 相关代码)产出可执行审查,被解决而非被驳回。

何时使用

连接机器人之前。花 1 周从团队实际审查评论历史定义 10-20 条规则。

如何做

1. 挖掘审查历史 - 从 GitHub/GitLab 导出 6 个月 PR 审查评论 - 按主题聚类:安全、性能、命名、错误处理、测试 - 前 10-20 个高频主题成为规则 2. 规则写成结构化检查 - 每条规则:{ id, description, severity, check(diff, context) -> Finding[] } - 例:no-console-log -> 标记 src/ 中新增的 console.log - 静态规则(regex/AST)与 LLM 辅助规则(语义)混合 3. 选择模型 - gpt-4o-mini 做分类(便宜、快、规则检查够用) - Claude 做细致审查(安全推理、架构反馈) - 缓存规则结果;仅需语义判断的规则调 LLM 4. 设计评论格式 - 每发现一条评论,作为可审查行评论(非文字墙) - 格式:[Rule: id] 严重度图标 + 1 句问题 + 建议修复 - 按文件分组发现;每 PR 限 5 条评论避免噪音 5. 定义审查触发 - PR 打开 + 新推送时(重新审查 diff) - 跳过草稿和机器人 PR(renovate、dependabot) - 用 .ai-reviewer.yml 做每仓库规则覆盖

示例

// 结构化规则 const rules = [ { id: "no-console-log", description: "生产代码中无 console.log", severity: "warn", check(diff) { return diff.addedLines .filter(l => l.code.match(/console.log(/)) .map(l => ({ file: l.file, line: l.number, message: "移除 console.log 或用 logger" })); }, }, { id: "unhandled-async", description: "异步调用无 try/catch 或 .catch", severity: "error", async check(diff, context) { // LLM 辅助:让 Claude 找未处理的 await return await claude.findUnhandledAwaits(diff, context); }, }, ]; // .ai-reviewer.yml(每仓库覆盖) rules: no-console-log: off # 此仓库是 CLI,日志没问题 unhandled-async: error max_comments_per_pr: 5

常见问题

  • ⚠无规则——LLM 每个 PR 发泛泛'考虑加注释',开发者一周内就驳回
  • ⚠发文字墙而非行评论——开发者无法执行 20 行文章,略过漏真问题
  • ⚠审查机器人 PR(dependabot)——机器人在依赖机器人 PR 上发评论,造成无限评论循环

最佳实践

  • ✓挖团队 6 个月审查评论定义规则——机器人应执行团队标准而非通用标准
  • ✓发现作为可审查行评论发布,每 PR 限 5 条——信噪比决定开发者是否读机器人
  • ✓webhook 处理中跳过草稿 PR 和机器人作者 PR,避免噪音和评论循环

实现与 PR 集成

构建 webhook、diff 解析和评论发布,配限流和落地。

为什么

webhook 循环是机器人失败之处——每次推送发评论刷屏 PR、不限流撞 API 上限、发未落地评论(不关联具体行)让开发者忽略机器人。每 PR 批量审查,只评论变更行。

何时使用

规则在样本 diff 上产出好发现后。连接 webhook,先在测试仓库运行再指向主仓库。

如何做

1. 建 webhook 接收器 - GitHub App(比机器人账号权限更细,首选) - Webhook:pull_request(opened、synchronize)+ pull_request_review - 用 X-Hub-Signature-256 验证 webhook 签名 2. 解析 diff - GET /repos/:owner/:repo/pulls/:number/files(分页) - 每文件:提取新增行及行号 - 经 .gitattributes 跳过生成文件(*.min.js、*.lock、dist/) 3. 跑规则收集发现 - 先跑静态规则(快、无 LLM 成本) - LLM 辅助规则批量:一个 prompt 含所有相关 diff + 上下文 - 每发现落地到 diff 中具体 (file, line) 4. 发可审查评论 - POST /repos/.../pulls/:number/comments 带 position(diff 中行) - 用 GitHub Review API(POST /reviews)批量评论为一次审查 - 除非 error 严重度规则触发,标记审查为 COMMENT(非 REQUEST_CHANGES) 5. 处理限流和重试 - GitHub:App 每小时 5000 请求;接近限流时排队审查 - LLM:按 (rule_id, diff_hash) 缓存发现,重推时跳过重审 - 幂等:发新评论前删除机器人旧评论

示例

// Webhook 处理(GitHub App) app.webhooks.on("pull_request.opened", async ({ payload }) => { if (payload.pull_request.draft) return; // 跳过草稿 if (payload.pull_request.user.login.includes("[bot]")) return; // 跳过机器人 const diff = await github.getDiff(payload); // 分页文件 const findings = []; for (const rule of rules) { findings.push(...await rule.check(diff, { repo: payload.repository })); } const top = findings.slice(0, 5); // 限 5 条 // 作为单次审查带行评论发布 await github.rest.pulls.createReview({ owner, repo, pull_number: pr.number, event: findings.some(f => f.severity === "error") ? "REQUEST_CHANGES" : "COMMENT", comments: top.map(f => ({ path: f.file, line: f.line, body: `[${f.ruleId}] ${f.severity === "error" ? "🚫" : "⚠️"} ${f.message}` })), }); });

常见问题

  • ⚠每次推送都发不去重——10 提交 PR 收 10 相同审查,刷屏时间线
  • ⚠未落地评论(无行位置)——作为通用 PR 评论发布,开发者无法内联解决
  • ⚠审查中途撞 GitHub API 限流——机器人静默失败,PR 完全无审查

最佳实践

  • ✓按 (rule_id, diff_hash) 缓存发现,发前删旧机器人评论——使重推幂等
  • ✓用 GitHub Review API 将所有评论批量为一次审查事件,非逐条评论
  • ✓接近 API 限流时排队审查,从队列(BullMQ + Redis)处理而非静默失败

部署与调优

部署为 serverless 函数或容器,追踪审查质量,每周调优规则。

为什么

AI 审查者静默退化——模型更新改评论风格,或新代码模式触发误报。不追踪'评论解决 vs 驳回'和每周规则审查,机器人信噪比下降直到开发者禁用。

何时使用

机器人在真实 PR 发评论时。第一天起追踪质量指标,每周据数据调优规则。

如何做

1. 部署 webhook 接收器 - Cloud Run 或 Fly.io:含 GitHub App 的容器,PR 间缩到零 - min-instances = 0(成本:按审查付费),max = 5(处理 PR 打开风暴) - GitHub App 私钥存密钥管理器 2. 追踪审查质量指标 - 每条评论存 { rule_id, pr, posted_at, resolved_at, dismissed } - resolved = 开发者修复问题;dismissed = 开发者点"解决"未修复 - 看板:每规则解决率、每规则驳回率、每周总评论数 3. 每周调优规则 - 看板:驳回率 > 50% 的规则噪音大——收紧或移除 - 一个月无发现的规则可能过期——检查代码库是否已演进 - 从近期手动审查评论中加现有规则未覆盖的新规则 4. 安全处理模型更新 - 固定模型版本(gpt-4o-2024-08-06)避免更新静默改行为 - 模型升级时:在 50 个历史 PR 上重跑机器人并 diff 发现 - 新模型驳回多 > 20% 则回滚 5. 收集开发者反馈 - 每条机器人评论加 thumbs-up / thumbs-down 反应 - 月度调查:"机器人有帮助吗?"1-5 分 - 均分低于 3 则暂停机器人做全规则审查

示例

// 部署到 Cloud Run(缩到零) // Dockerfile -> gcloud run deploy ai-reviewer --source . --min-instances 0 --max-instances 5 // 质量追踪(Postgres) await db.comments.insert({ rule_id, pr_number, repo, posted_at: new Date(), status: "open", // -> "resolved" | "dismissed" }); // 每周质量报告(定时任务) const rules = await db.query(` SELECT rule_id, AVG(CASE WHEN status = 'resolved' THEN 1 ELSE 0 END) AS resolve_rate, AVG(CASE WHEN status = 'dismissed' THEN 1 ELSE 0 END) AS dismiss_rate FROM comments WHERE posted_at > now() - interval '7 days' GROUP BY rule_id `); // 任一规则 dismiss_rate > 0.5 则告警 Slack——太吵,需调优

常见问题

  • ⚠无质量追踪——机器人发数月,驳回率爬到 80%,开发者静音无人察觉
  • ⚠模型未固定——静默更新改评论语气,误报飙升,信任一夜蒸发
  • ⚠无开发者反馈渠道——开发者觉得烦但无法信号,静默禁用

最佳实践

  • ✓第一天起按规则追踪解决 vs 驳回率——驳回率是机器人信任的先行指标
  • ✓固定模型版本,升级前在 50 历史 PR 重跑——行为变更触生产前捕获
  • ✓每条评论加 thumbs-down 反应并月度调查——有用度低于 3/5 则暂停审查规则

完整开发者生命周期

从想法到维护的 14 阶段开发者路径图 — 可视化依赖关系、追踪进度。

下一步