AI 生成代码已经不是什么新鲜话题了,团队里越来越多人在用 AI 助手写函数、补测试、生成 boilerplate。但随之而来的一个新问题:AI 写出来的代码能跑,可它符合团队规范吗?缩进风格对不对?命名是否遵循项目约定?依赖引入是不是绕过了审核?异常处理有没有按团队标准来?
我见过不少团队,刚开始对 AI 生成代码挺兴奋,结果一 merge 就出乱子。代码能编译、测试能过,但 CR(Code Review)的时候 reviewer 看得直皱眉:命名风格和项目现有代码不一致、import 顺序混乱、缺少团队要求的错误处理包装、甚至把不该提交的调试日志一起生成了。
这篇文章想聊的,就是怎么把“AI 生成代码是否符合团队规范”这件事,从“靠人肉审”变成“靠流程管”。我会先把规范和 AI 生成代码之间的矛盾拆开讲清楚,再给出一套实际可以落地的校验方案:从 lint 规则、pre-commit 钩子、CI 检查,到 Prompt 层面约束 AI 的输出风格,最后结合真实操作流程,说说我踩过的坑和排查技巧。适合正在引入 AI 辅助开发、想把规范建设也一并做起来的团队参考,也适合个人开发者想给自己立点规矩的情况。
1. AI生成代码与团队规范:矛盾的根源
1.1 “能用”和“合规”之间差着一条线
先说个我自己的观察。AI 生成的代码,质量下限其实不低——语法正确性、基本逻辑都没问题,甚至比部分新手写的更“圆润”。但问题恰恰出在“圆润”上:AI 是从海量公开代码里学出来的,它的“默认风格”可能是某个开源项目的风格、可能是某个流行教程的风格、也可能是一种四不像的混合体。而团队规范恰恰是“非默认”的。
举个例子。某团队约定所有函数参数必须有显式类型,并且禁止使用any。AI 生成的代码往往会图省事,给你写一堆any,或者干脆省略类型标注,让 IDE 自动推断。理由很简单——公开代码里这么写的太多了,AI 训练时见过大量类似样本,自然会倾向于这种写法。这跟 AI 懂不懂规范没关系,是训练数据和生成机制决定的:它追求的是“最可能的续写”,不是“最符合你们团队约定的续写”。
所以“能跑”和“符合规范”之间,天然存在一条线。这条线如果没有一个自动化机制去卡,光靠人工 review 盯,少量代码还好,一旦 AI 生成代码量上来,reviewer 会疯掉的。
1.2 团队规范不只是“代码风格”
很多团队理解的规范就是“缩进用两个还是四个空格”“单引号还是双引号”。但真正规范建设成熟的团队,规范远不止这些。至少包括四个层次:
- 风格规范:缩进、引号、分号、命名规则、import 排序、注释格式。这类规则最常见,也最容易自动化检查。
- 架构规范:目录结构、分层职责、模块间依赖方向。比如“service 层不允许直接调用 repository 之外的东西”“工具函数必须放在 utils 目录”“禁止在组件内部定义嵌套函数并作为 prop 传递”。这类规范 AI 最容易违反,因为 AI 不掌握你的项目全貌。
- 依赖与安全规范:新增依赖必须走审批、禁止使用某个版本的第三方库、锁文件必须更新。AI 生成代码时经常“顺手”给你推荐一个包,直接给你 import 进来,但团队可能根本没审核过这个依赖。
- 测试与文档规范:新增公共函数必须有单测、单测覆盖率不得低于某个阈值、对外接口必须补充文档注释。AI 生成代码往往只给实现,不给配套。
理解了这四层,你就知道“测试 AI 生成代码是否符合团队规范”这件事,不是跑一个 formatter 就完事的。它需要一套分级、分层的检查机制。
2. 搭建一套“机器管机器”的校验体系
2.1 从 Lint 到 CI,逐层卡住
既然要靠自动化去卡规范,那第一步就是把规范变成可执行的检查。具体来说,我建议按下面三个层次去搭:
第一层:IDE 和 pre-commit 钩子,让代码在提交前就被拦一次。
这一层是给开发者(以及 AI 辅助写代码的人)用的。在你本地写完代码、准备 commit 时,就自动跑一遍规范检查。常见做法是用 husky + lint-staged(前端)或者 pre-commit 框架(Python),只检查本次提交涉及的改动文件,不检查全量代码,这样速度快,不打扰人。
第二层:CI 流水线,让代码在合并前被正式审查。
这一层是给团队兜底的。即使某位开发者本地跳过了 pre-commit(总有办法跳过),CI 上也会强制跑一遍。流程一般是: checkout 代码 → 安装依赖 → 跑格式检查 → 跑 lint → 跑测试 → 跑覆盖率 → 跑依赖审查。任何一个环节失败,MR 就没法 merge。
第三层:定时巡检“存量代码”,防止 AI 生成的代码通过人工 review 溜进主干后产生“坏味道”。
有些问题在提交时不一定能暴露出来。比如某个 AI 生成的函数,当时没报 lint 错误,但随着后续代码扩展,它变成了“结构性问题”,导致后来者都照着它的错误模式写。这时候就需要一个定期的自动化巡检,把存量代码中“疑似 AI 生成风格”的片段标记出来,比如命名不一致、异常处理缺失、重复代码等,让技术负责人决定是否重构。
2.2 把规范“翻译”成机器能懂的规则
很多人卡在这一步:团队规范是写在 Wiki 里的自然语言,怎么让机器去理解?
答案很简单:把自然语言规范逐条翻译成 lint 规则。听起来工作量很大,但实际上大部分常见规范都有现成规则集覆盖。举个例子:
- “函数必须显式标注返回类型” → TypeScript ESLint 的
explicit-function-return-type规则 - “禁止在循环中定义函数” → 规则
no-loop-func - “import 必须按字母排序” →
import/order插件 - “禁止使用
any” →@typescript-eslint/no-explicit-any - “新增依赖必须经过审批” → 依赖审查工具,比如
depcheck+lockfile-lint
这一步的核心原则是:规范只有变成规则,才算落地。写 Wiki 不算落地,开会宣贯不算落地。一个规范如果没有对应的自动化检查,那它在 AI 生成代码面前就是一张废纸。
2.3 规则不是越多越好,要分级配置
我见过一个团队,刚引入 ESLint 的时候,把社区推荐规则全都extends进去了。结果呢?lint 报了几千个错误,开发者直接躺平,干脆把检查命令从 CI 里移除。这就是典型的“规范过度”。
我的建议是分三级配置:
- error 级:违反就直接报错,阻断合并。只放团队真正在意、且修复成本低的规则。比如命名规范、类型标注、禁止
eval、禁止未使用的变量。 - warn 级:不阻断合并,但会在 CI 报告里显示。适合那些团队想改但一时改不完的规则,先用 warn 暴露问题,再逐步收紧成 error。
- off 级:明确关闭的规则。要么是团队认为没必要的,要么是当前代码库还无法满足的。关闭也是一种管理决策,总比一直报错强。
这样分级的好处是,AI 生成的代码跑一轮 lint,你能很快看出哪些是“硬伤”(error),哪些是“建议”(warn),然后按优先级去处理。
3. 让 AI 先自检:Prompt 约束与自动修复
3.1 在生成阶段就植入规范
既然 AI 的默认风格不一定符合团队规范,那我们能不能在生成之前就给 AI “下规矩”?完全可以,而且效果比事后修复好得多。
核心做法就是:把规范写进系统提示词(System Prompt)里。例如:
你是一个本团队的资深工程师。请遵循以下编码规范生成代码: 1. 所有函数和类成员必须显式标注类型,禁止使用 any。 2. 字符串一律使用单引号,行尾不加分号。 3. import 语句必须按字母顺序排列,先第三方包,后本地模块。 4. 新增外部依赖必须先说明用途,不得直接 import 未出现在 package.json 中的包。 5. 每个公共函数必须编写 JSDoc 注释,包含参数说明和返回值说明。 6. 禁止使用 console.log 调试输出。这样做的逻辑是:AI 生成的文本是逐字预测的,你给它一段规范上下文,它后续生成的代码会倾向于匹配你给的风格。我实测下来,效果比不写 Prompt 直接让 AI 生成,lint 通过率能提高不少。
但注意:Prompt 约束不是万能的。AI 可能在长对话中“忘了”你开头给的规范,也可能对于复杂的架构规范(比如目录分层)根本无从遵循——因为它不了解你的项目全貌。所以“生成阶段约束”是第一步,不是全部。
3.2 AI 自动修复:能修什么、不能修什么
第二个应用点是“自动修复”。不少 lint 工具本身就支持--fix参数,可以自动处理缩进、引号、import 排序、多余分号这类机械性问题。而 AI 辅助工具甚至能更进一步,根据 lint 报错信息自动调整代码逻辑。
我这里有个重要提醒:自动修复分两类,机械修复是可以放心做的,但语义修复要谨慎。
- 机械修复:格式化、排序、重命名局部变量、删除未使用的 import。这种修复不改变代码逻辑,可以批量执行,放心让工具做。
- 语义修复:比如“这个函数未处理异常,请按团队规范补充错误处理”“这个模块的依赖方向不对,请重构”。这种修复会改变代码行为,AI 很可能修出新的问题。建议自动修复后必须有测试兜底,并且人工 review。
我自己在实操中的做法是:lint 环节开启--fix,让工具自动处理风格问题;修复后立刻跑一遍单测;单测过了再交给 AI 做一轮“语义自审”——把规范片段发给 AI,让它对照自查一遍。相当于让 AI 自己当一次 reviewer。这个流程跑下来,绝大多数规范问题都能在提交前解决。
4. 实操流程:从提交到合并的一次完整校验
4.1 定义“可接受的合并门槛”
校验体系搭好了,接下来要回答一个问题:到什么程度才算“符合规范”?
我建议用“门槛”的方式来定义,而不是用“零报错”这种理想化目标。比如:
| 检查项 | 合并门槛 |
|---|---|
| 格式检查 | 0 错误 |
| Lint(error 级) | 0 错误 |
| Lint(warn 级) | 允许 ≤ 3 个,且不允许新增 |
| 单元测试 | 通过率 100%,覆盖率 ≥ 80% |
| 依赖审查 | 新增依赖必须通过审批 |
| 架构约束 | 0 违反 |
这个门槛要根据团队实际情况去调整。如果一开始就定“0 error 0 warn”,团队可能被存量问题淹没;如果定得太松,规范检查就形同虚设。我比较推荐的节奏是:先把 error 级规则收紧,warn 级规则逐条清零,一个季度后再把某条 warn 升级为 error,形成一个阶梯式收紧的循环。
4.2 一次完整的校验过程示例
假设你的团队正在用 AI 生成一个新模块的代码,完整流程可以这么走:
第一步:写 Prompt 时带上规范片段。
请生成一个用户注册的 service 函数。 要求: - 使用 TypeScript,所有函数参数和返回值显式标注类型,禁止 any。 - 错误处理使用团队自定义的 AppError 类,不得直接抛原始 Error。 - 函数内禁止使用 console.log,日志统一通过 logger 服务输出。 - 补充单元测试,覆盖成功和失败两个分支。第二步:AI 生成代码后,先跑一遍本地检查。
npm run lint -- --fix npm run test这时候大概率会发现几个问题,比如:AI 还是误用了any、测试覆盖不完整、import 顺序不对。在本地先修一遍,修完再进入下一环节。
第三步:提交 MR,让 CI 全量检查。
CI 会重新跑一遍所有检查。如果出现“新增警告”,MR 页面会显示警告数量超标,merge 按钮是灰的。开发者需要返回去修复,或者说明为什么这是合理的例外。
**第四步:AI 自审 + 人工审核。”
收到 CI 通过的通知后,建议让 AI 对照团队规范,对 MR 里所有 AI 生成的代码做一轮“自审”。可以问它:“这是你之前生成的代码,请对照以下规范逐条检查,列出不符合的项并给出修改建议。”这一步能发现很多 lint 规则覆盖不到的、属于“架构品味”层面的问题。
第五步:合并,并留下一条“AI 代码占比”记录。
我接触过的一些团队会在这里加一步:统计本次 MR 里有多少行是 AI 生成的,并且由技术负责人抽样复核。不用完全禁止 AI 生成代码,但要确保 AI 生成的部分是“经过同样标准检验的”。
这套流程跑几次之后,团队会慢慢形成一种节奏:AI 生成代码不是“免检产品”,而是和普通团队成员的代码一样,得走同一套质量关卡。
5. 常见问题与排查技巧实录
5.1 AI 生成风格不稳定:同一个功能,两次生成的结果差异很大
这是我遇到最多的情况。原因是 AI 的生成具有随机性,尤其是在没有明确规范约束时,它可能一次生成函数式风格,一次生成类风格,一次用lodash写,一次手写循环。代码功能没问题,但完全不像同一个人写的。
排查思路和解决办法是:
- 在 Prompt 里给出一个你团队现有代码的“范例片段”,让 AI 照着风格写。这比单纯描述规范效果好得多。
- 把团队规范文档直接作为上下文传给 AI(如果工具支持),让它在生成时实时参考。
- lint 规则要能覆盖到风格一致性。比如
consistent-this、func-style这类规则,能强制统一函数声明风格。
5.2 lint 明明过了,但 reviewer 还是觉得不对
这种情况通常是“机器查不到”的层面出了问题。lint 能查格式和明显笔误,但查不出“这个函数太长应该拆开”“这里缺了一个 null 判断”“这层抽象是多余的”。
针对这部分,我有两个办法:
- 架构约束用专门工具做。比如前端可以用
dependency-cruiser检查模块依赖方向;Java 可以用ArchUnit把架构规则写进测试;Python 可以用import-linter。这一类工具能把“service 不能依赖 controller”“utils 不能引用业务模块”这种抽象规范变成可执行断言。 - 给 AI 当 reviewer 提供一份 checklist。把团队在 CR 环节经常提的意见沉淀成一份文档,然后在 AI 自审环节把 checklist 一并丢给 AI。比如:“请检查是否有重复代码、是否有过度设计、是否有潜在的类型收缩问题”。AI 虽然不一定完全正确,但能给你提供一批“可疑点”,再交给人类 reviewer 去确认。
5.3 规则太多导致“规则疲劳”
团队里一旦出现“不管怎么写 lint 都不过”的状态,开发者就会开始想办法绕过检查(比如// eslint-disable-next-line满天飞),规范体系就离失效不远了。
我的经验是:处理规范冲突时,优先调整规则,而不是靠 disable 注释硬扛。如果某个规则频繁被// eslint-disable,要么是规则本身太激进,要么是团队编码习惯需要统一培训,要么是 AI 生成代码时没有正确约束。前两者是管理问题,后者是提示词问题。总之不要放任 disable 注释变成常态。
另外,建议定期统计“违反最多的规则 Top 10”,然后针对性地调整规范重点。比如某条规则一个月被触发了 50 次,说明 AI 或新人对这条不敏感,应该在 Prompt 里重点强调,或者在入职文档里重点说明。
5.4 AI 生成的测试“假通过”
这个问题值得单独拿出来说。AI 生成的单元测试经常出现一种情况:测试跑通了,但覆盖率很低,或者断言根本没有验证核心逻辑。比如测一个“加法函数”,测试断言的是result存在,而不是等于某个具体值。这种测试就是表面功夫。
我的排查技巧是:
- 在 CI 里强制覆盖率报告,不达标的 MR 不允许合并。
- 对于 AI 生成的测试,重点看是不是“断言了预期结果”,而不是“只验证不报错”。如果有条件,可以让 AI 生成“变异测试”风格的输入——故意改坏实现,看测试能不能发现。发现不了的测试就是失效测试。
5.5 “存量规范债”越积越多怎么办
AI 大规模引入后,团队会新增很多 AI 生成的代码,如果前期规范没跟上,几个月后可能出现一批“规范债”——不符合规范的代码已经上线运行,再改起来成本很高。
对这种情况,我建议的做法是采用“圈地”策略:新旧代码分开管理。旧代码按旧标准维护,不强制回改;新代码一律按新规范执行,在 CI 里用git diff检查,只对新增代码跑增量 lint。等到后续重构图腾涉及某块旧代码时,再顺手把它修到新规范下。这个策略能避免团队被遗留问题拖垮,同时保证规范是“向前看”的。
最后分享一点个人体会
我在实际维护这套检查机制的过程中,最大的感悟是:AI 生成代码的规范问题,本质上不是 AI 的问题,是团队规范建设的问题。AI 只是把“规范是否落地”这件事暴露得更明显了。以前人写代码也可能不符合规范,但人至少知道自己在凑合;AI 是不知道自己在凑合的,它会自信地生成一版看起来没问题、实际上和团队约定相悖的代码。所以规范建设的好坏,在 AI 时代被放大了。
这里有一个很实用的小技巧,是一个同事教我的:在 Prompt 里加一句“请假设这段代码会由一位严格的项目维护者审查,并要符合我们团队的公开编码规范。如果你不确定某个写法是否符合规范,请先提问确认,而不是自行假设。”就是这么简单一句话,AI 生成的代码质量会明显提升——因为它从“尽量生成更多”变成了“尽量生成更稳”。你也可以在团队里试试。
说到底,测试 AI 生成的代码是否符合团队规范,核心就是两条:把规范变成机器能执行的检查,让 AI 在生成阶段就参考这些规范。两者都不完美,但配合起来,已经能让“AI 写代码”这件事从“测试”变成“好用”了。