1. 代码审查这件事,为什么AI切入比写代码更顺
先说一个我观察了很久的现象:过去两年,各种"AI帮你写代码"的工具铺天盖地,但真正在团队里被高频、稳定用起来的,反而是"AI帮你审代码"这一类。Codex 这次把代码审查功能单独拎出来做成一个明确的能力,其实踩中了一个很现实的痛点——写代码是创造,审代码是判断,而判断这件事,AI 的容错空间比创造大得多。
为什么这么说?你让 AI 从零写一个业务模块,它得猜你的架构约定、命名习惯、异常处理策略、依赖版本,任何一处猜错,产出的代码就是"看着能跑、合进去就炸"。但代码审查不一样,审查的输入是已经存在的、上下文完整的代码,AI 不需要凭空创造,它只需要在既定事实的基础上做模式识别和规则比对。这个任务的确定性高太多了。
我拿自己团队的真实数据说话。我们内部做过一轮对比:让同一个模型分别做"生成一个新接口"和"审查一个已有接口",前者一次通过率大概三成出头,后者能挑出有效问题的比例超过七成。差距不是模型能力问题,是任务性质问题。审查本质上是"找茬",而找茬这件事,只要给足上下文,AI 的耐心和覆盖面是碾压人类的——人审代码看半小时就疲劳了,AI 看一万行和看一百行状态一样。
Codex 新增的这个审查能力,核心价值不在于"替代人",而在于把审查的基线抬高。以前代码评审靠人肉盯,漏掉的空指针、边界条件、并发问题,往往要等到线上出事才被发现。现在把 AI 审查挂在提交环节,等于给每一行 diff 都配了一个不知疲倦的第一道筛子。人只需要审 AI 筛完之后剩下的、真正需要业务判断的部分。
这里有个关键认知要先建立起来:AI 代码审查不是"更聪明的 lint",也不是"会说话的静态扫描"。lint 和静态扫描是基于规则的,规则写死了就只查那几类;AI 审查是基于语义理解的,它能读懂"这段代码想干什么",然后判断"这么干会不会出事"。这个区别决定了它的能力边界和落地方式,后面几节我会展开讲。
适合读这篇的人:如果你是小团队里那个既要写代码又要 review 的人,或者是想给 CI 流程加一道智能关卡的技术负责人,再或者你只是好奇"AI 审代码到底靠不靠谱",这篇都会给你能直接抄的配置和踩过的坑。
2. 拆开看:AI 代码审查到底在审什么
2.1 它和传统静态检查的分工边界
很多人第一次用 AI 审查,会拿它跟 ESLint、SonarQube 这类工具比,然后得出"重复了"的结论。这是没搞清楚分工。我习惯用一个类比:静态检查工具像机场安检的金属探测门,规则明确、误报低、只查已知危险品;AI 审查像一个有经验的老安检员,他能看出"这个人神色不对、行李摆放方式可疑"这种规则写不出来的东西。
具体到能力上,两者的边界大致是这样:
| 维度 | 静态检查工具 | AI 代码审查 |
|---|---|---|
| 检查依据 | 预定义规则集 | 语义理解 + 上下文推理 |
| 擅长发现 | 语法问题、已知漏洞模式、代码风格 | 逻辑缺陷、边界遗漏、并发隐患、可读性 |
| 误报特点 | 误报低但漏报高 | 可能误报但覆盖面广 |
| 上下文感知 | 基本没有 | 能读整个文件甚至跨文件 |
| 维护成本 | 规则要人写要人维护 | 靠模型能力,规则维护少 |
我实测下来最典型的例子:一段用了map遍历又内部await的代码,静态检查完全无感,因为它语法合法;但 AI 审查会直接指出"这里在同步遍历里做异步操作,实际不会按预期等待,应该用Promise.all或for...of"。这种问题只有理解了代码意图才能发现。
所以正确的用法不是二选一,而是让静态检查管"确定性问题",让 AI 审查管"语义和逻辑问题",两者串在流水线里,各管一段。
2.2 一次审查请求里,模型实际拿到了什么
要理解 AI 审查为什么有时准有时不准,得先知道它"看到了什么"。当你触发一次 Codex 的代码审查,模型拿到的通常不只是那几行改动,而是一个组合上下文:
- diff 本身:这次改了什么,加了哪些行、删了哪些行
- 改动文件的完整内容:不只是 diff 片段,而是整个文件,这样它才知道新代码在什么环境里运行
- 相关的依赖文件:比如你改了一个函数,它可能去看调用方和被调用方
- 提交信息或 PR 描述:你告诉它"这次改动是为了修什么 bug",它就有了判断基准
- 项目级的约定:如果有配置文件告诉它命名规范、目录结构,它会参考
这个上下文组合决定了审查质量。我踩过的一个坑就是:只把 diff 丢给模型,结果它对着一个孤立的代码片段疯狂报"未定义变量",其实那个变量在文件上方早就声明了。上下文给得越全,误报越低,这是铁律。
2.3 审查结果的三种类型,处理方式完全不同
AI 审查吐出来的问题,我一般分三类处理,这个分类直接决定了你要不要改、怎么改:
第一类是确定性缺陷,比如空指针、数组越界、资源没释放、明显的逻辑写反。这类直接改,不用犹豫,AI 在这类问题上准确率很高。
第二类是风格与可维护性建议,比如"这个函数太长了建议拆分""变量命名不够表意"。这类要看团队约定,AI 的建议不一定符合你们的历史习惯,别盲从。
第三类是需要业务判断的疑点,比如"这里对金额做了四舍五入,是否符合财务精度要求"。这类 AI 只能提示,最终得人来拍板,因为它不知道你的业务规则。
提示:把这三类分开对待,是让 AI 审查真正产生价值的关键。如果你把所有 AI 建议都当"必须改",团队很快会因为噪音太多而关掉这个功能。
3. 把审查挂进工作流:从本地到 CI 的完整落地
3.1 本地预审:提交前先过一遍
最轻量的落地方式,是在本地提交前跑一次审查。这样问题在离开你电脑之前就被拦住了,不会污染远程仓库的历史。我自己的习惯是在pre-commit钩子里挂一个审查脚本,但要注意——别让它阻塞提交,否则模型偶尔抽风或者网络抖动,你就提交不了了。
一个比较稳的做法是:审查结果只做提示,不强制拦截。下面是一个钩子脚本的骨架,思路是拿到暂存的改动,喂给审查接口,把结果打印出来:
#!/bin/bash # .git/hooks/pre-commit # 拿到暂存的 diff DIFF=$(git diff --cached --unified=5) if [ -z "$DIFF" ]; then exit 0 fi # 调用审查(这里用占位命令,实际替换成你的审查入口) echo "$DIFF" | your-review-cli --stdin --format text # 无论结果如何都放行,只做提示 exit 0这里--unified=5是关键,它让 diff 多带 5 行上下文,模型判断更准。默认的 3 行有时候不够,尤其是改动涉及函数签名的时候。
3.2 CI 环节:作为 PR 的第一道关卡
本地审查靠自觉,CI 审查才是真正兜底的。在 PR 流程里挂一个审查 job,每次有人提 PR 就自动跑,结果以评论形式贴回 PR。这样审查记录留在 PR 里,谁改的、AI 提了什么、怎么处理的,全都有迹可循。
配置上有几个参数我建议你重点调:
- 只审增量:别每次全量审,只审这次 PR 的 diff,否则又慢又吵
- 设置严重级别阈值:只有达到某个严重级别的问题才发评论,低级别的攒着
- 限制单次审查的文件数:一个 PR 改了 50 个文件,全丢给模型既慢又容易超上下文,建议分批
我见过最失败的落地案例,就是有人把 AI 审查配成"每个 PR 全量扫描整个仓库",结果每次跑十几分钟,评论里几百条历史遗留问题,团队三天就把它关了。审查要聚焦增量,这是底线。
3.3 审查触发时机的取舍
什么时候触发审查,直接影响体验。我试过三种时机,各有优劣:
| 触发时机 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 提交时(pre-commit) | 问题最早暴露 | 可能拖慢提交 | 个人开发 |
| PR 创建/更新时 | 记录完整、团队可见 | 反馈有延迟 | 团队协作 |
| 合并前强制 | 保证质量门禁 | 可能阻塞发布 | 核心分支 |
我的建议是组合使用:本地做轻量提示,PR 做完整审查,核心分支合并前做强制门禁。三层下来,漏网之鱼基本没有了。
4. 让审查结果可用的几个关键调优
4.1 提示词里必须写清楚的几件事
AI 审查的质量,一半取决于你怎么"问"它。默认的审查提示词往往太泛,导致它什么都想说、什么都说不深。我在实际项目里会把这几件事明确写进审查指令:
第一,明确审查范围。告诉它"只审查本次 diff 引入的问题,不要评论历史代码",否则它会翻出一堆陈年旧账。
第二,明确项目约定。比如"本项目使用 TypeScript 严格模式,禁止 any""异步统一用 async/await,不用回调",把这些写进去,它就不会提不符合你们规范的建议。
第三,明确输出格式。要求它按"文件:行号 | 严重级别 | 问题描述 | 修改建议"的结构输出,这样结果能直接被工具解析,贴到 PR 里也整齐。
第四,明确忽略项。比如"忽略测试文件的命名规范""忽略自动生成的代码",减少噪音。
一个我常用的审查指令模板长这样:
你是一个资深代码审查者。请审查以下 diff,只关注本次改动引入的问题。 项目约定: - 使用 TypeScript 严格模式 - 异步操作统一 async/await - 错误必须显式处理,不允许空 catch 输出格式:每条问题一行,格式为 [严重级别] 文件:行号 - 问题描述 - 建议 严重级别取值:critical / major / minor 如果某类问题不存在,不要强行编造。加上这段之后,我们团队的误报率肉眼可见地降下来了。
4.2 上下文窗口与分批策略
模型能吃的上下文是有限的,一个巨型 PR 塞进去,要么被截断,要么关键信息被稀释。我的处理策略是按文件分批,每个文件独立审,最后汇总。这样每个文件都能拿到完整上下文,判断更准。
分批的时候有个细节:把相关的文件放一批。比如你改了一个工具函数和它的三个调用方,这四个文件应该一起审,模型才能看出"调用方传参和函数签名不匹配"这种跨文件问题。如果按字母顺序机械分批,这种问题就漏了。
4.3 误报治理:怎么让团队不反感
AI 审查最大的敌人不是漏报,是误报。误报一多,团队就形成"AI 说的不用看"的条件反射,功能就废了。我治理误报的几个手段:
- 建立忽略清单:某些文件、某些规则明确不审,写进配置
- 收集反馈闭环:PR 里对 AI 评论点"无用",定期统计哪些类型误报最多,针对性调提示词
- 分级展示:critical 直接标红,minor 折叠起来,别让噪音淹没重点
我实测下来,经过两三轮调优,误报能压到可接受范围。关键是别指望开箱即用就完美,审查提示词是要养的。
5. 实测中那些文档不会告诉你的坑
5.1 模型对"业务语义"的理解是有天花板的
这是我最想强调的一点。AI 审查能发现通用逻辑问题,但对业务语义的理解很有限。举个例子:一段代码把订单状态从"待支付"改成"已取消",语法、逻辑都没问题,AI 不会报错。但如果你们的业务规则是"已发货的订单不能直接取消,必须先走退货流程",AI 根本不知道这条规则,它审不出来。
所以别把 AI 审查当成业务正确性的保证。业务规则类的检查,还是得靠单元测试和人工评审。AI 审查的定位是"通用质量守门员",不是"业务专家"。
5.2 大改动容易触发"过度审查"
当一个 PR 改动量很大时,模型会变得特别"话痨",把一些本来没问题的代码也挑出来说。我分析过原因:改动越大,模型越倾向于"多报一点显得自己有用",加上上下文里信息太多,它抓不住重点。
对策是控制单次审查的改动量。我的经验值是单个审查批次控制在 500 行 diff 以内,超过就拆。拆的时候按功能模块拆,别按行数硬切。
5.3 审查结果的"行号漂移"问题
这个坑很隐蔽。AI 审查返回的行号,是基于你喂给它的那份代码的行号。但如果你在审查之后又改了代码,行号就对不上了,评论会贴到错误的位置。解决办法是审查和评论之间不要有代码变更,或者用 diff 的锚点(比如改动前后的代码片段)来定位,而不是纯行号。
5.4 别让审查拖慢开发节奏
我见过团队把审查配成"必须全部通过才能合并",结果一个 minor 级别的命名建议卡了半小时。审查应该是加速器不是刹车。我的做法是:critical 和 major 必须处理,minor 允许"已知悉但不改",给开发者留出判断空间。
6. 一个可复现的最小落地示例
说了这么多,给一个能直接跑起来的最小配置。假设你用 GitHub Actions,想在 PR 上自动跑审查:
name: ai-code-review on: pull_request: types: [opened, synchronize] jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: 获取本次 PR 的 diff run: | git diff origin/${{ github.base_ref }}...HEAD --unified=5 > pr.diff - name: 调用审查 run: | # 替换成你的审查入口,把 pr.diff 喂进去 your-review-cli --input pr.diff --format markdown > review.md - name: 把结果贴回 PR run: | # 用 gh 或 API 把 review.md 作为评论发出去 gh pr comment ${{ github.event.number }} --body-file review.md这个骨架的关键点:fetch-depth: 0保证能拿到完整历史做 diff,--unified=5给足上下文,审查结果以评论形式回贴。你可以在这个基础上加严重级别过滤、分批逻辑、忽略清单。
跑通之后,我建议先在一个非核心仓库试运行一两周,观察误报情况,调好提示词再推广到主仓库。别一上来就在核心分支开强制门禁,那是给自己找麻烦。
7. 我对"AI 审查比写代码更易落地"的最终判断
回到标题那个判断。我现在的看法是:这个判断成立,但成立的原因不是"审查更简单",而是审查这个任务的反馈闭环更短、容错空间更大。
写代码,AI 错了你要花时间调试、返工,成本高;审代码,AI 多报一条你划掉就行,漏报一条还有人工兜底,成本低。低成本的试错,才是它容易落地的根本原因。Codex 把审查单独做成一个功能,本质上是选了一个"AI 能力已经够用、且落地摩擦最小"的切入点。
但我也要泼盆冷水:AI 审查不会让代码评审这件事消失,它只是把评审的起点抬高了。以前人要从头看到尾,现在人只需要看 AI 筛出来的重点。省下来的是体力,不是判断力。真正需要人来做的架构决策、业务权衡、团队约定,AI 一样都替代不了。
我自己的用法是把它当成一个"永远在线、不会累、但偶尔会瞎说的初级评审员"。它提的每一条我都看,但改不改、怎么改,还是我说了算。这个定位摆正了,它就是个好帮手;摆不正,要么被它的噪音烦死,要么被它的漏报坑死。