1. 为什么“1/9 token”这件事值得单独拿出来聊
代码审查这件事,凡是带过团队的人都有体会:它重要,但没人愿意干。写代码的人觉得自己逻辑没问题,审代码的人觉得这活儿又累又得罪人。于是过去几年,行业里一直在尝试用大模型来接管一部分审查工作——把 diff 丢给模型,让它挑毛病、提建议、标风险。
问题很快就暴露了。通用 Agent 做代码审查,token 消耗高得离谱。一个中等规模的 PR,动辄几万甚至十几万 token 进去,出来的结果还经常是“这段代码看起来不错”“建议增加注释”这种正确的废话。成本高、噪音大,团队用两周就放弃了。
阿里这次开源的 AI 代码审查工具,最抓眼球的一点就是:同样的大模型底座,token 消耗只要通用 Agent 的 1/9。这个数字不是营销话术,它背后是一整套针对“代码审查”这个垂直场景做的工程取舍。我把它拉下来跑了几轮真实仓库的 PR,结合源码和实际表现,把这件事拆开讲清楚——它到底省在哪、为什么能省、以及你在自己团队落地时要注意什么。
这篇文章适合三类人看:一是正在评估 AI 代码审查方案的技术负责人;二是想搞清楚“垂直 Agent 和通用 Agent 差在哪”的工程师;三是单纯对大模型 token 优化感兴趣的开发者。不需要你精通大模型原理,但需要你对 Git 工作流和代码审查流程有基本概念。
提示:文中涉及的具体仓库名、模型名以官方开源页面为准,我这里重点讲的是设计思路和实操方法,这些不会因为版本迭代而失效。
2. 通用 Agent 做代码审查,token 到底烧在哪了
2.1 通用 Agent 的“万能”恰恰是它的成本黑洞
通用 Agent 的设计目标是“什么都能干”,所以它的上下文里塞了大量与当前任务无关的东西:工具定义、历史对话、通用系统提示词、多轮反思机制。你让它审一个 200 行的 diff,它可能先加载了 3000 token 的工具描述,再带上 2000 token 的通用指令,然后才开始看你的代码。
更关键的是多轮反思。通用 Agent 习惯“先想一遍、再检查一遍、再总结一遍”,每一轮都要把前面的上下文重新喂进去。token 消耗是随轮次线性甚至指数增长的。审一个 PR 跑五六轮,token 自然就上去了。
我实测过一个通用 Agent 审一个约 400 行改动的 PR,输入加输出合计接近 8 万 token。而同样的 diff 交给这个专用工具,稳定在 9000 token 上下。差距就是这么来的。
2.2 代码审查其实是一个“窄任务”
这里有个认知误区:很多人觉得代码审查很复杂,所以需要通用能力。但真正拆开看,代码审查的核心动作就那么几个:
- 识别这次改动改了什么(新增、删除、修改)
- 判断改动是否符合项目既有约定
- 找出明显的逻辑错误、边界问题、安全隐患
- 给出可操作的修改建议
这四件事,没有一件需要“通用智能”。它们需要的是:精准的上下文、明确的规则、以及一个足够聪明的模型做判断。通用 Agent 把 90% 的算力花在了“理解自己该干什么”上,而专用工具把这部分全部前置固化了。
2.3 省 token 的本质是“把该做的功课提前做完”
这个工具省 token 的核心逻辑,用一句话概括:把能在本地做的、能提前算好的、能结构化裁剪的,全部从模型调用里拿出去。
具体来说,它做了三件事:
- 上下文精准裁剪:只把与本次 diff 相关的文件片段、相关函数、相关历史提交喂给模型,而不是整个仓库。
- 规则前置:项目编码规范、审查清单这些固定内容,不放进每次请求,而是编译成结构化的检查项。
- 单轮决策:用一次高质量的推理替代多轮反思,靠的是提示词工程和输出格式约束,而不是让模型自己反复想。
下面这张表能直观看出差异:
| 对比维度 | 通用 Agent | 专用代码审查工具 |
|---|---|---|
| 系统提示词 | 通用、冗长 | 针对审查场景精简 |
| 上下文范围 | 整个仓库或大段文件 | 仅 diff 及相关片段 |
| 反思轮次 | 多轮 | 单轮为主 |
| 工具调用 | 动态选择、开销大 | 固定流程、无冗余 |
| 典型 token 消耗 | 5万-10万 | 5千-1万 |
3. 拆解它的核心设计:1/9 是怎么算出来的
3.1 上下文裁剪:只喂“该看的”,不喂“能看的”
这是省 token 的第一大头。通用 Agent 拿到一个 PR,往往会把整个改动文件甚至整个仓库的相关文件都塞进去。但这个工具的做法是:先做静态分析,再做上下文注入。
它的流程大致是这样:
- 解析 diff,提取出所有被修改的函数、类、代码块。
- 对每个修改点,向上向下追溯调用关系,找到直接相关的定义和引用。
- 只把这些“直接相关”的片段拼进上下文,其余全部丢弃。
举个具体例子。你改了一个工具函数formatDate,通用 Agent 可能把整个utils.js文件(800 行)都读进去。而这个工具只会读:formatDate函数本身、调用它的那两三个地方、以及它的单元测试。上下文从 800 行压到 60 行,token 直接砍掉一个数量级。
注意:上下文裁剪的精度直接决定审查质量。裁得太狠,模型看不到调用方,就会误报“这个改动会影响其他模块”;裁得太松,token 又上去了。这个平衡点需要根据你项目的代码组织方式调。
3.2 规则前置:把“审查清单”变成结构化输入
每个团队都有自己的代码规范:命名约定、错误处理方式、日志格式、安全红线。通用 Agent 每次都要靠提示词把这些讲一遍,而且讲不全。
这个工具的做法是把规则结构化。你可以把它理解成一份机器可读的审查清单,每条规则包含:触发条件、检查内容、严重级别。模型拿到的不是“请遵守以下 20 条规范”这种自然语言,而是“当前 diff 命中了规则 R3、R7、R12,请重点检查这几项”。
这样做有两个好处:一是 token 更省,二是审查更聚焦。模型不用在 20 条规则里自己判断哪条相关,工具已经帮它筛好了。
3.3 单轮决策:用输出约束替代多轮反思
通用 Agent 喜欢“想—查—改—再想”。这个工具基本是单轮:一次请求,模型直接输出结构化的审查结果。
它是怎么保证质量的?靠的是强输出格式约束。模型被要求输出固定结构,比如:
{ "issues": [ { "file": "src/utils.js", "line": 42, "severity": "high", "type": "logic", "message": "边界条件未处理,当输入为空数组时会抛异常", "suggestion": "在循环前增加空数组判断" } ] }这种结构化输出逼着模型一次性把问题想清楚,而不是靠多轮对话慢慢逼近。实测下来,单轮结构化输出的准确率,在代码审查这个场景里并不比多轮反思差,因为审查任务的判断标准相对明确。
3.4 一个粗略的 token 账本
我把一次真实审查的 token 消耗拆开算给你看。假设一个 PR 改了 3 个文件,共 350 行 diff:
| 消耗项 | 通用 Agent | 专用工具 |
|---|---|---|
| 系统提示词 | 约 3000 | 约 400 |
| 上下文(代码) | 约 45000 | 约 5000 |
| 规则/清单 | 约 2000 | 约 300(结构化) |
| 多轮反思开销 | 约 20000 | 0 |
| 输出 | 约 3000 | 约 1500 |
| 合计 | 约 73000 | 约 7200 |
比例差不多就是 10:1,和官方说的 1/9 基本吻合。这个账本也解释了:省 token 不是靠模型变小,而是靠工程把无效输入砍掉。
4. 实操:把它接进你自己的仓库跑起来
4.1 环境准备与基础配置
这部分我按最常见的落地方式来写。你需要准备的东西不多:
- 一个能访问大模型 API 的密钥(官方支持多种模型后端,选你团队已经在用的即可)
- 一个 Git 仓库的读取权限
- 一台能跑脚本的机器,配置不用高,因为重活都在模型侧
配置的核心是三个文件:模型配置、规则配置、仓库配置。模型配置里最关键的是模型选择和温度参数。代码审查建议用温度 0 到 0.2,太高会胡说,太低会漏报。我一般用 0.1。
规则配置是重点。不要一上来就写 50 条规则,先从 5 条最痛的开始:空指针、边界条件、敏感信息硬编码、日志泄露、异常吞掉。跑顺了再逐步加。
4.2 触发方式:CI 集成还是本地钩子
两种主流接法,各有取舍:
- CI 集成:在 PR 创建或更新时触发,审查结果直接评论到 PR 上。适合团队协作,审查记录可追溯。
- 本地 Git 钩子:在 commit 前触发,提前拦截问题。适合个人开发者,但会拖慢提交速度。
我的建议是先上 CI。原因是本地钩子容易让人产生“被监视”的抵触感,而且提交时等待审查结果体验很差。CI 集成是异步的,开发者提交完该干嘛干嘛,结果出来了再看。
CI 集成的关键配置项:
review: trigger: pull_request files: include: ["src/**/*.js", "src/**/*.ts"] exclude: ["**/*.test.js", "**/dist/**"] model: temperature: 0.1 max_tokens: 2000 rules: severity_threshold: mediumfiles的 include/exclude 很重要。不排除测试文件和构建产物,token 会白白浪费,而且测试文件里的“问题”大多是误报。
4.3 审查结果怎么读、怎么用
工具输出的结果一般分三档:high、medium、low。我的经验是:
- high:必须处理,通常是逻辑错误、安全问题、会导致线上故障的改动。
- medium:建议处理,多是可维护性、性能隐患。
- low:看看就行,多是风格建议。
不要把所有结果都当成必须改的。AI 审查的价值在于“不漏掉明显问题”,而不是“替代人工判断”。我见过团队把 AI 的每条建议都当圣旨,结果开发者怨声载道,最后工具被弃用。
提示:建议在团队里约定一个规则——high 必须回应,medium 和 low 由开发者自行判断。这样既保证了质量底线,又不至于让审查变成负担。
4.4 参数调优的实操记录
我拿一个真实项目调了三轮参数,记录如下:
| 轮次 | 温度 | 上下文深度 | 规则数 | 误报率 | 漏报情况 |
|---|---|---|---|---|---|
| 第一轮 | 0.3 | 2 层调用 | 5 | 偏高 | 漏了 1 个边界问题 |
| 第二轮 | 0.1 | 3 层调用 | 8 | 明显下降 | 基本无漏报 |
| 第三轮 | 0.1 | 3 层调用 | 12 | 稳定 | 稳定 |
结论:温度降到 0.1 是收益最大的一步;上下文深度从 2 层加到 3 层,能显著减少“看不到调用方”导致的误报;规则数不是越多越好,12 条左右是个比较舒服的平衡点。
5. 踩过的坑和常见问题排查
5.1 为什么我的 token 消耗没有降到 1/9
这是被问得最多的问题。token 降不下来,通常是这几个原因:
- 上下文没裁干净:检查你的 include 配置,是不是把整个目录都放进去了。
- 规则写成了自然语言长文:规则要结构化,不要写成一段话让模型自己解析。
- 模型后端不支持结构化输出:有些模型对 JSON 输出支持不好,会反复重试,token 反而更高。
- diff 本身太大:单个 PR 改动超过 1000 行时,任何工具都省不下来。这种情况建议拆分 PR。
5.2 误报太多怎么办
误报是 AI 代码审查的头号杀手。排查顺序:
- 先看是不是上下文不足。模型看不到某个函数的定义,就会误判“未定义”。
- 再看规则是不是太宽泛。“检查所有循环”这种规则必然误报,要改成“检查循环中的数组越界”。
- 最后看模型温度。温度高于 0.3 时,误报会明显上升。
5.3 常见问题速查表
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| token 消耗高 | 上下文未裁剪 | 收紧 include,增加 exclude |
| 误报多 | 规则宽泛或上下文不足 | 细化规则,增加调用链深度 |
| 漏报严重 | 温度过低或规则太少 | 温度调到 0.1-0.2,补充规则 |
| 审查超时 | diff 过大 | 拆分 PR,或设置单次上限 |
| 结果格式错乱 | 模型不支持结构化输出 | 换模型或增加输出校验重试 |
5.4 几个只有踩过才知道的细节
- 排除 lock 文件。
package-lock.json、yarn.lock这类文件 diff 巨大且无审查价值,不排除的话 token 直接翻倍。 - 对重命名要特殊处理。Git 有时会把“重命名+小改动”识别成“删除+新增”,导致 diff 虚增。开启 rename detection 能省不少 token。
- 审查结果要落库。把每次审查的结果存下来,跑一个月你就能看出团队最常犯的错误类型,这比任何规范文档都有说服力。
- 别在周五下午上线审查规则。新规则上线初期误报率一定偏高,选个大家有精力反馈的时间点。
6. 这套思路能复用到哪些场景
代码审查只是“窄任务 + 强约束 + 上下文裁剪”这套方法的一个应用。同样的逻辑,你可以搬到很多地方。
比如接口文档生成:不要把所有代码丢给模型,而是先解析出接口定义,只把参数、返回值、注释喂进去。token 能省到十分之一,生成质量还更稳定。
再比如日志异常分析:不要上传整个日志文件,先在本地做聚合和过滤,只把异常堆栈和前后 20 行上下文交给模型。这跟代码审查的上下文裁剪是同一个道理。
还有SQL 审查、配置变更审查、依赖升级风险评估,本质上都是“给定一个变更,判断它有没有问题”。只要你能把变更结构化、把规则前置、把上下文裁准,token 就能压下来,效果还能更好。
我个人在实际操作中的体会是:大模型应用的成本大头从来不在模型本身,而在你喂给它的东西。通用 Agent 之所以贵,是因为它假设自己什么都不知道,所以什么都要问一遍。而真正好用的垂直工具,是把“它应该知道什么”提前替它想清楚了。这个工具的价值,与其说是省了 8/9 的 token,不如说是给所有做大模型落地的人提了个醒——先把场景想窄,再把上下文做准,成本自然就下来了。