日期:2026-07-22
我们当时服务的客户是一家拥有数千名研发、代码仓库超过两万个的某头部互联网企业。他们的核心痛点和很多成长型技术团队一样:代码评审(Code Review)高度依赖少数资深工程师,标准不统一,评审质量随人员情绪和负载剧烈波动;大量隐患在合入主干后才被测试或生产告警暴露,此时修复成本已经是设计阶段的几十倍。我们评估过,单纯靠加人头扩大评审覆盖面既不经济也不可持续——资深评审者本就是稀缺资源。
这个项目里,我们决定用大模型补齐「人审」的短板:在既有评审平台前加一层智能预评审,自动读 diff、结合历史缺陷标注风险、预测易错模块,并把结论以可解释的方式回写到评审界面,最终决策仍交回评审者。底座上,我们采用的是自研 AI 私有化部署底座,推理服务跑在 vLLM 之上,并通过我们采用的 AI 网关统一接入多模型、做计量与限流。这不是要替代人,而是把人从重复、易漏的体力活里解放出来。
落地场景围绕三条主线串起来。第一,PR/MR 提交后,大模型读取完整 diff 以及变更文件的历史上下文,按团队沉淀的评审规则(空指针、并发竞争、资源泄漏、越权访问等)逐条给出风险点,并直接附上可点击的代码行定位。第二,把历史缺陷库(如 Jira 缺陷、线上 incident)与代码指纹对齐,对本次变更命中的「易错模块」做风险预测,输出高/中/低分级。第三,与既有评审平台(GitLab/Gerrit 类)对接,把模型结论以评论形式写入评审流,评审者一键采纳或驳回,采纳结果回流用于持续优化提示词与分级阈值。
业务侧我们同时服务了一家某股份制银行的研发中台,他们对「可解释、可复核、可审计」的要求极高,因此模型输出必须带依据,不能只给一个结论。这一约束反过来塑造了我们的工程方案——所有缺陷标注都要能追溯到具体规则或历史缺陷样本。
diff 语义理解与上下文拼接。单纯把 diff 文本丢给模型会丢失大量语义:函数被截断、跨文件调用链看不到、常量定义不在视野内。我们的做法是先做一次轻量 AST 静态分析,按变更点向上回溯被调用方与下游调用方,把「变更函数 + 受影响签名 + 相关常量/类型定义」拼成结构化上下文窗口,再交给模型。上下文长度用滑动截断控制,单个变更集合上限 12k tokens,超出则按调用图重要性排序裁剪,保证核心路径优先进入窗口。
评审规则与历史缺陷对齐。我们面临规则「漂移」问题:历史缺陷标签稀疏、噪声大。解决方案是建立规则—样本双通道:一方面把团队评审规则写成结构化 YAML(每条含触发模式、严重度、示例),另一方面用 Milvus 向量库把历史缺陷的代码片段向量化,检索时同时匹配规则与近邻样本。重排阶段用 cross-encoder 对候选做精排,过滤掉只是字面相似但语义无关的样本,误报率因此明显下降。
缺陷风险分级与误报控制。早期我们给的告警太多,评审者直接忽略整条流。我们改为三级分级(高/中/低)并要求高优必须带历史依据,中低优合并为折叠摘要。分级阈值用历史采纳数据动态校准:若某类提示连续被驳回超过 N 次,自动降级并进入人工复核队列重新标注。这样把「全盘告警」变成「分级优先」,采纳率显著提升。
与既有评审平台对接。对接最大的坑是协议与鉴权。我们通过采用的 AI 网关接入层把内部多模型的 REST/gRPC 归一化为 OpenAI 风格接口,评审平台只对接一个稳定端点;网关的计量层按「部门—应用—用户」做 token 与配额核算,避免大模型调用把算力打爆。一次真实事故是某仓库批量回刷历史 PR,触发网关限流熔断,限流信号反向驱动底座弹性扩缩容,把突发流量平稳消化,而没有拖垮在线评审。
以下为脱敏示意数据,取自某头部互联网企业两个研发事业部的灰度对照(约三个月窗口):
| 指标 | 改造前 | 改造后 | 说明 |
|---|---|---|---|
| 评审建议采纳率 | 约 38% | 约 71% | 分级后高优提示带依据,评审者更愿意采纳 |
| 缺陷提前捕获率 | 约 22% | 约 58% | 上线前在评审阶段拦住的缺陷占比 |
| 漏审率 | 约 14% | 降至约 4% | 易错模块预测命中的高风险变更被强制提示 |
| 单 PR 评审工时 | 约 26 分钟 | 降至约 11 分钟 | 模型预评审承担了初筛与定位 |
| 线上缺陷回滚率 | 约 9‰ | 下降至约 3.5‰ | 缺陷更早暴露,生产事故减少 |
需要强调的是,这些都是脱敏示意值,用于说明趋势而非审计结论。真正让我们满意的不是单点数字,而是评审者反馈「终于不用从零看 diff 了」。
第一,定位要清楚:大模型是评审辅助而非替代。我们把最终决策权始终留在评审者手里,模型只负责「把可疑点摆到面前并说清理由」,这避免了责任错位,也降低了误报带来的信任损耗。第二,风险分级优于全盘告警——给评审者一堆同类告警等于没给,分级 + 依据 + 折叠才是可用形态。第三,历史缺陷库是金矿但极脏,必须做规则—样本双通道对齐和重排,否则向量检索的噪声会淹没信号。第四,基础设施要分层解耦:我们采用的 AI 私有化部署底座负责推理与算力,采用的 AI 网关负责接入、路由、计量与限流熔断,限流信号反向驱动底座弹性扩缩容,这一协同让稳定性问题在架构层就被吸收,而不是靠业务侧打补丁。
案例片段(已脱敏): 评审提示词(节选,已脱敏): 你是资深评审者。仅基于以下 diff 与上下文,按规则库输出风险点。 每条格式:{file, line, severity: high|medium|low, rule_id, reason, suggestion}。 约束:high 必须引用历史缺陷样本 ID 或具体规则;未知则标 low 并注明不确定。 输出示例: {"file":"order/service.go","line":142,"severity":"high", "rule_id":"CONC-007","reason":"并发写共享 map 未加锁,命中历史缺陷 INC-2291", "suggestion":"对 cache 加 sync.RWMutex 或使用 sync.Map"} 压测结论(脱敏):P99 延迟约 1.8s(单 PR 平均 diff 3.2k tokens), 网关限流阈值设为单应用 200 QPS,触发后 30s 内熔断并回退到纯人工评审。