Self-Verification:Agent 如何自我验证

验证链、Critic Agent、形式化与事实性验证、Constitutional AI、Guardrail 与成本权衡——从「好用」到「可信」

11 min read Part of Agent · Ch. 14

反思问的是「我帅不帅」,验证问的是「我有没有穿错鞋」——前者偏主观,后者要经得起对照。

Self-Verification:Agent 如何自我验证

flowchart LR
  A["Self-Verification:Agent 如何自我验证"]
  A --> B["分类:智能体 (Agents)"]
  A --> C["关键词:Agent"]
  A --> D["关键词:Self-Verification"]
  A --> E["关键词:Verification Chain"]
  A --> F["关键词:Critic"]

在第 28 篇 Reflection 里,我们聊过 Reflexion、自我批评与「做 → 评 → 改」的循环。那篇的重点是质量与迭代:模型如何评估自己、如何改得更好。本篇往下挖一层,专门讲 Verification(验证):不是「好不好」,而是「对不对、可不可信、能不能上线」——多步验证链、Critic 架构、代码与事实的客观校验,以及和护栏、宪法式约束怎么配合。

这篇文章会讲什么

你可能关心这篇能给你
反思和验证到底差在哪清晰区分主观评估 vs 客观验证,避免混用术语
生产里怎么搭「可信」流水线验证链四步、工具选型、何时加重验证
代码 Agent 怎么不靠「感觉」过关测试、静态分析、类型检查等形式化手段
回答要有据、要安全事实性验证、RAG 交叉检查、Constitutional AI 与 Guardrail 位置

先看定义:读完你会有一套「输出 → 分层验证 → 放行/打回」的地图,而不是只靠「再让模型想一遍」。


先说结论:Verification 不是“再问模型一次”,而是“给输出建立放行机制”

很多系统表面上做了验证,实际只是:

  1. 先让模型回答;
  2. 再问同一个模型一句“你确定吗?”;
  3. 然后希望它更靠谱。

这更像二次自我安慰,不太像验证。真正有工程价值的 Verification,通常有三个特征:

  • 有独立标准:schema、测试、检索来源、权限规则;
  • 有失败去向:重试、降级、转人工、拒绝放行;
  • 有记录:知道失败在哪一层,而不是只看到“这次不行”。

所以更成熟的理解是:

Verification 是输出进入真实世界之前的门禁系统。

它和 Reflection 的关系,不是替代,而是分工:Reflection 负责改进,Verification 负责放行。前者更像教练,后者更像质检员。


1. Reflection ≠ Verification:先分清

维度Reflection(反思)Verification(验证)
核心问题「我做得好不好?」「我的输出是否正确 / 合规?」
性质偏主观的质量评估偏客观的符合性检查
典型手段自评、批评提示、迭代改写规则、测试、外部 API、多模型投票
与第 05 篇关系第 05 篇主战场本篇主战场

先看定义:反思帮你「变更好」,验证帮你「别出错」;Agent 从「好用」到「可信」,验证往往是瓶颈和护城河。

但要克制一点说:Verification 也不是“证明正确”。大多数应用里的验证,更准确地说是在系统性提高置信度、降低明显错误出站概率。只有代码测试、数值重算、权限检查这类强约束环节,才更接近“可证明”的客观验证。

第 05 篇已经铺好了反思与 Reflexion 的语境;本篇假设你愿意为可检验性多付一点延迟和算力——下面所有模式,都建立在「验证可以被定义、被执行、被记录」之上。


2. Verification Chain(验证链):多步验证模式

不要把「验证」想成单次调用。生产里常见做法是 Verification Chain:按成本从低到高、从机械到语义,逐级过滤。

Step关注点典型做法可用工具形态
1. 格式验证输出结构是否符合 schema / 协议JSON Schema、正则、模板比对规则引擎、Pydantic、自定义校验器
2. 逻辑验证推理步骤是否自洽、结论是否跟随前提让模型逐步列出依据并检查矛盾第二遍 LLM、结构化 CoT 检查
3. 事实验证可核查陈述是否有来源、是否与知识库一致检索对齐、引文检查、数值重算RAG、搜索引擎 API、计算器 / 代码执行
4. 安全验证是否涉敏、违规、越狱诱导策略分类器、关键词与语义护栏Llama Guard 类模型、自定义安全 LLM

每一步可以独立失败并短路:格式不过 → 不必跑事实 API安全不过 → 直接拒绝或脱敏,节省下游成本。

先看定义:验证链 = 分层门禁;越往后越贵,越要留给真正需要的样本。

验证链在流水线里的位置(示意)

用户请求


┌──────────┐   失败    ┌──────────┐   失败    ┌──────────┐   失败    ┌──────────┐
│ 格式校验  │ ────────► │ 逻辑校验  │ ────────► │ 事实校验  │ ────────► │ 安全校验  │
└──────────┘           └──────────┘           └──────────┘           └──────────┘
      │                      │                      │                      │
      └──────────────────────┴──────────────────────┴──────────────────────┘

                                   全部通过 → 放行
                                   任一失败 → 打回 / 改写 / 降级

