跨模型同行评审:为AI编码智能体构建代码质量闸门
最近一段时间AI coding 类工具的演进速度非常快已经从“单点代码补全”走向了“任务规划—自动编码—测试验证”的完整智能体闭环。很多团队开始把编码智能体接入日常开发流程但随之而来的一个现实问题是模型自主产出的代码谁来保证质量我在使用编码智能体时经常遇到一种现象模型写出来的代码看起来结构完整可一跑测试就报错让同一个模型解释缺陷原因它又沿着原来的错误假设重新推导一遍最后给出一个“看似修复了、实际没修复”的结果。问题根源并不在代码能力而在于单模型自审存在显著的盲区。本文围绕“面向编码 agent 的跨模型同行评审Cross-model peer review for coding agents”展开介绍如何引入另一个独立模型对编码智能体的产出进行交叉审查并给出一个可以运行的 Python 最小实现从协议设计、提示词模板、工程权衡到落地建议逐层拆解。无论你是在做 AI coding 工具的产品研发还是想为团队内部智能体加一道质量闸门本文都有可参考的价值。1. 从单模型自审到跨模型评审1.1 AI 编码智能体为什么需要质量控制过去我们对 AI 编程的认知大多停留在“IDE 里的代码补全”模型根据上文预测下一行代码。而现在的 AI coding agent 已经完全不同它是一个能理解仓库结构、维护多轮上下文、自主生成 coding plan、读写文件、执行命令并运行测试的系统。举个典型例子。开发者在智能体对话窗口里输入“为当前订单模块增加 Excel 导出功能”智能体会先拆解任务生成一个可执行计划然后按计划创建工具类、修改 Controller、补充依赖配置最后还会尝试运行测试来验证结果。整个过程可能涉及十几个文件的变更而且是一次性自动完成的。这种模式下质量风险被显著放大。因为每个步骤都是模型在有限上下文里做出的决策早期一个不准确的判断可能被后续代码补丁逐渐放大甚至形成结构性的错误。如果等到代码合并进主干后再靠人力 code review 去发现问题返工成本会非常高。因此在智能体工作流中加入自动化的质量闸门已经变成工程落地的刚需。放在这个背景下看模型能力本身不是唯一瓶颈如何控制自主产出的可靠性才是编码智能体能否进入生产环境的关键。1.2 单模型自审的盲区最容易想到的质量闸门是让生成代码的模型自己再检查一遍也就是“自反思”。这个思路实现成本低对简单任务也有一定效果但一旦任务复杂度上升问题就会明显暴露。第一个问题来自同源偏置。生成和评审使用的是同一个模型、同一套权重模型对自己刚产出的代码天然存在偏好。评审时它更倾向于维护已有实现而不是从外部视角质疑方案本身。第二个问题是同源上下文错误。编码过程中如果出现了一个错误的技术假设比如误用了某个 API 的返回值结构自审时模型面对的还是同一段上下文很难跳出这个假设去怀疑前提是否成立。于是经常出现“模型解释了错误原因但给出的修复方案仍然建立在错误前提上”的尴尬情况。第三个问题更隐蔽。即便我们给自审环节写了很强的评审提示词模型内部共享的推理路径仍然和生成阶段一致容易出现“形式上满足了评审要求、实质上没有改变决策”的假修复。这也是为什么在某些 benchmark 上模型自反思提升有限甚至出现回退的原因。1.3 跨模型评审核心思想要打破单模型自审的闭环一个直接的思路是借鉴软件工程中的同行评审代码作者不审查自己的代码而是交给另一个没有参与编码的开发者去 review。跨模型同行评审把这个逻辑移植到了智能体场景只不过评审者变成了另一个异构模型。完整的流程大致是------------ 生成代码/修改diff ------------ | 生成 Agent | ------------------------ | 评审 Agent | | Model A | | Model B | ------------ ------------ | 结构化评审意见(JSON) | ---------------------- | | 通过/质量达标 未通过/存在缺陷 | | 结束并合并变更 反馈给生成 Agent A 进行修订后再次评审由于模型 B 和模型 A 在架构、训练数据、对齐方式上存在差异它对 A 的推理盲区更敏感更容易发现边界条件、安全隐患、逻辑漏洞这类单模型自审会忽略的问题。这里需要澄清一点跨模型评审的核心不是“用更大的模型压小模型”而是利用模型之间的差异性形成交叉验证。有时候一个能力稍弱但与生成模型差异明显的评审模型反而比更强的同源模型更能发现有效问题。2. 跨模型评审的系统设计2.1 角色与责任跨模型评审系统至少包含两类角色在复杂流程中还可以进一步扩展。生成者负责根据需求、约束和上下文产出代码变更。它可以是初始编写代码的模型也可以是收到评审意见后执行修订的模型。评审者负责审查生成者交付的代码并输出结构化结论。最简单的设计里生成者和修订者是同一个模型 A评审者是另一个模型 B。如果你想进一步降低同源风险也可以把修订者拆成模型 C也就是“A 生成、B 评审、C 修改”。这种多角色拆分的代价是调用次数增加、成本上升所以在实际项目中我建议从“A 生成、B 评审、A 修订”这种最简模式入手等发现特定模式问题后再引入第三个模型。2.2 工作流协议跨模型评审的完整协议可以表示为一个循环输入任务需求和约束条件。生成者根据需求创建代码变更。如果有测试或静态检查先执行并把执行结果同步给评审者。评审者检查代码给出结构化评审意见。系统判断评审是否通过以及质量评分是否达到阈值。通过则结束流程返回产物未通过则把评审意见转成修订指令。修订者根据意见修改代码回到第 3 步直到通过或达到最大迭代次数。循环层数不能设计得太深。每轮调用都会增加延迟和成本而且评审意见本身可能存在噪声过多迭代可能让代码在反复修改中偏离原始需求。我一般把最大迭代次数限制在 2 到 3 轮宁可允许少量缺陷遗漏到人工评审阶段也不让自动流程陷入无意义空转。2.3 评审结果的结构化表达要让生成者和评审者顺畅协作评审者不能只输出一段自由文本。两个模型之间需要一种可靠的中间协议我建议使用 JSON 作为评审结果的主要格式。评审结果至少应该包含以下字段字段类型说明summarystring评审总体结论摘要verdictenumPASS / CHANGE / REJECTscorenumber质量打分0 到 100issuesarray缺陷列表每项包含位置、类型、描述、优先级suggestionsarray可执行的修改建议model_namestring执行评审的模型标识结构化输出的价值在于系统可以稳定地解析判分、定位问题、归类缺陷并通过阈值控制是否进入修订流程。更重要的是当评审意见需要被追溯审计时结构化格式比自然语言更容易检索和统计。3. 实现一个最小跨模型评审工具3.1 环境与依赖下面我们编写一个最小可运行的 Python 工具用来演示完整的跨模型评审流程。示例代码调用 OpenAI 兼容的接口你可以根据实际使用的模型提供方修改 base_url 和 model 名称。需要准备Python 3.10 或以上版本requests 库python-dotenv 库用来读取环境变量安装依赖pip install requests python-dotenv在项目目录创建.env文件内容如下OPENAI_COMPATIBLE_BASE_URLhttps://api.example.com/v1 API_KEYsk-xxxx GENERATOR_MODELmodel-a REVIEWER_MODELmodel-b这里把生成模型和评审模型分别配置成 model-a 和 model-b实际使用时替换成对应服务商提供的模型名称即可。3.2 项目结构整个示例比较简单只有一个 Python 文件cross_model_review/ ├── .env ├── main.py └── requirements.txtrequirements.txt内容为requests2.31.0 python-dotenv1.0.0如果你不想把依赖版本写死可以只写requests和python-dotenv安装时自动拉取最新版本。3.3 核心代码调用模型先封装一个 call_model 函数统一处理请求发送、超时和响应解析。# 文件路径cross_model_review/main.py import json import os from typing import Dict, List, Optional import requests from dotenv import load_dotenv load_dotenv() BASE_URL os.getenv(OPENAI_COMPATIBLE_BASE_URL, https://api.example.com/v1) API_KEY os.getenv(API_KEY, ) GENERATOR_MODEL os.getenv(GENERATOR_MODEL, model-a) REVIEWER_MODEL os.getenv(REVIEWER_MODEL, model-b) def call_model( messages: List[Dict[str, str]], model: str, temperature: float 0.2, max_tokens: int 4096, response_format: Optional[Dict] None, ) - str: 调用 OpenAI 兼容的 chat/completions 接口。 headers { Authorization: fBearer {API_KEY}, Content-Type: application/json, } payload: Dict { model: model, messages: messages, temperature: temperature, max_tokens: max_tokens, } if response_format: payload[response_format] response_format resp requests.post( f{BASE_URL}/chat/completions, headersheaders, jsonpayload, timeout120, ) resp.raise_for_status() return resp.json()[choices][0][message][content]这个函数的优点是兼容大量使用 OpenAI 协议的模型服务切换模型时只需改配置不需要改业务代码。3.4 核心代码生成、评审、修订、主循环接下来定义四个关键函数。首先是生成代码函数def generate_code(requirement: str, model: str) - str: 根据需求生成初始代码。 prompt f 你是一名资深工程师请根据下面的需求编写完整代码。 需求 {requirement} 要求 1. 只输出代码不要输出解释。 2. 代码需要包含必要的异常处理和边界判断。 3. 如果函数有输入参数请在 docstring 中说明参数含义。 messages [{role: user, content: prompt}] return call_model(messages, modelmodel, temperature0.1)然后是评审函数def review_code(requirement: str, code: str, model: str) - Dict: 使用评审模型对代码进行结构化审查。 prompt f 你是一名严格的代码评审专家。请从正确性、安全性、可维护性、边界条件、性能五个维度 审查下面的代码并输出 JSON 格式的评审结果。 评审结果 JSON 结构如下 {{ verdict: PASS 或 CHANGE 或 REJECT, score: 0, issues: [ {{ dimension: 正确性, severity: high / medium / low, location: 代码片段或行列信息, description: 问题描述, suggestion: 修改建议 }} ], summary: 总体结论 }} 需求 {requirement} 代码 {code} messages [{role: user, content: prompt}] content call_model( messages, modelmodel, temperature0.0, response_format{type: json_object}, ) return json.loads(content)评审提示词里明确要求模型输出 JSON并定义了 verdict、score、issues 等字段这样主流程可以直接解析。接下来是修订函数def revise_code( requirement: str, code: str, review: Dict, model: str, ) - str: 根据评审意见修订代码。 issues_text json.dumps(review.get(issues, []), ensure_asciiFalse, indent2) prompt f 你是一名工程师请根据评审意见修改代码只输出修改后的完整代码。 需求 {requirement} 原代码 {code} 评审意见 {issues_text} 要求 1. 逐条处理评审意见不要遗漏。 2. 只输出修改后的代码不要解释。 messages [{role: user, content: prompt}] return call_model(messages, modelmodel, temperature0.1)最后是主循环负责把上面的函数串起来def run_pipeline( requirement: str, max_rounds: int 3, pass_score: int 80, ) - None: 执行跨模型评审主流程。 print( 第 1 轮生成初始代码 ) code generate_code(requirement, GENERATOR_MODEL) for round_idx in range(1, max_rounds 1): print(f 第 {round_idx} 轮评审 ) review review_code(requirement, code, REVIEWER_MODEL) score review.get(score, 0) verdict review.get(verdict, REJECT) print(f评审结论: {verdict}, 评分: {score}) print(f缺陷数量: {len(review.get(issues, []))}) for issue in review.get(issues, []): print(f - [{issue.get(severity)}] {issue.get(description)}) if verdict PASS and score pass_score: print( 评审通过 ) save_result(code, review) return if round_idx max_rounds: print( 达到最大轮次仍未能通过评审 ) save_result(code, review) return print(f 第 {round_idx 1} 轮修订 ) code revise_code(requirement, code, review, GENERATOR_MODEL) def save_result(code: str, review: Dict) - None: 保存最终代码和评审结果。 with open(result.py, w, encodingutf-8) as f: f.write(code) with open(review.json, w, encodingutf-8) as f: json.dump(review, f, ensure_asciiFalse, indent2) print(结果已保存到 result.py 和 review.json)3.5 运行与验证在main.py底部添加入口if __name__ __main__: demo_requirement 编写一个 Python 函数读取 CSV 文件并统计每列非空值数量要求处理文件不存在和空文件的情况。 run_pipeline(demo_requirement, max_rounds3, pass_score80)运行命令python main.py预期你会看到类似下面的输出 第 1 轮生成初始代码 第 1 轮评审 评审结论: CHANGE, 评分: 65 缺陷数量: 2 - [high] 文件不存在时直接抛出异常未按需求处理 - [medium] 空文件场景下 pandas 读取可能报错缺少边界判断 第 2 轮修订 第 2 轮评审 评审结论: PASS, 评分: 86 缺陷数量: 0 评审通过 结果已保存到 result.py 和 review.json实际输出取决于模型能力但流程本身是确定的。这个最小实现已经具备“生成—评审—修订—循环”的完整闭环你可以在此基础上扩展出更多能力。4. 评审提示词与评价维度设计4.1 通用评审维度在编码智能体场景中评审提示词的质量几乎决定了整个跨模型评审系统的效果。我把评审维度划分为五个核心方向你可以根据团队规范增删。正确性是最基础的维度包括代码是否满足需求描述、核心逻辑是否正确、分支条件是否完整、返回值是否符合预期。安全性关注注入攻击、命令执行、敏感信息泄露、资源释放等问题。可维护性关注命名是否清晰、函数切分是否合理、是否有多余的重复代码。边界条件关注空值、超长输入、并发、网络超时、文件不存在等场景。性能则关注时间复杂度和不必要的资源消耗。在评审提示词中不必要求每个问题都涉及所有维度而是让模型按维度逐项排查。逐维度排查比泛泛批评更能发现问题。4.2 一套可直接复用的评审提示词模板我给出一套比较通用的评审提示词模板你可以直接复制到自己的提示词工程中你是一名代码评审专家。你的任务是根据需求文档对代码进行结构化审查。 请从以下五个维度逐项检查不要遗漏任何维度 1. 正确性代码是否满足需求是否存在逻辑错误 2. 安全性是否存在注入、越权、敏感信息泄露、资源泄漏风险 3. 可维护性命名是否清晰函数是否过长是否存在重复代码 4. 边界条件空值、空文件、超长输入、并发、依赖服务不可用等场景是否考虑 5. 性能是否有明显的时间或空间复杂度优化空间 输出要求 - 使用 JSON 格式输出不要输出额外文字。 - verdict 字段使用 PASS、CHANGE 或 REJECT。 - score 字段为 0 到 100 的整数。 - issues 数组中每条问题必须包含 dimension、severity、location、description、suggestion。 - 如果问题存在description 必须引用具体的代码片段或行列信息。 - summary 字段用一句话总结总体结论。 需求文档 {requirement} 待审查代码 {code}这套模板的关键在于“给模型明确的审查框架 严格的输出格式”比单纯说“请检查这段代码”要可靠得多。4.3 评审与执行验证结合除了让评审模型直接阅读代码更好的做法是把执行结果作为评审上下文。比如让编码智能体先运行 pytest然后把测试输出和代码一起交给评审模型。这样评审模型可以同时看到“代码本身”和“运行结果”两类信息对问题的判断会更准确。在智能体工作流中这相当于构造了一个更完整的评审信息空间评审输入 需求文档 代码 diff 测试运行日志 静态检查结果如果测试失败评审模型可以直接定位到失败的测试用例并指出是生产代码问题还是测试代码问题。这能明显减少误报。5. 跨模型评审在编码智能体工作流中的位置5.1 在 coding plan 阶段介入很多编码智能体在开始写代码前会先输出一个 coding plan把大任务拆解为多个子任务。跨模型评审完全可以作用在 plan 阶段。生成模型 A 输出 coding plan 后评审模型 B 可以先审查计划本身判断子任务拆分是否合理、是否有遗漏约束、执行顺序是否依赖正确。计划阶段评审的成本很低因为还没有代码生成但收益很高一个错误的计划会导致后续所有步骤白做。这种“先评审计划再评审代码”的做法可以理解为把质量闸门前移属于一种预防性控制。5.2 在代码 diff 阶段介入最常见的介入点是代码变更完成之后。此时评审模型查看的是 diff而非完整文件。diff 评审的好处是聚焦模型只需要关注本次改动的部分不会因为仓库过大而分心。在 CI/CD 流程里可以把这个环节做成自动化的 pre-merge 检查。当开发者或智能体提交 PR 时系统自动拉取两个模型一个生成变更一个评审变更。评审通过后才能人工合并。5.3 人机协同边界需要明确的是跨模型评审不是要替代人工 review而是把人工从低效的格式检查、变量命名、重复代码这类机械问题中解放出来让人集中精力解决架构设计、业务语义、产品需求这些更深层问题。最终的合并权应该始终保留在人类工程师手中。模型给出的评审意见再合理也只是“建议”不是“决策”。在工程实践中我会把模型评审结论标记为“自动建议”并保留完整的修改历史方便人工追溯。6. 工程落地中的坑与权衡6.1 成本与延迟跨模型评审相比单模型自审调用次数至少翻倍。每轮迭代要调一次生成模型、一次评审模型如果需要修订还要再调一次生成模型。假设一个任务平均需要两轮评审那么总调用次数大约是 4 到 5 次。对于个人开发者这个成本可能还好但对于每天执行成千上万个任务的自动化平台成本会线性放大。几个控制成本的策略一是在低风险模块使用小参数模型做评审高风险模块才启用强模型二是先做规则过滤比如改动只涉及注释或配置时跳过评审三是限制最大迭代轮数避免模型反复修改产生额外调用。6.2 评审模型的误报与幻觉评审模型本身也会产生幻觉可能给出不存在的缺陷甚至把正确代码当成错误代码。这类误报会让修订模型做无用功严重时还会把原本正确的代码改坏。降低误报的思路是要求评审意见“有证据”。在提示词里明确要求每个 issue 必须引用代码中的具体片段、函数名或行号必须描述出触发场景。没有证据的评审意见系统可以选择忽略。另外可以加一层相似度去重。多轮评审中出现的相似意见如果第一次已经被处理过后续轮次就不应该再重复触发。6.3 上下文长度与多文件评审当代码变更涉及多个文件时简单地把所有文件拼成一个大 prompt 往往不可行。一方面 token 消耗巨大另一方面模型在超长上下文中的关注力会分散评审精度反而下降。推荐策略是将评审拆成两层先对每个关键文件做独立评审再把多个文件的评审摘要汇总给一个“总评审模型”让它针对跨文件一致性和接口兼容性做最终判断。这种分层评审能兼顾细节和全局。6.4 模型选择策略跨模型评审的模型组合不应该是一成不变的。常见的策略包括使用异构模型组合通常是不同厂商或不同架构的模型保证差异度。定期统计评审意见采纳率淘汰总是产生无效意见的模型。针对不同语言和框架选择不同的评审模型比如 JavaScript 项目用一种组合Python 项目用另一种组合。选择模型时不要只看模型排行榜的分数更关键的是在你自己项目数据上的“缺陷发现率”和“误报率”。建立一个小规模的评测集提前验证模型组合的效果是值得做的一件事。7. 最佳实践建议7.1 提示词工程建议基于前面多轮实验我总结了几条提示词设计上的最佳实践。给评审模型一个固定角色比如“高级代码评审专家”有助于稳定输出。要求模型逐维度排查不要一次性笼统评价。强制输出结构化 JSON方便自动化处理。必须引用代码位置和触发场景提升评审意见可执行性。最后在提示词里明确定义“通过”的标准比如评分达到多少、不存在 high 级别缺陷避免模型对阈值产生主观理解。7.2 流程与审计跨模型评审过程应该完整留痕。每次评审都记录评审模型版本、生成模型版本、评审输入摘要、输出 JSON、最终合并结果。这些数据有双重价值一是出现线上事故时可以回溯是哪一轮评审漏掉了缺陷二是可以积累成训练集用来优化未来的评审提示词和模型选择。7.3 渐进式灰度上线如果要在团队内推广跨模型评审不建议一步到位直接拦截所有合并请求。我建议的演进路径是离线阶段阶段对历史 PR 跑一遍跨模型评审对比人工评审结果统计命中率和误报率。建议模式评审结果以 comment 形式出现在 PR 中不阻塞合并观察团队反馈。强制模式对部分高风险模块强制执行未通过则不能合并。全量模式条件成熟后放开到所有模块同时保留人工复核通道。在这个路径里团队可以在每个阶段积累信心也能让工程师逐步接受“自动评审意见”。8. 总结跨模型同行评审本质上是用“模型之间的差异”对抗“单模型推理的盲区”它把代码审查从个人行为变成了结构化的工程流程。本文从为什么需要这种模式讲起给出了一套最小可运行的 Python 实现并围绕评审提示词、系统设计、成本控制、模型选择和实践落地展开了讨论。如果你正在开发 AI coding agent或者想给现有智能体工作流加一道质量闸门建议先从一个小模块开始把生成模型与评审模型跑通再逐步扩展评审维度与迭代策略。技术方案永远没有一步到位的关键是先跑起来拿到真实数据再持续迭代。跨模型评审不会是编码智能体质量控制的终点未来一定会出现更细粒度的评测工具、更智能的缺陷定位方法和更高效的模型协作协议。但无论工具怎么演进“独立评审者 结构化反馈 环环留痕”这套内核都会是值得长期坚持的工程思路。