
最近在做 Agent 评测与推理链路优化时我发现一个很典型的瓶颈大模型生成答案的能力进步很快但很多错误并不是“不会做”而是“答完就交卷”缺少一道检查动作。斯坦福有一篇关于 LLM-as-a-Verifier 的论文最近讨论度很高核心观点非常直接验证Verification这个环节同样可以 Scaling。也就是说不只在生成侧增加计算资源在验证侧投入更多推理计算也能稳定提升最终结果质量。本文会从概念、论文思路、最小可运行代码、Agent 落地和常见坑位几个方向展开。无论你是做大模型应用开发、Agent 编排还是偏算法侧的评测工作都可以把这套“生成—验证—修正”的流程借鉴到自己的项目里。1. 背景为什么“验证”成了大模型应用的新焦点1.1 生成能力过剩验证能力不足过去一年多我们习惯了用“生成”解决问题让模型写代码、做数学题、抽信息、写摘要。模型也确实变强了但一个扎心的现象是你让同一个模型把一道题做两遍它可能给出两个不一样的结果而且它自己无法判断哪个更可靠。这就引出一个问题模型缺的不是“再生成一次”的能力而是“判断这次生成对不对”的能力。很多团队在调 Agent 的时候把精力都花在换提示词、换模型、加工具调用上却忽略了一个关键节点结果出来之后有没有人或者系统帮它把关。其实人类做题时也有类似习惯——先写草稿再代入检查。大模型应用里缺的正是这个“代入检查”的环节。1.2 LLM-as-a-Verifier 的基本含义LLM-as-a-Verifier字面意思是“把大模型本身当作验证器”。传统做法里验证往往依赖规则、单元测试、数据库约束或者人工审核。而 LLM-as-a-Verifier 的思路是既然大模型能读题、能推理那它就也能检查另一份解答是否正确。这和我们熟悉的 LLM-as-a-Judge 有相似之处但侧重点不同。Judge 更偏向“两个答案哪个更好”是一种比较式的评价Verifier 更偏向“这个答案是否真的正确”是一种绝对式的检查。在代码场景里Verifier 可以模拟 Code Review在数学场景里Verifier 可以扮演“代课老师”在 Agent 场景里Verifier 可以充当“质检员”。1.3 验证为什么要单独拆出来很多人会把“生成”和“验证”混在一起让模型“先做一遍再自己检查”。这当然可以但问题是同一个模型如果自身存在知识盲区或推理偏好它的自我检查往往只是把错误理由换一种说法再输出一次。把验证拆出来用独立流程、独立提示词、甚至独立模型来做本质上是在做“职责分离”。生成侧可以追求发散、多采样、探索多种方案验证侧可以追求严格、保守、逐条核对。两个环节用不同的采样参数、不同的系统提示词往往比一个“万能”提示词更稳定。2. 核心概念拆解Verifier、Reward Model、Critic 之间的关系2.1 三种“验证器”形态的对比在工程上你可能会听到几个相近的术语Verifier、Reward Model、Critic。它们是不同训练背景下的叫法但都指向同一个功能给一个结果打分或判断对错。术语来源背景输入输出典型用途Verifier推理/评测问题 候选答案正确/错误或分数选出最终答案Reward ModelRLHF 训练提示词 回答标量奖励强化学习训练信号CriticActor-Critic状态/动作价值估计或批评意见强化学习、Agent 反思对于大部分应用开发同学不需要去严格区分这几者的训练细节。你只需要记住一个判断标准如果这个东西是在“推理结束后检查答案”那它就是 Verifier如果它参与模型训练阶段给梯度提供信号它就更接近 Reward Model。2.2 Generation 与 Verification 的职责分离一个标准的“生成—验证”管道通常长这样生成阶段对同一个问题做多次采样得到 N 个候选答案。验证阶段验证器依次检查每个候选答案给出正确性分数或结论。决策阶段根据验证分数选出最高分答案或者把低于阈值的答案打回重写。这里有一个很容易忽略的点生成阶段需要“多样性”验证阶段需要“确定性”。如果生成时温度太高候选答案可能离谱如果验证时温度太高打分可能忽高忽低。所以最佳实践是生成用 0.7~1.0 的温度验证用 0.0~0.2 的温度。2.3 Self-Verification 与外部验证器的差别Self-Verification 的意思是模型自己验证自己的答案这种方式的优点是成本低、链路短不需要额外接入规则或工具。缺点是同源模型的盲区可能重叠容易“自信地错”。外部验证器则可能是另一套规则引擎、另一个模型、或者一系列工具校验。比如在代码任务里外部验证器可以真正把代码跑一遍——这比任何语言模型判卷都可靠。在实际项目里我的建议是能用工具验证的优先用工具工具覆盖不到的再用 LLM 验证器最后才考虑纯自验证。3. LLM-as-a-Verifier 论文思路的通俗解读3.1 论文想回答的核心问题最近被频繁讨论的斯坦福论文方向就是 LLM-as-a-Verifier。不同平台对论文细节的转述有差异但核心问题非常一致把更多计算资源投入到“验证”这一侧能不能像“生成”侧一样带来稳定且可预期的效果提升这个问题之所以重要是因为过去大家默认“模型强 生成结果强”。论文试图证明的不只是“验证有用”而是“验证也是一条可以 Scaling 的路线”。换句话说当生成模型规模受限或者你无法换更大的模型时你仍然可以通过增强验证环节把整体系统精度往上推。论文的具体实验设置、基座模型和榜单数字需要以原文为准。这里我不转述尚未确认的对比结果只讲这套思路里的通用方法论。3.2 验证器可以怎么训练论文思路里验证器通常有两种构建方式。第一种是提示词方案直接在推理阶段让模型扮演验证器输出分数和理由。这种方式最轻量不需要训练适合快速验证 idea。第二种是微调方案构造一批“问题—候选答案—标注”三元组用标注数据训练一个专门的验证模型。这种方式效果通常更稳定但需要收集标注、划分训练集、做质量校验成本高很多。工程上一般先跑第一种确认验证器真的能区分好答案和坏答案再决定要不要投入资源做第二种。3.3 为什么说“验证也能 Scaling”Scaling 这个词在这一两年被反复使用大家熟悉的是“模型越大效果越好”。但论文思路里的 Scaling 指的是验证侧的计算量比如增加验证器采样的次数、用更强的模型做验证、在一个答案上做多轮验证再综合判断。可以这样理解当我们面对一个难题时人类不一定会做但往往会“检查”。检查得越仔细、维度越多发现错误的概率越高。LLM-as-a-Verifier 就是把这种直觉形式化验证并不是一次性的打分动作而是一个可以分配更多计算资源的独立过程。当然这并不意味着验证资源可以无限堆。验证效果也会有边际递减所以设计时要明确“验证到什么程度就够用”而不是盲目堆 token。3.4 对 DeepSeek 自验证方向的启发项目标题里提到的“DeepSeek 自验证超 Fable5”可以理解为在自验证对比实验中DeepSeek 系列模型通过引入验证环节取得了更好的表现。Fable5 到底是哪个模型、对比条件是什么以原始评测为准。我们更值得关注的是“自验证”这条路是否可复制。DeepSeek 这类强推理模型的输出往往包含完整推理链这给验证器提供了很好的素材验证器不仅能看最终答案还能逐步检查推理过程。这也是为什么自验证在数学、逻辑推理、代码任务上效果更明显——因为这些任务有明确的“对错标准”验证器能抓住具体的步骤错误。如果你本地已经部署了 DeepSeek 模型或者使用 DeepSeek 开放平台的 API完全可以直接复现下面第四节的最小验证流程。4. 实战搭建一个最小可运行的验证器流程4.1 方案设计与技术选型为了让流程足够通用我选择用 OpenAI 兼容接口来调用模型。这样既能对接 DeepSeek 开放平台也能在本地通过 Ollama、vLLM 等工具启动兼容服务代码基本不用改。整个实验分成三步先生成多个候选答案再让验证器逐个打分最后根据分数选出最终答案。我们用一个简单的数学应用题来演示一个两位数十位数字与个位数字之和是 11十位数字比个位数字大 5求这个数。这个题目足够简单方便观察验证器的判断逻辑。4.2 环境准备与依赖安装本文示例以 Python 3.10 环境为例主要依赖是 openai SDK 和 python-dotenv。pip install openai python-dotenv在项目根目录创建 .env 文件# 文件路径.env DEEPSEEK_API_KEYsk-xxxxxxxx DEEPSEEK_BASE_URLhttps://api.deepseek.com需要说明的是不同模型的版本和接口地址变化较快这里只是示例思路实际使用时请以 DeepSeek 开放平台官方文档为准。模型名我在示例里用deepseek-chat如果你的账号下模型名不同替换成对应模型名即可。如果你本地部署了模型也可以把 base_url 换成本地服务的地址例如 Ollama 的 OpenAI 兼容地址是http://localhost:11434/v1模型名换成你本地拉取的模型名称。4.3 第一步生成多个候选答案生成阶段的目的是拿到多个风格不同、思路不同的候选答案。这里通过调整 temperature 来控制多样性。# 文件路径examples/generate_candidates.py from openai import OpenAI client OpenAI( api_keyyour-api-key, base_urlhttps://api.deepseek.com, ) def generate_candidates(problem: str, model: str deepseek-chat, n: int 5) - list[str]: candidates [] for i in range(n): resp client.chat.completions.create( modelmodel, messages[ {role: system, content: 你是一位严谨的数学解题助手。}, {role: user, content: f请解决下面的问题给出详细步骤。\n\n{problem}}, ], temperature0.7 i * 0.1, max_tokens1024, ) candidates.append(resp.choices[0].message.content) return candidates if __name__ __main__: problem 一个两位数十位数字与个位数字之和是 11十位数字比个位数字大 5求这个数。 for idx, cand in enumerate(generate_candidates(problem)): print(f 候选答案 {idx 1} ) print(cand)这段代码里有两个关键参数temperature控制生成随机性max_tokens控制输出长度。生成阶段允许模型展开思路所以 token 给得比较宽裕。4.4 第二步用 LLM 作为验证器打分验证器的提示词是整个流程里最重要的部分。核心要求是先检查再打分禁止跳过推理直接给结论。# 文件路径examples/verify_answer.py from openai import OpenAI client OpenAI( api_keyyour-api-key, base_urlhttps://api.deepseek.com, ) def verify_answer(problem: str, candidate: str, model: str deepseek-chat) - dict: verifier_prompt f你是一个严格的答案验证器。请逐步检查下面的解答是否正确地解决了问题。 【问题】 {problem} 【待检查的解答】 {candidate} 请按以下步骤输出 1. 重新整理问题要求说明题目到底在问什么。 2. 逐条核对解答中的关键步骤指出每一步是否合理。 3. 指出错误或漏洞如果没有错误请明确说明“未发现明显错误”。 4. 最后单独一行输出分数xx其中 xx 是 0 到 100 的整数。 resp client.chat.completions.create( modelmodel, messages[ {role: system, content: 你只做验证工作不生成新解答。}, {role: user, content: verifier_prompt}, ], temperature0.0, max_tokens1024, ) return {text: resp.choices[0].message.content}为什么强制验证器“先整理题目要求”因为很多验证错误来自验证器没理解题目导致把对的答案判成错的。先复述题目等于让模型在回答问题前先对齐目标。4.5 第三步聚合结果并选择最终答案拿到 N 个候选答案的验证分数后最简单的策略是选最高分。但为了后面方便做日志分析我会把验证文本也一起保留。# 文件路径examples/select_best.py import re def extract_score(text: str) - float: # 优先读取“分数xx”这种格式 m re.search(r分数[:]\s*(\d(?:\.\d)?), text) if m: return float(m.group(1)) # 兜底读取最后一次出现的数字 nums [float(x) for x in re.findall(r\d(?:\.\d)?, text)] if nums: return max(min(nums[-1], 100.0), 0.0) return 0.0 def select_best_answer(problem: str, candidates: list[str]) - dict: results [] for cand in candidates: info verify_answer(problem, cand) score extract_score(info[text]) results.append({score: score, answer: cand, verdict: info[text]}) results.sort(keylambda x: x[score], reverseTrue) return results[0]这里需要注意分数提取的正则表达式要跟验证器提示词里的输出格式保持一致。如果你想让解析更稳可以要求验证器最后输出 JSON然后用json.loads解析。4.6 运行与结果分析把三部分串起来运行# 文件路径examples/main.py from generate_candidates import generate_candidates from select_best import select_best_answer problem 一个两位数十位数字与个位数字之和是 11十位数字比个位数字大 5求这个数。 candidates generate_candidates(problem, n5) best select_best_answer(problem, candidates) print(最终选择的答案) print(best[answer]) print(f验证分数{best[score]})预期结果是大部分候选答案都能正确得到 83验证器会给高分个别候选如果过程有跳步验证器会指出问题并给低分。最终选出的答案大概率是正确的。这个最小流程的可贵之处在于它不依赖任何特定模型。你完全可以把生成侧和验证侧换成不同的模型例如用强模型验证弱模型的输出这在成本敏感场景里很常见。5. 自验证循环让模型自己检查并修正5.1 从“一次生成”到“生成-验证-修正”第四节只做了“选最佳”还没有真正利用验证意见改进答案。在 Agent 场景里更常见的是“生成—验证—修正”循环验证器发现错误后把具体意见反馈给生成侧生成侧据此修改然后再验证直到分数达标或达到最大轮数。这种循环类似于人类写完代码后 review再根据 review 意见改代码。它的好处是验证器的错误信息被充分复用而不是简单抛弃低分候选。5.2 实现一个简单的自验证循环下面代码演示了如何在生成和验证之间来回迭代。# 文件路径examples/self_verify.py from openai import OpenAI from generate_candidates import generate_candidates from verify_answer import verify_answer from select_best import extract_score client OpenAI( api_keyyour-api-key, base_urlhttps://api.deepseek.com, ) def self_verify_and_revise(problem: str, model: str deepseek-chat, max_rounds: int 2) - str: answer generate_candidates(problem, n1, modelmodel)[0] for round_idx in range(max_rounds): verdict verify_answer(problem, answer, modelmodel) score extract_score(verdict[text]) print(f第 {round_idx 1} 轮验证分数{score}) if score 90: print(验证通过返回当前答案。) return answer revise_prompt f你上一轮的解答被验证器给出了 {score} 分。请参考验证意见修正解答。 【问题】 {problem} 【上一轮解答】 {answer} 【验证意见】 {verdict[text]} 请输出修正后的完整解答不要只写修改说明。 resp client.chat.completions.create( modelmodel, messages[ {role: system, content: 你是答题者请根据验证意见修正答案。}, {role: user, content: revise_prompt}, ], temperature0.3, max_tokens1024, ) answer resp.choices[0].message.content return answer if __name__ __main__: problem 一个两位数十位数字与个位数字之和是 11十位数字比个位数字大 5求这个数。 print(self_verify_and_revise(problem))这里有一个细节修正阶段的 temperature 我用的 0.3比生成阶段低。原因是修正任务有明确的参考意见不需要太多发散低温度能避免把原本正确的部分改坏。5.3 自验证在数学与代码场景中的应用自验证循环最适用的场景是那些有明确“对错标准”的任务。数学题可以代入验证代码题可以运行测试数据库任务可以检查影响行数信息抽取任务可以核对原文出处。对于开放式写作、文案生成这类任务自验证效果会差很多因为“对错”标准模糊验证器只能给出主观意见。所以我的建议是先判断任务是否具备客观正确性再决定要不要上自验证。没有客观标准时验证器更适合用来做质量筛选而不是纠错。6. 在 Agent 工作流里落地验证器6.1 Agent 为什么需要验证环节Agent 的核心特点是“多步决策 工具调用”。每走一步都可能产生错误调用参数拼错了、检索结果选错了、工具返回理解错了。如果不在每个关键节点加验证错误会沿着链路累积最终输出一个看似完整、实则不可用的结果。验证器在 Agent 里可以充当三类角色步骤验证器验证某一步工具调用是否合理。结果验证器验证最终答案是否满足用户原始需求。回溯验证器发现当前路径走不通时输出诊断信息触发 Agent 重新规划。6.2 常见验证策略验证策略原理适用场景成本工具校验真正运行代码/执行 SQL代码、数据库任务中反推验证把答案代回题目检查数学、逻辑题低自洽性验证多次采样结果一致性开放任务中LLM 验证器阅读并评分无规则可写的任务高工具校验永远是第一优先级。能跑测试就跑测试能查数据库就查数据库这些方式的可靠性远高于语言模型判卷。LLM 验证器是用来覆盖工具覆盖不到的部分。6.3 验证结果如何回环到 Agent 决策验证结果不能只是“打个分”就结束。在 Agent 里建议把验证结果结构化至少包含三个字段结论pass/fail/不确定、具体问题列表、修改建议。然后根据这些字段决定继续执行、重新生成、换一种工具路径还是直接终止并向用户解释。比如一个检索 Agent如果结果验证器发现答案里包含超出原始上下文的信息就可以判定为“幻觉风险”触发重新检索而不是直接返回。这种“验证结果驱动决策”的模式比单纯设置一个分数阈值更可靠。7. 常见问题与排查思路实际跑验证器流程时最容易遇到下面这些问题问题现象常见原因解决思路验证器分数普遍偏高提示词没要求逐步检查模型在敷衍强制按步骤输出并让它先找出潜在错误验证器分数普遍偏低条件过严把表达差异当成逻辑错误明确“只要逻辑正确即可不要求措辞一致”多个候选分数几乎一样生成侧 temperature 太低候选同质化提高温度或增加采样数量分数提取失败模型自由输出正则匹配不到要求模型最后输出 JSON再解析自验证循环不收敛验证意见太笼统答题者不知道改哪里把意见按“错误位置/原因/修改建议”结构化接口报错或超时密钥、base_url、限流配置问题检查 .env 配置确认模型名存在验证器把正确答案判错验证器本身能力不足或复述题目环节缺失换更强的验证模型或让验证器先解释题目如果只是跑最小流程最常出错的点是 prompt 格式化。建议先打印一次verifier_prompt肉眼确认问题、候选答案、输出格式三部分都正确再往下调试。8. 最佳实践与工程建议8.1 提示词设计验证器提示词要遵循“先检查、后打分”的原则。不要让模型直接给分而是强制它先复述题目、逐条核对、指出错误、最后给分。这个顺序能让模型的分数更有依据。如果想更稳定可以给验证器提供一两个 few-shot 示例。比如一个“错误解答被正确识别”的例子能显著降低验证器盲目给高分的概率。8.2 采样与成本控制验证器不是所有请求都要跑全流程。可以做一个分级策略简单问题生成 3 个候选、验证 1 次困难问题生成 8 个候选、验证 2~3 次。在进入完整验证之前还可以先用长度过滤、关键词过滤等廉价手段把明显离谱的候选排除掉。验证侧的 temperature 建议设置成 0.0 或 0.1。验证是判断任务不是创意任务低温能提升稳定性。8.3 数据、日志与评测上验证器之前先准备一小批带人工标注的测试集。统计验证器在这批数据上的“判对率”而不是只看它自己喜欢打高分还是低分。每次修改提示词后都要回归这一批数据避免“修好一个 case 带崩一片 case”。所有验证结果最好都落日志字段至少包含问题、候选答案、验证文本、分数、最终是否选中。这样后续做错误分析时可以直接定位是生成侧问题还是验证侧问题。8.4 安全与合规边界在大模型链路里嵌入验证器不是给它无限权限。验证器如果需要调用外部工具或数据库必须遵循最小权限原则只开放完成验证所必需的读权限。涉及生产环境的任何验证动作都应该在测试环境验证通过、有备份、可回滚的情况下进行。另外不要把密钥硬编码在代码里建议放到环境变量或配置中心。不要把用户隐私数据直接塞进验证器提示词必要时做脱敏处理。验证器输出只是参考信号不能作为唯一的事实依据尤其在高风险决策场景中要有人工兜底。9. 总结与下一步学习路线整套 LLM-as-a-Verifier 的实战路线可以拆成四步用提示词方案搭一个最小验证流程确认验证器能区分好答案和坏答案。在最小流程上加入“生成—验证—修正”循环观察能不能把最终答案拉高。在 Agent 链路里按节点插入验证器并把验证结果结构化驱动 Agent 决策。攒一批标注数据评估验证器效果再决定要不要微调一个专用验证模型。如果你最近也在做 Agent 验证建议先跑通第四节的最小流程把验证日志攒下来再考虑升级成微调方案。验证器这个方向刚火起来很多细节要靠自己的数据才能摸清楚。遇到有意思的 case欢迎在评论区一起讨论。