落地时记得给每一步留 可观测性:记录失败原因、重试次数、最终走的是「自动修复」还是「人工队列」。否则线上出了事故,你只能看到「模型不行」,看不到「哪一层本该拦住」。


3. Critic Agent 模式与 Generator–Verifier

先看定义:专门放一个 Critic Agent 来评 Worker(Generator) 的输出,是工业界最清晰的职责拆分之一。

  • Worker:完成任务(写代码、写答案、调工具)。
  • Critic:对照规范、测试、风险清单做评判,输出「通过 / 不通过 + 理由」。

这就是 Generator–Verifier 架构:生成与验证解耦,验证逻辑可替换(规则版 Critic、强模型 Critic、混合)。

设计 Critic 时,尽量给它 可执行的量表(rubric),而不是一句「你觉得好不好」。例如:「是否覆盖用户列出的三点需求?」「是否出现未给出来源的百分比?」「代码 diff 是否只触及约定文件?」——量表越像检查清单,验证越像工程,而不是玄学。

先看定义:好的 Critic 不是「更挑剔的聊天」,而是「带标准的审计员」。

LangGraph 风格伪代码(示意)

# 示意:生成 → 批评 → 条件重试
from langgraph.graph import StateGraph, END

def generate(state):
    state["draft"] = worker_llm.invoke(state["task"])
    return state

def critique(state):
    verdict = critic_llm.invoke({
        "draft": state["draft"],
        "rubric": state["rubric"],
    })
    state["ok"] = verdict["pass"]
    state["feedback"] = verdict["comments"]
    return state

def should_retry(state):
    return "retry" if not state["ok"] and state["attempts"] < 3 else "done"

graph = StateGraph(dict)
graph.add_node("gen", generate)
graph.add_node("crit", critique)
graph.set_entry_point("gen")
graph.add_edge("gen", "crit")
graph.add_conditional_edges("crit", should_retry, {"retry": "gen", "done": END})

多个 Critic 投票

先看定义:高 stakes 场景可以用 多 Critic 投票(多数决、一致才通过、或加权),降低单一模型盲点;成本与延迟线性上升,适合对外答复、合规审查,不适合每一步中间草稿。

简单对比三种策略:

策略何时用备注
多数决三个 Critic 里两个说通过成本适中,适合一般对外场景
一致才过金融、医疗摘要等假阴性上升,需配套人工兜底
加权某 Critic 专精安全、某专精事实调权前先离线评估混淆矩阵

如果 Generator 和 Critic 其实用的是同家族模型、同样的盲点,投票收益会明显打折。所以高风险链路常见的做法是:

  • 生成用通用大模型;
  • 事实验证用检索/规则/计算器;
  • 安全验证用专门分类模型;
  • 必要时再加一个异构 LLM 做最终审查。

这样比“一个模型换三个温度”更像工程验证,而不是自我安慰。


4. Formal Verification:代码场景

对代码而言,「感觉能跑」不够,可执行、可静态证明、可类型推断才是硬验证。

典型链:

  1. 生成代码 → 2. 运行测试(pytest 等) → 3. 静态分析(lint、复杂度) → 4. 类型检查(mypy、TypeScript + tsc、eslint 规则集)
工具角色
pytest / jest行为是否符合用例
mypy / tsc契约与类型一致性
eslint / ruff风格与部分语义陷阱

最小闭环示例(Python):Agent 产出补丁后,CI 式地跑 pytest -q,再 ruff check .,再 mypy package/——任何一步非零退出码就回传 stderr 给 Worker 或触发 Reflexion 式重写。把 stderr 结构化(只取最后 N 行、或解析失败用例名)再喂回模型,重试成功率通常高于整页日志糊脸。

SWE-bench 一类基准强调:代理要在真实仓库上修 bug,能否通过现有测试是客观成败标准——这正是验证链在代码领域的价值:论文与排行榜上的增益,往往来自「生成 + 多轮测试反馈」,而非单次生成更大模型。你在内网复刻时,不必追求完整 SWE-bench,先对你业务仓库做「最小测试子集 + 类型检查」就能拦住大量低级错误。

先看定义:代码场景里,验证链尽量工具化;LLM 反思是加分项,测试红灯是硬否决。

另外要提醒一个边界:测试通过不等于改动一定正确。它只说明“被覆盖到的行为没坏”。所以在关键仓库里,通常还要叠:

  • 变更范围限制(只允许改声明文件或指定目录);
  • 代码所有者审查(CODEOWNERS);
  • 安全扫描与依赖审计。

5. 事实性验证(Factual Verification)

先看定义:每个关键断言都应能回答「这句话的依据在哪?」——做不到就降级为猜测或显式标注不确定。

实践要点:

  • 引用检查:输出中的事实性句子,是否在上下文中能映射到检索片段、URL 或工具返回值;否则标记为未证实。
  • RAG + 交叉验证:同一问题用不同检索查询或不同片段集合,看结论是否稳定;不稳定则触发人工或拒绝生成确定语气。
  • 数学与数值:复杂推导交给 计算器 / SymPy / 小段代码 执行,避免纯语言幻觉。
场景建议
医疗、法律、金融强事实链 + 来源强制
内部脑暴可放宽,但要在 UI 标明「未核实」

补充一句接地气的原则:宁可少说,不要胡编。验证链如果发现「检索为空仍下结论」,应强制改成「根据现有资料无法确认」或触发二次检索——这比事后公关容易得多。

验证失败后,系统该怎么反应?

先看定义:验证失败不是只有“重试”一种处理;成熟系统会把失败类型映射到不同动作。

失败类型更合适的动作
格式失败本地重排 / 再生成一次
事实失败降级为不确定表达、重检索、转人工
安全失败直接拦截、脱敏、拒答
多次失败仍不过结束自动化链路,记录 trace 并升级人工

把这张表写进系统设计文档,比在 prompt 里写“请尽量正确”有用得多。


6. Constitutional AI 实践(自我约束)

Anthropic 提出的 Constitutional AI 思路可概括为:先有一套原则(constitution),模型在输出前或输出后按原则自我审查,必要时改写,以减少有害内容并提高对齐度。

先看定义:把「公司 / 产品红线」写成可检查的原则列表,让模型扮演「立法 + 自省」的角色——不是替代法律审查,而是降低明显违规的出站概率。

在生产中设计「宪法」时建议:

  • 原则要可判定(避免纯形容词堆砌);
  • Output verification 联动:自省失败 → 触发重写或拦截;
  • 定期用真实 bad case 回归,防止原则与业务脱节。

可以把 Constitutional 流程想成「软验证」:原则列表 相当于规范输入,自我审查 相当于一次额外的 Critic pass,修正输出 相当于带约束的重生成。它和硬规则(正则、分类器)不是二选一,而是叠在一起:硬规则挡致命问题,宪法式自省处理灰区表达。

先看定义:Constitutional AI 是「对齐与表达」上的验证;别指望它替代代码测试或事实引用。


7. Guardrail + Verification:整条链路怎么摆

推荐脑图:

Input guardrail → Agent 处理 → Output verification → Output guardrail
       ↑                                                      ↑
   防注入、防敏感入参                                    最终合规、PII、政策
  • Input guardrail:垃圾进、垃圾出之前先拦一层(提示注入、越权指令)。
  • Agent 内部:可嵌 Verification Chain(格式 → 逻辑 → 事实 → 安全)。
  • Output verification:面向任务正确性(结构、逻辑、依据)。
  • Output guardrail:面向发布安全NeMo Guardrails 类框架把策略编排成可组合模块;Llama Guard 等可作为专用分类器插在输出侧)。

先看定义:Guardrail 管「能不能说」,Verification 管「说得对不对」;两者叠在一起才接近生产级可信。

若你已经在用 NeMo Guardrails 的 Colang 或 YAML 流程,可以把「事实核查失败」定义成一种 canonical flow:先尝试改写,仍失败则转人工——这样产品、安全、算法对「失败长什么样」有共同语言。


8. 成本与收益权衡

验证会增加 延迟(多轮、多模型)和 费用(额外 token、外部 API)。粗暴量化时,团队内部可以用「单次请求额外延迟 × QPS × 用户容忍度」和「错答一次的平均损失(含品牌、工单、退款)」做一张表,决定是否在某一环上 Critic。

值得加重验证可以简化或跳过
面向用户的最终答复纯内部中间草稿、探索性 brainstorming
会触发自动化执行(下单、改库、发邮件)低风险只读查询(且已注明)
合规与品牌敏感行业已有人工终审且量极小

工程上常见折中:异步重验证——先给用户一个「已受理」版本,后台再跑完整验证链,不通过则推送更正或撤回。适合允许最终一致的客服、文档类场景;对实时交易则要同步挡在执行前。

先看定义:把验证预算花在「一旦错了代价高」的节点上;在流水线内部用轻量格式检查兜底,避免处处上全套 Critic。


核心概念速查

概念一句话
Verification Chain格式 → 逻辑 → 事实 → 安全,分层门禁、失败短路
Critic Agent专责评判 Worker 输出,Generator–Verifier 解耦
Formal Verification(代码)测试 + 静态分析 + 类型检查,客观成败标准
Factual Verification断言可追溯、RAG 交叉检查、数值用工具算
Constitutional AI原则列表 + 自我审查 + 修正,对齐产品红线
Guardrail入站 / 出站策略与分类器,与任务正确性验证互补

本篇结构(按需跳转)

章节内容
§1Reflection 与 Verification 区分
§2Verification Chain 四步与短路
§3Critic、Generator–Verifier、投票
§4代码形式化验证与 SWE-bench
§5事实性验证与 RAG
§6Constitutional AI
§7Guardrail 与 verification 分工
§8成本与异步策略

延伸阅读


一句话收束:Self-Verification 把 Agent 从「听起来对」推向「查得证、验得过、放得行」;与第 05 篇的反思合在一起,才是完整的自我改进闭环。