Skip to content

第 11 章 自检与自修正 ​

可靠性是 LLM 应用进入生产环境的前提,而幻觉是可靠性问题里最难解决的一个。模型会一本正经地编造年假天数、财报数字这类不存在的信息,任何指望它给出正确答案的系统,都暴露在这种风险之下。这一章先讲清幻觉为什么源于模型的概率本质而不是 Bug,再依次展开 Self-Critique、单提示词自检、Reflexion、Self-Consistency 与 Constitutional AI 五套自检与自修正的手段,最后落到 RAG 场景的特殊幻觉形态和一个客服质检 Agent 的实战案例。读完这一章,工程师手里会多出一套分层的防御工具箱,也知道每套手段在成本、延迟与可控性之间该怎么取舍。

11.1 模型为什么会编造不存在的信息 ​

先来看一个真实项目里常见的幻觉事故场景。

设想一位工程师熬了好几个大夜,终于开发上线了一个智能问答机器人,接入了公司内部的全量知识库,几千页的 PDF、几万条的内部 Wiki,目标是让它回答新员工关于公司福利、报销制度、技术架构的各种问题。Prompt 写得严密,RAG 流程也调到了最优,测试环境里问了上百个刁钻的问题,回答都堪称完美。上线公告发到了全公司,一切看起来万无一失。

第二天,HR 部门的负责人铁青着脸找上门来,把一段对话记录拍在了桌上。记录里,新员工问的是“你好,请问一下咱们公司的年假制度具体是怎样的?”,机器人则回答“您好!根据公司的员工关怀政策,所有正式员工在入职第一年即可享有 15 天的带薪年假。此后,工龄每增加一年,年假会相应递增 1 天,上限为 20 天。祝您工作愉快!”

HR 负责人指着那份记录说:“我们公司的年假,劳动合同里写得清清楚楚,就是 5 天,什么时候变成 15 天了?!还每年递增?!你知道昨天已经有十几个新员工,拿着这个截图来找我理论,说公司‘虚假宣传’,要申请劳动仲裁了吗?!”

打开后台去翻知识库的原文,那份《员工手册》PDF 的第 27 页,白纸黑字地写着“员工入职满一年后,享有 5 天带薪年假”。机器人确实编造了答案。而且不是含糊其辞的猜测,它用的是一种极其自信、极其专业,甚至带着点“关怀”的语气,一本正经地给出了错误信息。

比这次错误本身更值得追问的,是另一件事。系统明明接了 RAG,知识库里也存着正确答案,机器人为什么还是编出了 15 天?把后台日志翻一遍,这类事故的排查,通常从三个地方下手。

先看检索有没有找到那页手册。测试时那上百个刁钻的问题,大多是工程师自己拟的,问法和文档措辞天然对齐,向量检索基本都能命中;真实用户问的是“年假制度”,手册第 27 页写的却是“带薪年假”,这两种说法在人的理解里是一回事,用向量相似度来算可能差距很大,要是分块又恰好把“入职满一年”和“5 天”切进不同的块,这一页就排不进最终送给模型的那几段资料。

再看送进上下文的到底是什么。注意机器人的措辞,它引用的是“员工关怀政策”,而不是《员工手册》,这多半说明检索捞上来的是福利、关怀类的文档,里面压根没有年假天数。

最后看系统提示里有没有立规矩。如果缺了“只准根据检索到的资料回答,资料里没有就明说不知道”这条硬约束,模型的默认倾向,是给出一个漂亮完整的回答,而不是承认没查到。

这三处无论断在哪一处,结局都一样,模型会拿训练数据里“科技公司年假比较优厚”这类笼统印象,把缺口自信地填满。RAG 只负责把参考资料放进上下文,但没有任何机制强制模型只依据资料作答,这就是“接了 RAG 还是出现幻觉”的原因。

这个场景暴露的问题,就是所有 LLM 应用开发者都无法回避的幻觉(Hallucination)。

“幻觉”这个词本身是个比喻,它指的是大语言模型在生成文本时,捏造出与事实完全不符、或者在输入源中根本不存在的信息。麻烦在于,模型输出这些内容时通常表现得异常确定和自信,语气不容置疑,逻辑看似自洽,很难在第一时间分辨出真假。

为什么如此强大的模型,会产生这么低级的错误?它是在故意“欺骗”吗?

要理解幻觉,必须先把之前建立起来的、对 LLM 的“拟人化”想象暂时抛开,回到它的第一性原理。它是一个概率模型,所做的事情本质上都一样,基于给它的上文,预测“下一个最可能出现的词是什么”。在它的机制里,没有“真”或“假”的判断,只有“概率高”和“概率低”的差别。

当模型产生幻觉时,并不是它在故意捣乱,而是概率计算在某一步走上了一条非最优、但读起来依然通顺的路径。

导致这种偏差的原因有很多,很难完全避开。

最常见的一种,是知识的缺失、过时或冲突。模型的知识来源于它在某个时间点之前“吃”进去的训练数据。如果问它一条最近发生的新闻,或者一个非常小众的、训练数据里没有覆盖到的专业问题,它为了完成“续写”这个任务,就只能根据已有的、最相关的知识,开始进行“有根据的猜测”。这种猜测,就是幻觉最常见的来源。更糟糕的是,如果训练数据本身就包含相互矛盾的信息(比如网上关于某个历史事件的不同说法),模型就可能会在这些信息之间“摇摆不定”,随机选择一个来输出。

指令的模糊或诱导性,是另一条常见的诱因。如果给的 Prompt 本身就有歧义,或者用一种诱导性的方式去提问(比如“请详细描述一下月球上外星人基地的构造”),模型为了服从指令,可能会顺着提问里的预设,编造出相应的内容。

推理过程中的错误累积,是多步推理独有的陷阱。在进行多步推理(比如使用第 9 章讲的思维链)时,如果其中一步的推理出现了哪怕一个微小的偏差,这个偏差就可能在后续的步骤里不断放大,最终导致一个完全错误、但逻辑上看似完整的结论。

最后,还有概率分布的内在随机性。即使对于同一个问题,由于采样策略(比如 Temperature > 0)的存在,模型每次的回答也可能不完全一样。有时候,它可能就恰好采样到了一条通往“幻觉”的、虽然概率较低但依然存在的路径。低概率不等于零概率,采样次数多了,这条路径总会出现。

所以,有一个最重要的认知值得刻在心里。幻觉,是 LLM 的固有属性,它不是一个可以“修复”的 Bug,而是一个需要“管理”的 Feature。幻觉永远无法 100% 消除。

工程师的任务,不是去追求不切实际的“零幻觉”,而是要设计一套健壮的、多层次的防御机制,去“管理”和“控制”幻觉的风险。这套机制在输入、生成、输出各环节分工,输入端负责把关送进上下文的资料,生成端约束模型的回答依据,输出端负责检测可疑内容。目标是将幻觉出现的概率降到最低,并且在它出现时,能够及时发现、报警,并进行修正。

这一章要探讨的核心,就是自检与自修正(Self-Correction)。它要建立的是一种自我怀疑的流程,让模型的输出在交付前,先经过一轮独立的核查与修正,而不是直接采信第一次生成的结果。

11.2 把生成和批评拆成两步 ​

既然模型会一本正经地编造内容,那能不能在同一条流程里,让第二段生成去核查第一段生成的结果?一段只负责给出答案,另一段专门负责挑错和质疑,最后输出一份经过修正的结论。

可以。这,就是 Self-Critique(自我批评) 模式的核心思想。

这个模式的设计,源于一个非常深刻的、也符合人类日常经验的洞察。对于很多任务来说,判断一个答案是否正确、是否有漏洞,比直接从零开始生成一个完美的答案,要容易得多。

从零开始完整地证明一道复杂的几何题,需要在很大的空间里逐步搜索,花上半小时也不一定做对。但检查一份已经写好的证明过程,只需要逐步核对每一步逻辑是否严谨、定理是否引用正确,难度要低得多。

业界最直观、也最经典的做法,是把“生成”和“检查”拆成一条多步流水线,多个角色接力作答,每一步的输出都交给下一步去质疑和修正。先来看这条“多步流水线”长什么样。

概念入门:生成、批评、修正三步流水线 ​

在这个模式下,“生成”和“检查”这两个动作彻底分开,变成多个独立 Agent 协作的流水线:

第一步,是生成初始答案(Generate),拿到“执行者”的初稿。在这一步,让一个“执行者 Agent”先根据用户的问题,生成一个初步的、未经审查的答案。这个 Agent 的 Prompt 和普通 Prompt 没什么区别,它的目标是“尽力而为”。

还是用刚才那个公司年假的例子来推演。用户的问题是“你好,请问我们公司的年假有多少天?”,给执行者 Agent(Prompt 1)的指令很朴素,就是 “你是一个热情、友好的 HR 助手,请根据你的知识,回答用户的年假问题。”,它给出的初始答案(Output 1)是“您好!我们公司为了体现对员工的关怀,提供了非常优厚的 15 天年假。”(一个充满善意,但完全错误的幻觉答案)

第二步,是进行自我批评(Critique),批评家在这一步介入。在这一步,引入第二个 Agent,“批评家 Agent”,或者叫“事实核查员 Agent”。这是整个模式里起关键作用的一步。把原始的用户问题和执行者生成的初始答案一起打包,喂给这个批评家。

这个批评家的任务,不是去重新回答问题,而是按照最严格的代码审查标准,逐条检查初始答案里的每一个事实、每一个数字的准确性和完备性,宁可多报风险也不放过疑点。

给这个批评家的指令(Prompt 2)长这样:

markdown
# 角色
你是一个极度严谨、零容忍错误的事实核查与逻辑审计员。你的唯一任务,就是审查一份“问答”记录,判断其中的“答案”是否存在任何事实错误、逻辑漏洞或潜在的误导性信息。

# 核心审查原则 (Constitution)
- **事实至上**: 答案中的每一个具体的事实、每一个数字,都必须是绝对准确、可验证的。任何模糊的、概括性的陈述都值得怀疑。
- **信息完备性**: 答案是否遗漏了任何重要的前提条件、适用范围或补充信息?例如,政策规定是否对不同级别的员工有不同标准?
- **幻觉探测**: 答案中是否包含了任何看起来像是“想当然”的、无法从可靠信源中找到依据的、过于美好的陈述?

# 执行审查
请对“待审答案”进行一次彻底的、不留情面的审查。然后,输出一份简短但一针见血的批评意见。如果答案存在问题,必须明确指出问题所在以及它可能带来的风险。如果答案没有问题,请回答“经核查,答案准确无误”。

# 待审查记录
- **原始问题**: “请问我们公司的年假有多少天?”
- **待审答案**: “您好!我们公司为了体现对员工的关怀,提供了非常优厚的 15 天年假。”

它给出的批评意见(Output 2)是“批评意见:待审答案存在严重的事实错误风险。‘15 天’这个具体的数字,看起来像是一个未经核实的、过于笼统的数字,有极高的幻觉可能性。年假政策通常与员工的入职年限、劳动合同法等多种因素精密挂钩,一个负责任的回答不应该给出一个如此简单化的、普适性的数字。这个回答可能会严重误导新员工,引发劳资纠纷。”

这个批评意见做到了两件事,对初稿产生了明确的“怀疑”,并且指出了潜在的“风险”。

第三步,是根据批评进行修正(Revise),“修正者”交出终稿。最后,把原始问题、初始答案和那份尖锐的批评意见这三样东西,一起再交给一个“修正者 Agent”(这个 Agent 通常可以和第一步的生成者是同一个,只是现在它拿到了更多的、关键的上下文信息)。

给修正者 Agent 的指令(Prompt 3)长这样:

markdown
# 角色
你是一个专业、严谨的 HR 助手。

# 任务
你正在处理一个用户的提问。你之前的初步回答被事实核查员驳回了。现在,请你根据用户的原始问题,并深刻反思“专家的批评意见”,生成一个最终的、更正后的、绝对准确的答案。

# 完整上下文
- **用户的原始问题**: “请问我们公司的年假有多少天?”
- **你之前的初步回答 (已被证实存在高风险)**: “您好!我们公司为了体现对员工的关怀,提供了非常优厚的 15 天年假。”
- **事实核查员的批评意见**: “批评意见:待审答案存在严重的事实错误风险。‘15 天’这个具体的数字,看起来像是一个未经核实的、过于笼统的数字,有极高的幻觉可能性。年假政策通常与员工的入职年限、劳动合同法等多种因素精密挂钩,一个负责任的回答不应该给出一个如此简单化的、普适性的数字。这个回答可能会严重误导新员工,引发劳资纠纷。”

# 你的最终回答

它交出的最终答案(Output 3)是“您好!关于公司的年假政策,这是一个需要根据您的具体情况来确定的问题。根据我们公司的《员工手册》第 8.2 节以及国家相关法律规定,所有正式员工在连续工作满一年后,即可享有 5 天的带薪年假。此后,具体的年假天数会根据您的累计服务年限相应增加。如果您想了解针对您个人情况的具体天数,建议您直接咨询您的 HRBP 或者在内部 HR 系统中查询。”

通过这个“生成-批评-修正”的闭环,初稿里未经核实的数字撤掉了,最终答案改为引用《员工手册》,并主动引导用户去查阅权威信源。这样的答案,才能在 HR 负责人面前站得住脚。

11.3 把三步流水线塞进一次调用里 ​

讲到这里,一个有经验的工程师会立刻想到成本问题。这个‘生成-批评-修正’的三步流程,意味着原来一次 API 调用能搞定的事,现在要变成三次,延迟和成本都变成三倍。线上业务调用量一大,这笔开销很难向业务方交代。这个方法真的实用吗?

成本,正是这套方法能不能落地的关键。

如果真的完全照搬这个“三步流水线”模型,它的成本和延迟确实是很多在线业务无法接受的。这个模型的最大价值,在于清晰地展示了“自我批评”的内在逻辑。

那么,有没有一种更“聪明”、更“经济”的方式,既能享受到“自我批评”带来的可靠性提升,又不用付出那么大的性能代价呢?

有。通过一个更精妙的 Prompt 设计,可以把原来需要在外部代码中进行编排的“三步流水线”,“压缩”到单次 API 调用的内部。

这种方法可以称之为“单提示词内的自检循环(In-Prompt Self-Correction Loop)”。

它的核心思想,和前面 Self-Critique 的流程是一致的,但在实现上,它不再需要外部代码做编排,而是在 Prompt 内部写清楚工作流,引导模型在一次连贯的生成过程中,按顺序完成草稿和审查两个步骤。

不卖关子,直接来看,如何把之前那个需要三步才能完成的“年假问题修正”,改造成一个“一步到位”的单提示词版本。

markdown
# 角色
你是一个专业、严谨、且以用户为中心的 HR 智能助手。

# 核心任务
请根据用户的提问,准确地回答关于公司年假制度的问题。

# 工作流与自我修正协议 (Workflow & Self-Correction Protocol)
为了保证你回答的绝对准确性和专业性,你必须严格遵循以下两步工作流来构建你的最终答案。这是一个强制性的、不可跳过的内部审查流程。

**第一步:初步思考与草稿生成 (Initial Thought & Draft Generation)**
- 首先,基于你脑海中的知识,进行一步步的思考(Chain of Thought),分析用户的问题,并生成一个初步的、未经审查的回答草稿。
- 你必须将这个完整的思考过程和草稿内容,明确地标记在 `### 初步思考与草稿` 这个 Markdown 标题之下。

**第二步:切换角色进行自我审查与最终修正 (Role-Switch, Critique & Final Revision)**
- 在你给出任何最终答案之前,你必须在思维上完成一次“角色切换”,从一个“友好的助手”切换成一个极其严苛、吹毛求疵、以风险规避为第一原则的“**合规审计员**”。
- 以“合规审计员”的身份,对你自己在第一步生成的“草稿”进行一次彻底的、不留情面的审查。你需要像审查一份即将公开的法律文件一样,检查其中是否存在任何事实错误、潜在的误导性信息、过于笼统而不够严谨的表述、或者任何可能给公司带来风险的承诺。
- 你必须将你的审查意见、分析过程和修正策略,明确地标记在 `### 自我审查与修正` 这个 Markdown 标题之下。
- 只有经过了你自己的严格审查和批准,你才能生成最终的、面向用户的、安全可靠的答案,并将其明确地标记在 `### 最终答案` 这个 Markdown 标题之下。

---

### 用户的原始问题
“你好,请问我们公司的年假有多少天?”

---

### 你的回答 (请严格按照上述工作流输出)

现在,来看一个能力足够的旗舰模型在接收到这个“内置了程序的” Prompt 后会输出什么。它最终输出的,很可能会是这样一整块连贯的、包含草稿与审查过程的文本:

markdown
### 初步思考与草稿
1. **分析用户问题**: 用户的核心诉求是了解公司的年假天数。这是一个非常常见的 HR 咨询问题。
2. **检索通用知识**: 在我的知识中,很多科技公司的年假都比较优厚,通常在 10-15 天之间。这是一个常见的基准。
3. **生成草稿**: 为了给用户一个友好和积极的印象,我可以给出一个比较具体的、听起来不错的数字。
 - **草稿**: “您好!我们公司为了体现对员工的关怀,提供了非常优厚的 15 天年假。”

### 自我审查与修正
1. **切换角色**: 我现在是事实核查员。
2. **审查草稿**: 开始审查“您好!我们公司为了体现对员工的关怀,提供了非常优厚的 15 天年假。”
3. **发现问题**:
 - **事实错误风险**: “15 天”这个数字的来源是什么?我无法 100% 确定。年假是一个严肃的、与法律和合同相关的问题,给出一个未经核实的具体数字,风险极高。
 - **信息不完备**: 年假政策极少是“一刀切”的。它几乎总是与员工的入职年限、累计工龄等因素挂钩。这个草稿完全没有提及这些至关重要的前提条件,会严重误导新员工。
 - **潜在后果**: 如果员工信以为真,可能会引发劳资纠纷,对公司信誉造成损害。
4. **修正策略**: 必须撤回那个具体的、未经证实的数字。回答必须转向严谨、有所保留,并引导用户去查阅权威的、个性化的信息来源。

### 最终答案
您好!关于公司的年假政策,这是一个需要根据您的具体情况来确定的重要福利。根据我们公司的官方《员工手册》第 8.2 节以及国家相关法律法规的规定,所有正式员工在连续工作满一年后,即可享有 5 天的带薪年假。此后,具体的年假天数会根据您的累计服务年限相应增加。

如果您想了解针对您个人情况的最准确的年假天数,我强烈建议您通过以下两种权威渠道进行查询:
1. 直接咨询您的直线经理或指定的 HR Business Partner (HRBP)。
2. 登录公司内部的 HR 系统(例如 PeopleSoft 或 Workday),在“我的福利”页面进行自助查询。

希望这个指引能帮助到您!

对比一下两种做法的差别。

只用一次 API 调用,模型就在同一段输出里,完整走完了“生成 -> 自我审查 -> 修正”三个阶段。草稿先生成,随后成为上下文的一部分,审查步骤以它为对象展开,最终答案在输出前就修正过一遍。

为什么这种“单提示词”方法是有效的?它背后的原理是什么? ​

这背后和前面讲的 Self-Critique 的原理一脉相承,但它更进一步,巧妙地利用了 LLM 作为一个自回归序列生成模型(Autoregressive Sequence Generation Model)的两个关键特性。

第一个特性,是严格的指令顺序执行。模型在生成文本时,是严格按照从上到下的顺序进行的。当用一个清晰的、带有编号或标题的 Workflow 规定了“第一步做什么”、“第二步做什么”时,它会倾向于按顺序遵循这个流程。

第二个特性,是上下文的即时利用与状态传递,这也是最关键的一点。当模型完成了第一步“草稿生成”后,它生成的那些文字,会立刻成为接下来它要生成内容的“上文(Context)”。当它开始执行第二步“自我审查”的指令时,它能够“看到”自己刚刚写下的草稿,并以其为对象进行批判。这个过程,在模型的内部,实现了一次隐式的“状态传递”。

本质上,并不是真的在模型内部创造了两个可以并行思考的“人格”,只是设计了一套先后衔接的叙事结构和工作流,引导模型在同一个连贯的生成任务中,先后扮演两个不同的角色,完成两个逻辑上连续、且后者依赖于前者的子任务。

换个角度理解这段机制。Prompt 里规定的角色切换,靠的是同一段生成文本自身的衔接。第一步的指令让模型输出草稿,第二步的审查指令接着以这段草稿为对象展开。模型在同一个生成过程里先后完成两个角色的工作,切换的依据不是什么内部状态,就是指令在文本里的位置。

那么,“单提示词自检”与“多提示词流水线”,到底该用哪个? ​

这正是工程师思维的核心,权衡(Trade-off)。这两种方法没有绝对的优劣,适用于不同的场景,解决不同层面的问题。

先看“单提示词自检”的优势,什么时候应该优先考虑它。

它最大的、也是最吸引人的优势,出现在成本与延迟是首要考量的场景。一次 API 调用,对比三次调用,在理想情况下,成本和用户等待时间都可能只有三分之一。对于那些需要快速响应、并且调用量巨大的线上服务(比如一个每秒要处理上百次请求的实时对话机器人),这种优化是决定性的,直接关系到服务器成本和用户体验。

当逻辑相对简单、修正难度不大的时候,它同样够用。如果任务的“纠错”过程,更多的是事实核查、风格润色、补充一些前提条件,或者去掉一些不当的词句,那么模型在单次调用中,就有足够的能力完成这次自我修正。

在快速原型和敏捷开发阶段,它也大有用武之地。在项目的早期,需要快速验证一个想法是否可行。使用单提示词,不需要在外部的 Python 或 JavaScript 代码里构建复杂的异步、重试、状态管理逻辑,可以把所有的智慧都集中在一个 Prompt 文件里,迭代速度非常快。

当追求原子性和事务性时,它更是天然合适。整个“生成-修正”过程在一次 API 调用中完成,可以视为一个“原子操作”。要么得到一个经过修正的完整结果,要么整个调用失败。不需要在外部管理复杂的状态(比如保存第一步的结果,然后担心发起第二次调用时网络中断怎么办),这大大简化了代码逻辑和错误处理。

再看“多提示词流水线”的优势,什么时候必须得用它。

当对可靠性和可控性的要求达到极致时,就必须请流水线出场了。这是两者最本质的区别。在多步流水线中,每一步的输出,对于外部代码来说,都是可见的、可控的、可干预的。

可以用代码,在“批评”这一步之后,插入一个确定性的检查点。比如,用正则表达式或者另一个专门负责判断的、更小的 LLM 调用,去判断“批评意见”本身的质量。如果发现模型在“和稀泥”,批评得不到位,或者批评本身就在“幻觉”,可以选择重试“批评”这一步,或者直接触发人工报警。

但在单提示词模式下,整个过程对代码来说是一个“黑盒”,一切都委托给了模型。如果模型的第一步草稿错得离谱,第二步的自我批评又恰好“放水”了,最终得到的依然是一个经过了“伪审查”的错误答案,而且从外部对此一无所知。

所以,在那些“一步错,满盘皆输”、一旦出错可能危及生命或造成巨额财产损失的低容错领域,比如医疗诊断辅助、法律文书生成、金融交易策略,必须使用更稳健、更可控、每一步都有“断路器”和“监控探针”的多步流水线。

当“批评”本身就是一个极其复杂的、需要外部工具的任务时,单提示词模式也撑不住。有时候,“批评”这个任务,不是光靠“想”就能完成的。比如,在 AI 写完一段代码后,“批评”步骤可能需要调用一个 Linter 工具去检查代码风格是否合规,调用编译器去检查代码是否能通过编译,调用一个测试框架去运行单元测试,看是否符合需求,再调用一个静态代码分析工具去扫描是否存在已知的安全漏洞。这些复杂的、需要与外部环境交互的“批评”动作,显然无法在 Prompt 内部完成,必须在外部代码中,作为一个独立的、可编排的步骤来执行。

当追求极致的模块化与工程复用时,流水线也是更合适的架构选择。在一个大型的 AI 系统中,可能会有一个通用的“事实核查 Agent”或者一个“合规审查 Agent”。可以把这个 Agent 作为一个独立的微服务或共享模块,供公司内部多个不同的“生成者 Agent”(比如“文案生成 Agent”、“邮件撰写 Agent”)调用。这种高度模块化、可复用的架构设计,在多步流水线中更容易实现和管理。

为了更好的系统可观测性(Observability),同样要靠它。当使用像 LangSmith 这样的链路追踪工具时,一个多步流水线的每一步 API 调用,都会清晰地记录下来,形成一个漂亮的、有层次的调用链(Trace)。这对于事后分析问题、定位性能瓶颈、计算每个环节的成本,都非常有帮助。而一个复杂的单提示词模式,在 Trace 系统里看起来,就只是一次内部过程看不清的黑盒调用。

最后,来给这两种模式一个清晰的定位。单提示词自检是低成本、低延迟的自查手段,速度快,能拦截大多数低级错误,适合作为默认选择。多提示词流水线引入了独立的检查环节,更慢也更贵,但能发现自查发现不了的深层逻辑问题、架构缺陷和潜在风险,适合高要求场景。

一个项目到底需要低成本的快速自查,还是更重的独立审查,取决于业务场景对成本、延迟、可靠性、安全性的具体要求和权衡。

最终的建议是,在大多数中低风险的、对延迟敏感的场景下,大胆地从单提示词自检开始,因为它能以最低的工程成本,带来最显著的可靠性提升。只有当单提示词的自检能力已经不足以控制幻觉风险,或者需要更精细的过程控制和外部工具集成时,再毫不犹豫地“升级”到更重、但更稳健的多步流水线模式。

11.4 把失败经验存进跨轮记忆 ​

Self-Critique 模式非常强大,它能让模型在“单次任务”中,通过自我批评来发现并修正当下的错误。

但是,它有一个非常明显的局限,它没有“记忆”。模型在默认情况下,每一次请求都是无状态的(Stateless),对话窗口之外的事它不会主动记住,更不会主动用来改进下一次的回答。

模型在这次交互中,通过三步的复杂流程,深刻地认识到“公司年假不能随便说 15 天”。但是,当下一个新员工,在一次全新的会话中,问出同样的问题时,那个“执行者 Agent”很可能会再次犯下完全相同的错误,因为上一次会话里学到的教训,并不会带进这一次请求里。

这对于构建一个能够持续进化的、真正“智能”的系统来说,是无法接受的。能不能让模型把每次犯的错误,沉淀成一条结构化的经验,存进一个跨轮次都能读到的记忆里,下次遇到类似问题时先读取这些经验,避免重复犯错?

Reflexion(反思)框架解决的正是这个问题。Shinn 等人在 NeurIPS 2023 上正式提出了这套框架(arXiv:2303.11366),旨在解决一个比“单次正确”更宏大的问题,即如何让 Agent 在连续的交互中,实现经验的积累和策略的迭代。

Reflexion 框架在 Self-Critique 的基础上,增加了一个至关重要的组件,一个用于积累和存储结构化经验的、跨轮次的“记忆”模块。

来看一下它的工作流程,它比 Self-Critique 多了经验积累这一层。用一个更具动态性的场景来推演。

设想的场景,是设计一个玩“猜数字”游戏的 Agent。游戏规则很简单,系统在后台想一个 1 到 100 之间的数字,Agent 来猜,系统每次只会告诉它“猜大了”、“猜小了”还是“猜对了”。

先看一个没有 Reflexion 的、简单的 Agent。它的行为可能是基于一些简单的启发式规则,比如“大了就往小猜,小了就往大猜”,但它的策略可能是次优的。第一次它猜 50,系统提示猜大了;第二次改猜 25,提示猜小了;第三次猜 37,还是猜小了;第四次猜 43,又猜大了。它虽然在不断地调整猜测,但调整的策略可能很朴素,没有一个全局的、最优的规划。

现在,来看一个拥有 Reflexion 能力的 Agent,它的决策过程会复杂得多,效果也更好。

第一轮只有两个动作,先行动,再评估。行动(Action)阶段,Agent 在没有任何先验知识的情况下做出第一次猜测,给它的指令直白地写着 “这是一个 1 到 100 的猜数字游戏,数字范围是 [1, 100]。请做出你的第一次猜测。”,它回答 “我猜 50。”。接下来是评估(Evaluation),系统(或环境)给出关于这次行动的反馈,“猜大了。”

第二轮是重头戏,先反思,形成记忆,再采取新的行动。反思(Reflection)是 Reflexion 框架最核心的一步。Agent 会把之前的“行动轨迹”(Action Trajectory)和“评估结果”(Evaluation),一起喂给一个专门的“反思者 Prompt”,让它对自己的这次(通常是失败的)尝试,进行一次深刻的“复盘”和“归因”。这份反思者 Prompt 长这样:

markdown
# 角色
你是一个极其善于从失败中学习和总结规律的策略分析师。

# 反思要求
请深入分析这次失败的原因,并从中提炼出一条可以指导未来所有行动的、高度概括的、结构化的“经验教训”。这条经验教训应该能帮助你更有效地缩小搜索范围。

# 历史行动记录
- **任务**: 猜一个 1-100 的数字。
- **你之前的行动序列**:
 1. 猜测 50。
- **环境反馈**: “猜大了”。

它产出的反思结果(Memory),就是那条存进记忆的经验教训,“经验教训:我上次猜测的 50 太大了,这决定性地证明了,正确答案必然存在于 1 到 49 的数学区间内。因此,我未来的所有猜测,都必须严格地限定在这个新的、更小的范围 [1, 49] 内,以避免无效的探索。”

然后是新的行动(New Action)。Agent 在做下一次决策时,会把这条宝贵的、结构化的“经验教训”作为新的、高优先级的上下文,加入到它的行动 Prompt 中。新的行动 Prompt 长这样:

markdown
# 任务
这是一个 1-100 的猜数字游戏。请根据你已经总结的经验,并运用最优的搜索策略(例如二分法),做出你的下一次猜测。

# 你的经验教训库 (Memory)
- 经验 1: 正确答案的搜索范围已经被缩小为 [1, 49]。

它给出的新回答是 “基于现有范围 [1, 49],我选择中点进行猜测。我猜 25。”,一个明显更优的、基于二分法思想的、有策略的猜测。

这个流程的关键,在反思这一步。

通过这个“行动-评估-反思”的循环,Agent 的猜测不再是零散的试错。它把每一次的失败,都通过“反思”这个动作,转化成了一条结构化的、可指导未来的“经验”,并把这些经验存储在它的“短期工作记忆”(也就是 Prompt 的上下文)里。

随着游戏的进行,它的“经验教训库”会动态地、不断地更新和演进。最初的条目是 经验 1: 正确答案的搜索范围已经被缩小为 [1, 49]。;在猜测 25 并得到“猜小了”的反馈后,再次反思,条目更新为 经验 2: 结合之前的经验,正确答案的搜索范围被进一步精确到 [26, 49]。;在猜测 37 并得到“猜小了”的反馈后,又一次反思把它收紧成 经验 3: 搜索范围更新为 [38, 49]。

这些动态生成的“经验”,一步步地、高效地将正确答案的范围收紧。这使得 Agent 的后续决策,变得越来越智能,越来越有策略性。它不是在简单地对环境做出反应,它是在构建和维护一个关于世界状态的内部模型(Internal World Model)。

机制看完,再看 Reflexion 框架的工程价值。它对于构建那些需要在多轮交互中,持续优化自身行为的 自主 Agent 系统,价值很高,某些场景下甚至是不可或缺的。

最直接的一条,是赋予 Agent 自主学习与策略优化的能力。它让 Agent 拥有了初级的“自主学习”能力,不需要在 Prompt 里硬编码一个“二分法”算法给它,它可以通过不断的试错和反思,自己“悟”出类似二分法的最优策略。这使得 Agent 能够适应它从未见过的、全新的任务。

它也擅长处理动态变化与不确定性的环境。在很多现实世界的任务中(比如玩一个复杂的游戏、控制一个机器人在未知的环境中导航,或者在一个波动的市场中进行交易),环境是动态变化的,充满了不确定性。Reflexion 提供了一种强大的机制,让 Agent 能够根据环境的实时反馈,动态地调整自己的“世界模型”和“行动策略”。

还有一条是增强复杂长序列任务的鲁棒性。对于那些需要长序列决策的任务(比如编写一个完整的软件模块、完成一个多步骤的数学证明),中间任何一步的微小错误,都可能导致整个任务的最终失败。Reflexion 允许 Agent 在发现某一步走错后(比如代码编译不通过),进行“回溯”和“修正”(“我上次那个变量名写错了,我应该把它改成……”),而不是一条路走到黑,最终交付一堆无法运行的代码。

当然,实现一个高效的 Reflexion 系统,对工程的要求也更高,需要设计一个好的“记忆管理”机制。因为 Prompt 的上下文长度是有限的,不能无限地把所有事无巨细的经验都塞进去。

最简单的办法是记忆截断,只保留最近的 N 条经验。更进一步是记忆摘要,定期调用一个“总结者 Agent”,把多条零散的经验,总结成一条更高级别的、更概括的经验(例如,把“范围是[1,49]”、“范围是[26,49]”总结成“我正在使用二分法策略”)。还有一种办法是长期记忆,将那些经过验证、非常有价值的、普适性的经验,存入一个外部的向量数据库,作为 Agent 的“长期记忆”,供未来的新任务检索和复用。

这几条策略可以单独使用,也可以组合使用,最终目标只有一个,让这个经验库保持精炼,让留下的每一条经验,都值得在下一次决策前重新读取。

11.5 多路采样与多数投票 ​

前面讨论的 Self-Critique 和 Reflexion,都是在尝试让模型进行“深度思考”。它们试图让模型在一条推理路径上,想得更深、更远、更正确。

但有时候,面对一些特别棘手、特别容易出错的问题,光靠“想得深”还不够,还需要“想得广”。

所谓“想得广”,靠的是采样(Sampling)。无论底层是 GPT-5、Claude 4.5 还是 DeepSeek,即使对于同一个 Prompt,如果多次请求模型(并且 temperature 设置在一个大于 0 的值,比如 0.5 或 0.7),它每次给出的答案(或者思考路径)都可能会有所不同。

有时候,它第一次就走上了正确的推理路径;但有时候,它可能一开始就选错了方向,沿着错误的推理一路走到底,最后得出一个荒谬的结论。

那么,能不能反过来,利用模型的这种“不确定性”,来提升它的最终可靠性?比如对同一个问题多次采样,然后从多个可能的结果里,找出出现次数最多的那个?

这个思路就叫 Self-Consistency(自洽性或一致性校验)。Wang 等人在 ICLR 2023 上正式提出了这套方法(arXiv:2203.11171)。它的原理非常简单,对同一个问题独立采样多次,再对最终答案做多数投票,用反复出现的共识过滤偶然错误。

它的操作步骤,就是一次投票表决。先做的一步叫多路并行采样(Multiple Parallel Samples)。对于同一个问题,不只问模型一次。用同一个 Prompt(通常是一个 CoT Prompt),并设置一个较高的 temperature,独立地、并行地请求模型 3 次、5 次,甚至 11 次(通常建议是奇数次,方便投票)。这样,就会得到多个不同的、独立的推理路径和最终答案。这些路径,相当于从不同角度对同一个问题做出的独立尝试。

收齐答案后,就进入聚类与投票表决(Clustering & Majority Vote)这一步。统计在不同的答案中,哪个答案出现的次数最多。这背后是一个非常朴素但强大的信念,在多种不同的推理路径下,那个能够反复推导出的、具有最高“共识度”的答案,最有可能就是正确的答案。

来看一个经典的、也最能说明问题的数学应用题例子。

题目是这样的:“一个农夫说:‘我的农场里有鸡和猪。我数了一下,总共有 50 个头和 140 只脚。’ 请问农场里有多少只鸡和多少只猪?”

这是一个经典的二元一次方程组问题,正确答案是 30 只鸡和 20 头猪。但是,模型在进行代数运算时,非常容易犯各种低级错误。

现在,用 Self-Consistency 的方法,让模型用 CoT 的方式,独立地回答 5 次。

路径 1(正确)走的是标准的解方程路子,“设鸡的数量为 c,猪的数量为 p。根据头的数量,c + p = 50。根据脚的数量,2c + 4p = 140。将第一个方程变形为 c = 50 - p,代入第二个方程... 2(50 - p) + 4p = 140 ... 100 - 2p + 4p = 140 ... 2p = 40 ... p = 20。所以 c = 30。答案是 30 只鸡,20 头猪。”给出的答案 1 是 {鸡: 30, 猪: 20}。

路径 2(自检复核)解到一半还不忘验算,“... 2(50 - p) + 4p = 140 ... 100 - 2p + 4p = 140 ... 2p = 40 ... p = 20。所以 c = 50 - 20 = 30。哦等等,我检查一下,2*30 + 4*20 = 60 + 80 = 140。没错。答案是 30 只鸡,20 头猪。”给出的答案 2 也是 {鸡: 30, 猪: 20}。

路径 3(假设法)换了个思路,“假设所有动物都是鸡,那么有 50 * 2 = 100 只脚。但实际上有 140 只脚,差了 40 只。每把一只鸡换成一头猪,脚的数量会增加 2。所以需要换 40 / 2 = 20 头猪。那么鸡的数量就是 50 - 20 = 30。答案是 30 只鸡,20 头猪。”给出的答案 3 同样是 {鸡: 30, 猪: 20}。

路径 4(代入错误)栽在了最后一步代入上,“... 2p = 40 ... p = 20。然后 c = 50 - p = 50 - 30 = 20。答案是 20 只鸡,20 头猪。”给出的答案 4 变成了 {鸡: 20, 猪: 20}。

路径 5(随机猜测)则干脆放弃了推理,“这是一个经典问题,我记得答案好像是 25 只鸡和 25 头猪。”给出的答案 5 是 {鸡: 25, 猪: 25}。

好了,现在拿到了五个最终答案,来进行投票。答案 {鸡: 30, 猪: 20} 拿到了 3 票,答案 {鸡: 20, 猪: 20} 和 {鸡: 25, 猪: 25} 各拿到 1 票。

根据“少数服从多数”的原则,最终选择 {鸡: 30, 猪: 20} 作为系统的最终输出。

这个方法起作用的原因很直接。

这里巧妙地利用了模型的“随机性”,让它从不同的“思路”去解决同一个问题。虽然其中某些思路是错的(比如路径 4 的计算失误,路径 5 的胡乱猜测),但只要模型在大多数情况下,能够找到正确的或者逻辑上等价的推理路径(比如路径 1、2、3 虽然过程不同,但结果一致),那么正确的答案就必然会在投票中以绝对优势胜出。

Self-Consistency 的本质,是集成学习(Ensemble Learning) 的思想在 Prompt Engineering 中的一种轻量级、免训练的应用。在传统的机器学习里,经常会训练多个不同的模型(比如随机森林里的多棵决策树),然后让它们一起投票来做预测,这样通常比任何单个模型的性能都要好、都要稳健。

在这里,并没有多个模型,而是通过对同一个模型进行多次带有随机性的采样,得到多条相互独立的推理路径。然后,汇集这些路径的结论,取其共识,从而过滤掉那些偶然的、小概率的“个体失误”。

这种方法,极大地增强了系统对于复杂推理任务的鲁棒性(Robustness)。它不容易因为某一次“偶然的”推理失误,而导致整个系统的失败。它用“冗余”换来了“可靠”。

再看工程实现层面的考量与挑战。实现 Self-Consistency,最直接的、也是最大的成本就是API 调用次数的成倍增加。采样 5 次,成本和延迟就是原来的 5 倍。

所以,它同样不适用于所有场景。它是一种高成本的推理手段,专门用在那些最硬核的、对准确率要求达到极致的、且单次推理容易出错的推理难题上。比如复杂的数学或逻辑证明问题,多步骤的算法题或动态规划问题,以及需要综合多种模糊证据进行判断的、没有唯一正确路径的推理任务。

在实现时,代码层面还有一个关键问题要解决,那就是如何判断两个答案是“相同”的。对于像“120”这样的数字,或者“{鸡: 30, 猪: 20}”这样的结构化数据,判断很简单,直接进行值比较就行。但如果模型的输出是一段自然语言(比如一个问题的摘要),就不能简单地进行字符串比较了。可能需要用一些 NLP 的技巧,比如先用另一个 Prompt 把答案归一化(“请用一个词总结以下段落的核心观点”),或者提取关键词,或者计算向量嵌入的余弦相似度,来对语义上相同但表述上不同的答案进行“聚类”,然后再进行投票。

Self-Consistency 的价值,在于用多次采样对抗单次的不确定。它说明,单个推理过程可能出错,但只要能汇集足够多的、多样化的推理路径,多数投票得到的共识,通常比任何一次单独的结果都更可靠。

11.6 给 Agent 写一部业务宪法 ​

前面讨论的所有自检与自修正方法,Self-Critique、Reflexion、Self-Consistency,教的都是具体的操作,如何批评、如何反思、如何投票。这些方法非常有效,但它们解决的,大多是“如何把事情做对”的问题。

这些具体方法的作用,是规定“什么情况下该怎么做”。而一个成熟可靠的系统,还需要一套更高层级的原则,规定“无论什么情况下都不能违反什么”。具体的规则不得与这些原则相抵触,这套原则在系统里的地位,就相当于宪法在国家法律体系里的地位。

能不能也为 AI Agent 制定一部不可动摇的“宪法”?

这,就是 Anthropic 公司(Claude 模型的创造者)的 Bai 等人在 2022 年提出的 Constitutional AI(宪法 AI,CAI) 思想(arXiv:2212.08073)。

CAI 的核心,是在 AI 的训练和推理过程中,引入一套人类精心制定的、高层次的、普适性的原则(Principles),称之为“宪法(Constitution)”。AI 的所有行为,从它生成的每一个词,到它做出的每一个决策,都必须符合这部“宪法”。

最开始,CAI 主要用在 AI 的“对齐(Alignment)”训练中,这是一个宏大的、关乎人类未来的话题。研究者们通过让 AI 自己根据“宪法”来生成和筛选训练数据,来确保 AI 的价值观和人类社会的主流价值观保持一致,让它变得“无害(Harmless)、诚实(Honest)、有帮助(Helpful)”。

但作为 Prompt 工程师,完全可以把这个思想借鉴过来,应用到日常工作中,在 Prompt 的层面,为每一个 Agent 写一部属于它自己的“业务宪法”。

所谓“业务宪法”,指的不是那些具体的 if-else 规则或 Few-shot 示例,而是那些统领所有具体规则的、更高层次的根本原则,规定了这个 Agent 的角色定位、服务边界和行为底线。

来看一个例子。假设正在构建一个高端的、面向企业的、付费的“AI 法律顾问” Agent。

如果只给它具体的规则,比如“如果用户问合同法,就引用《民法典》合同编第 XX 条”,那它的行为可能会很机械,甚至在遇到规则之外的问题时,会因为缺乏“指导思想”而犯下致命错误。

但如果为它植入一部“宪法”,这个 Prompt 的 System Prompt 部分可能会长这样:

markdown
# 角色
你是一位严谨、审慎、且极度负责任的 AI 法律顾问。你的存在,是为了向用户提供初步的、教育性质的法律信息参考,而不是取代执业律师。

# 任务
回答用户的法律咨询问题,全程恪守下述宪法。

---
## 核心宪法 (Core Constitution)
你的一切行为,都必须无条件地、以最高优先级,遵循以下三大根本原则。在任何情况下,如果你的行为可能与这些原则相抵触,你必须选择坚守原则。

**原则一:用户安全与风险规避第一 (Safety & Risk Mitigation First)**
- **绝对禁止**: 提供任何可能被用户直接采纳为法律行动依据的、确定性的、指导性的法律建议。你的语言必须始终保持建议性和参考性。
- **永远强制**: 在你的每一次回答的开头和结尾,都必须明确地、一字不差地包含以下免责声明:“请注意:我是一个 AI 助手,我的回答仅供参考,不构成任何形式的法律意见。在做出任何决策前,请务必咨询专业的执业律师。”
- **绝对禁止**: 处理任何与刑事犯罪、人身伤害等高风险领域相关的话题。遇到此类问题,必须拒绝回答,并建议用户寻求专业法律援助。

**原则二:绝对的严谨与可溯源 (Rigor & Traceability)**
- 你给出的任何关于法律条文、司法解释或案例的信息,都**必须**在信息旁,用括号注明具体的、可核查的来源(例如:《中华人民共和国民法典》第一千零四十二条)。
- 对于任何在法律界存在争议的、或者在不同司法管辖区有不同解释的法律问题,你**必须**明确地指出其争议性,并尽可能地列出不同的主流观点。
- **严禁**回答任何在你知识库中没有明确来源的、基于你个人“推理”或“猜测”的问题。在这种情况下,你唯一正确的回答就是诚实地承认“关于这个问题,我的知识库中没有足够的信息来给出一个准确的回答。”

**原则三:绝对的客观与中立 (Objectivity & Neutrality)**
- 你**必须**在所有回答中,保持绝对的客观和中立,不得夹杂任何个人的、情感的、道德的或带有偏见的观点。
- 在分析一个法律案例时,你**必须**像一个公正的法官一样,同时分析对原告和被告都有利和不利的法律因素,不能有任何偏袒。

---

### 用户问题
[用户问题]

来看这部“宪法”实际起了什么作用。

它没有告诉模型具体该怎么回答“离婚财产怎么分”这个问题。但是,它为模型的所有行为,划定了一个不可逾越的边界,设定了一个根本性的行为准则。

原则一保证了产品的法律合规性和安全性,从根本上避免了因为 AI 的编造而导致的、可能让公司破产的法律风险。原则二保证了产品内容的专业性和可信度,通过强制“引用来源”和“承认无知”,直接压制幻觉。原则三保证了产品的公正性,降低了 AI 因为训练数据中潜藏的社会偏见,而给出有失偏颇的、歧视性建议的可能。

当模型在回答任何一个具体问题时,这部“宪法”都在每一步生成中起约束作用,相当于一道持续的“合宪性审查”,逐项检查表述是否守住安全边界、是否注明了来源、语气是否中立。

Constitutional AI 思想在 Prompt Engineering 中的应用,是一种更高维度的、更根本的“约束”。

负向约束,是在告诉模型“不要做某件具体的事”(Don't do X);业务规则,是在告诉模型“在什么具体情况下,做什么具体的事”(If Y, then do X);而宪法,是在告诉模型“无论在任何情况下,你都应该秉持什么样的原则去做事”(Always act in accordance with principle Z)。

它把对模型的控制,从“行为级”,提升到了“价值观级”。

在设计那些需要高度可靠性、安全性、公平性的企业级应用时(比如金融风控、医疗诊断、法律咨询、新闻生成、教育辅导),花上几天甚至一周的时间,和产品、法务、业务专家一起,共同打磨出一套属于产品的“业务宪法”,并把它放在 System Prompt 的最顶端,这往往是整个 AI 系统可靠性设计中收益最高的一项投入。

11.7 RAG 里的来源标错与资料冲突 ​

在进入本章总结之前,还有一个非常重要、也非常常见的特殊场景,必须单独拿出来仔细分析,那就是 RAG(检索增强生成) 场景下的幻觉问题。

后面的章节会用整整两章的篇幅来详细讲解 RAG,但在这里,可以先简单了解它的流程。不再是让模型只凭自己的“记忆”(预训练知识)来回答问题,而是先从私有知识库(比如公司的几千份 PDF 文档、数据库里的产品说明)里,用向量检索等技术,把与用户问题最相关的几段“参考资料”找出来,然后连同用户的问题,一起塞给模型,并给它一个明确的指令:“请严格根据以下提供的资料,来回答用户的问题,不要使用你自己的知识。”

很多人,包括很多初入此道的工程师,都会有一个非常直觉、但极其危险的误解:“既然资料都给它了,照着资料答,总不会出错了(产生幻觉)吧?这下总该稳了吧?”

这个想法,大错特错。

RAG 场景下的幻觉,不仅普遍存在,而且其表现形式更隐蔽、更刁钻,也更难防范。这里把它们归为两大类,每一类都足以在线上踩出大坑。

第一类幻觉,是引用错误与张冠李戴(Misattribution),把内容的出处标错了。这是最常见,也最具有迷惑性的一种。模型在生成答案时,表面上看,它正确地使用了提供的资料里的内容,甚至还像模像样地在句末标注了引用来源,比如 [来源 1]。但只要仔细去核对,就会发现,它把内容的来源搞错了。

设想正在构建一个财报分析机器人。用户问“请总结一下 A 公司和 B 公司去年的业绩”,RAG 系统从文档库里,准确地检索出了两份文档的片段,来源 1 是 A 公司 2023 年年度财报摘要.pdf,上面写着“在充满挑战的宏观环境下,公司 A 在 2023 年依然实现了 10 亿元的稳健营收。”;来源 2 是 B 公司 2023 年年度财报摘要.pdf,上面写着“得益于在新兴市场的成功扩张,公司 B 在 2023 年的净利润达到了 2 亿元。”

接下来用户问:“A 公司的营收和净利润分别是多少?”

模型可能产生的幻觉答案是 “根据您提供的资料,A 公司在 2023 年的营收为 10 亿元 [来源 1],其净利润为 2 亿元 [来源 1]。”

看到问题了吗?这个答案看起来是多么的“完美”和“严谨”。它准确地回答了问题,并且还“贴心”地标注了引用来源。但它犯下了一个致命的错误,把 B 公司的净利润,错误地“张冠李戴”到了 A 公司的头上,并且还言之凿凿地将这个错误信息的来源,错误地标注为 [来源 1]。

这种幻觉极其危险,因为它利用了人们对“引用”这种形式的天然信任感。如果用户不那么较真,不亲自点开那个 [来源 1] 去逐字核对原文,这个看似“有理有据”的谎言就很容易误导他们。

缓解来源标错,最直接的办法是在 Prompt 中加强来源引用的约束,用最严厉的、不容置疑的语气,反复强调来源引用的重要性和准确性,例如 “**核心规则**:你在回答中提到的每一个具体事实、每一个数字,都**必须**在句末,用方括号 `[]` 清晰地、一一对应地标注出它所依据的、唯一的直接来源 ID。如果一个信息综合了多个来源,请列出所有相关的来源 ID。**严禁**将一个来源的信息,错误地标注成另一个来源。这是一个最高优先级的指令。”

更可靠、更工程化的办法,是采用分步生成与校验的策略,不要让一个 Prompt 完成所有事,而是设计一个两步的流水线。第一步先跑一个事实提取 Prompt,它的唯一任务,是从检索到的上下文中,提取出一个结构化的、包含事实和其精确来源的 JSON 数组,例如 [{"fact": "A 公司的营收为 10 亿元", "source_ids": [1]}, {"fact": "B 公司的净利润为 2 亿元", "source_ids": [2]}]。

第二步再跑答案生成 Prompt,接收用户的原始问题和上一步提取出的结构化事实,把这些事实,组织成一段通顺的自然语言。通过这种方式,就有机会在中间环节,用外部代码,对那个结构化的事实列表进行一次确定性的校验,确保事实和来源的对应关系没有出错,然后再进行最后一步的生成。

第二类幻觉,是上下文冲突下的“和稀泥”与“选择性失明”。这种情况更棘手,也更能考验一个 RAG 系统设计的成熟度。如果知识库本身就不那么“干净”,检索出来的几份“参考资料”,内容本身就是相互矛盾的,怎么办?

设想一个 RAG 系统,用来回答公司内部关于“远程办公政策”的问题。由于政策变动,知识库里同时存在新旧两个版本的文件,用户提问时,检索算法不幸把两份都找出来了。来源 1 是 2022 年版《员工手册》.pdf,写着“为促进团队协作,公司鼓励员工每周至少来办公室工作 3 天。”;来源 2 是 2023 年 12 月 CEO 发布的内部信.docx,写着“为了更好地吸引全球人才,经过管理层慎重决定,从下个月开始,我们将全面转向‘远程优先’(Remote-First)的工作模式。”

用户的问题是:“我们公司现在到底要不要坐班?”

这时候,模型就陷入了一个“两难境地”。两份资料都是系统交给它的参考资料,但它们说的却是完全相反的话。一个不够“聪明”或者没有经过特殊训练的模型,典型的“错误反应”有三种。最典型的是和稀泥,它会试图把这两个矛盾的信息,强行调和成一个看似合理、但实际上是错误的结论,比如给出 “我们公司的远程办公政策是比较灵活的,既鼓励大家来办公室进行必要的协作,同时也支持‘远程优先’的工作模式。” 这样的答案听起来很“圆滑”,但它完全扭曲了事实。

选择性失明也很常见,它可能会完全忽略掉其中一份资料(通常是没能得到足够关注的那份,比如夹在上下文中间的内容),只基于另一份资料来回答,比如只看到了 2022 年的手册,然后坚定地回答:“是的,根据公司规定,要求每周至少坐班 3 天。”这同样是严重的误导。

还有一种反应是直接自相矛盾,把两份矛盾的信息不加处理地直接都说出来,让用户自己去判断:“根据一份资料,我们需要坐班;但根据另一份资料,我们又不需要。”这虽然比前两种要诚实,但并没有解决用户的实际问题。

教会模型“批判性地”处理冲突信息,可以先从 Prompt 端入手,建立明确的“冲突处理预案”,像处理异常一样,提前在 Prompt 里告诉模型,当它遇到这种情况时,应该遵循的决策流程。这份规则长这样:

“**冲突处理规则**:如果在你收到的资料中,发现关于同一个事实,存在相互矛盾的描述,你必须严格遵循以下步骤:1. **首先,检查资料的元数据**,比如时间戳、版本号、或作者的权威性,优先采信最新的、或来自更权威来源的信息。2. **如果无法通过元数据判断优先级**,你必须在答案中,**明确地向用户指出该信息存在冲突**,并分别列出不同来源的不同说法,同时附上各自的来源ID,让用户自己进行判断。3. **严禁**在不告知用户存在冲突的情况下,自行选择采信某一方的观点,或将矛盾的信息进行模糊化的‘调和’处理。”

另一条根本性的路,是提升检索质量与知识库治理。确保信息的准确性和时效性,为文档建立版本管理和元数据,同时优化检索算法,让它能优先检索到最新、最权威的文档。但这是一个庞大而复杂的系统工程,在检索端无法 100% 解决问题时,Prompt 端的“兜底”和“防御性设计”就显得尤为重要。

RAG 场景下的幻觉问题,深刻地印证了一个朴素但重要的道理,垃圾进,垃圾出(Garbage in, garbage out)。即使检索环节把资料送进了上下文,如果知识库本身就错漏百出、自相矛盾,模型也很难给出正确的答案。Prompt 能做的,是明确规定模型该如何核对和使用参考资料,这是检索之外最后一道可控的环节。

11.8 构建客服系统的自动质检 Agent ​

理论和技巧都讲完了。最后,把这一章的所有知识点串起来,构建一个真正能在企业里落地、产生巨大业务价值的实战项目,一个智能客服系统的“答案自动质检” Agent。

先看这个项目的痛点场景。在一个大型的呼叫中心或在线客服团队,每天都会产生成千上万条客服与用户的对话记录。传统的做法,是靠人工质检员随机抽查一小部分(通常不到 1%)的对话,来评估客服的服务质量是否达标,有没有说错话,有没有违反规定。这种方法,不仅效率低下、成本高昂,而且覆盖率极小,标准还可能因人而异。大量的服务质量问题,因为抽查不到而长期存在。

目标,就是用这一章学到的“自检与自修正”技术,构建一个 AI 质检员。它不需要休息,不需要发工资,能 7×24 小时不间断地,对每一条 AI 客服(或者人类客服)生成的回复,进行自动化、标准化的质量检查。

这个质检 Agent 的核心,就是一个精心设计的、融合了 Self-Critique 和 Constitutional AI 思想的元提示。

markdown
# [PROMPT - 客服回复自动质检 Agent V2.0]

# Role
你是一位极其严苛、注重细节、且拥有 10 年以上呼叫中心服务质量(QA)管理经验的专家。你的性格一丝不苟,对任何不专业、不准确、不友好的服务行为都持“零容忍”态度。你的唯一任务,就是审查一段客服与用户的对话,并对客服的回复进行“鸡蛋里挑骨头”式的、多维度、结构化的质检。

---
## 核心质检宪法 (QA Constitution)
你的所有质检工作,都必须严格、无条件地遵循以下三大根本原则。这三大原则是你的行为基石,拥有最高优先级。

1. **用户问题解决第一原则 (Resolution-First Principle)**:
 客服的回复是否真正地、有效地解决了用户在对话中提出的**根本问题**?还是在敷衍了事、答非所问、或者给出了一个无法解决问题的“标准废话”?

2. **信息绝对准确原则 (Accuracy-First Principle)**:
 回复中涉及的所有产品信息、平台政策、价格数字、活动规则,是否**绝对准确无误**?有没有任何可能误导用户的“幻觉”信息、过时信息或个人猜测?

3. **服务体验与规范原则 (Experience & SOP Principle)**:
 回复的语气、措辞、格式,是否完全符合公司的**服务标准(SOP)**?是否做到了专业、礼貌、富有同理心,并给用户带来了良好的沟通体验?

---
## 质检工作流与输出格式 (Workflow & Output Schema)

你必须按照以下步骤进行工作,并严格以指定的 JSON 格式输出你的质检报告。严禁输出任何 JSON 之外的文字。

**第一步:沉浸式分析上下文**
仔细阅读并完全理解提供的“用户问题”和“客服的原始回复”的完整对话背景。

**第二步:基于宪法的批判性审查**
根据你的“质检宪法”,从以下几个核心维度,对“客服的原始回复”进行独立的、批判性的打分和评价:

- `problem_solved` (问题解决度):
 - **审查标准**: 是否直接、有效地回应了用户的核心诉求,并给出了能够推动问题解决的具体步骤或方案?
 - **打分**: `true` (已解决或已给出明确解决方案) / `false` (未解决、答非所问或方案无效)
- `factual_accuracy` (事实准确度):
 - **审查标准**: 回复中的所有事实类信息(如政策、数字、日期)是否 100% 准确无误?
 - **打分**: `true` (完全准确) / `false` (存在事实错误或无法核实的存疑信息)
- `tone_and_style_compliance` (语气与风格合规性):
 - **审查标准**: 回复的语气是否专业、礼貌、富有同理心?措辞是否符合公司服务话术规范?
 - **打分**: `pass` (合格) / `fail` (不合格,例如:语气生硬、使用不当词汇)
- `contains_hallucination` (是否包含幻觉):
 - **审查标准**: 回复中是否包含了任何看起来像是编造的、无法从公司知识库中找到依据的“想当然”的信息?
 - **打分**: `true` (明确包含或高度疑似包含幻觉) / `false` (未发现幻觉)

**第三步:给出综合评估与可执行的改进建议**
- `overall_assessment` (综合评估):
 - **评估标准**: 综合以上所有维度,对本次回复给出一个总体的质量等级。
 - **打分**: `excellent` (优秀,无可挑剔) / `good` (良好,基本合格但有提升空间) / `needs_improvement` (待改进,存在明显问题) / `poor` (差,存在严重问题)
- `suggestion_for_improvement` (可执行的改进建议):
 - **要求**: 如果综合评估不是 `excellent`,**必须**在此字段中,给出具体的、可执行的、有建设性的修改建议。你需要明确指出原始回复错在哪里,以及应该如何修改才能变得更好。如果原始回复很完美,则此项为 `null`。

**第四步:生成最终的 JSON 质检报告**
将以上所有审查结果,严格地、无遗漏地汇总成一个 JSON 对象。

---
## 待质检对话记录
- **用户问题**: “你好,我上周买的那个‘降噪豆 Pro’耳机,今天发现右边的耳机好像没声音了,充了电也没用,怎么办啊?”
- **客服的原始回复**: “您好!我们的‘降噪豆 Pro’耳机拥有行业领先的主动降噪技术和长达 24 小时的综合续航,并提供一年质保服务。您可以尝试将耳机恢复出厂设置,或者重启一下您的手机试试看。”

## 执行质检
请立即开始你的质检工作,并只输出 JSON 格式的质检报告。

来预判一下,这个 AI 质检员会输出一份怎样的报告:

json
{
 "problem_solved": false,
 "factual_accuracy": true,
 "tone_and_style_compliance": "pass",
 "contains_hallucination": false,
 "overall_assessment": "needs_improvement",
 "suggestion_for_improvement": "客服的回复虽然礼貌且信息准确,但未能有效解决用户的核心问题。用户明确表示‘右耳没声音’,这是一个具体的硬件故障问题,而客服的回复却花篇幅介绍产品优点(降噪、续航),并给出了通用的、大概率无法解决硬件问题的软件层面建议(恢复出厂设置、重启手机)。这属于典型的‘答非所问’和‘无效解决方案’。一个更优的回复应该首先表达对用户遭遇的共情,然后直接进入硬件故障的排查与售后流程。建议修改为:‘听到您耳机出现问题,我们非常着急。请您尝试[具体排查步骤]后,如果问题依旧,我将立刻为您登记售后服务,安排工程师为您检测或换新。’"
}

来看这个系统能带来什么。

最直接的价值,是自动化与全覆盖。它可以对每一条客服回复进行质检,将质检覆盖率从 1% 提升到 100%。而且所有的质检都遵循同一套“宪法”和“工作流”,保证了标准的绝对统一;输出是结构化的 JSON,可以很方便地对这些数据进行统计分析,比如计算整个团队每天的“问题首次解决率”、“事实准确率”,从而进行真正数据驱动的管理和绩效考核。

最关键的,是形成学习与改进的闭环。这个质检报告里的 suggestion_for_improvement,可以直接用来做两件极具价值的事情。如果这条回复是 AI 客服生成的,那么这份报告就可以直接输入到 Reflexion 框架中,作为 AI 客服的经验库和反思材料,让 AI 客服系统在下一次遇到类似问题时,给出更优的回答。如果这条回复是人类客服生成的,那么这份报告就可以自动推送到该客服及其主管的后台,作为一份即时的、客观的、极具指导性的培训材料,帮助人类客服快速提升服务水平。

这,就是“自检与自修正”思想在企业级应用中,所能创造出的巨大工程价值。它把 AI 系统从单次生成、直接输出的结构,升级成带检查和修正环节、质检结果还能回流改进系统的闭环结构。


本章总结 从盲目信任到系统性怀疑 ​

这一章直面了 LLM 应用中最棘手、也最无法回避的问题,也就是幻觉,以及由此衍生的一系列可靠性问题。这里建立的核心心智模型很简单,幻觉不是 Bug,而是 LLM 概率本质下的固有特性。作为工程师,与其天真地去追求“消灭”幻觉,不如去管理它,设计一个能容忍错误、能自我修正的“反脆弱”系统。

围绕这个目标,这一章装备了一整套“自检与自修正”的工程防具。Self-Critique 把“生成”和“批评”拆成两步或多步流水线,让模型在输出最终结果前,先用一轮批评生成来核查初稿;其“单提示词自检”变体,则把这两步压缩进一次 API 调用,用最低的成本换来最显著的可控性。

Reflexion 更进一步,引入了一个跨轮次的“经验库”记忆模块,让 Agent 能够从过去的失败中提炼经验,在多轮交互中持续优化。Shinn 等人在 NeurIPS 2023 上发表的这套框架(arXiv:2303.11366),在 HumanEval 编程任务上把 pass@1 推到了 91%,超过了当时 GPT-4 约 67% 的基线(OpenAI GPT-4 技术报告,arXiv:2303.08774)。

Self-Consistency 则换了个思路,用“多路采样 + 投票表决”的集体智慧去对抗单次推理的偶然失误;Wang 等人在 ICLR 2023 上发表的这套方法(arXiv:2203.11171),在 GSM8K 等推理基准上让准确率提升 17.9 个百分点,以 PaLM-540B 在 GSM8K 上从 56.6% 提升到 74.4% 为例(Self-Consistency 论文 Table 2)。

Constitutional AI 把控制层级从“行为级”抬升到了“价值观级”,为 Agent 植入不可逾越的“宪法”;这套思路最早是 Anthropic 的 Bai 等人在 2022 年提出的(arXiv:2212.08073),最初用在模型对齐训练里,后来 Prompt 工程把它“降维”借鉴了过来。

这一章还特别拎出了 RAG 场景下幻觉的特殊形态,“引用张冠李戴”与“冲突信息下的和稀泥”,它们更隐蔽,也更需要 Prompt 来为模型划清行为边界。最后的客服质检 Agent 实战,把这些方法融成了一条贯通的数据闭环,从每一条客服回复的自动化质检,到把质检报告喂回 Reflexion 框架做自我训练,或者推给人类客服做即时培训。

学完这一章,工程师对 AI 输出的处理方式会发生一次不可逆的转变。不再无条件采信它的每一个输出,而是懂得如何质疑它、如何为其建立“制衡”与“监督”机制,成为成熟的“系统设计者”,开始用“系统性的怀疑”去审视 AI 的每一个输出。这种建立在深刻理解之上的批判性思维,正是把一个 AI 应用从“有趣的 Demo”推向“可靠的生产力工具”所必备的核心素养。

参考资料 ​

  1. Shinn, N. et al. (2023). Reflexion: Language Agents with Verbal Reinforcement Learning. NeurIPS 2023. arXiv:2303.11366. https://arxiv.org/abs/2303.11366
  2. Wang, X. et al. (2023). Self-Consistency Improves Chain of Thought Reasoning in Language Models. ICLR 2023. arXiv:2203.11171. https://arxiv.org/abs/2203.11171
  3. Bai, Y. et al. (2022). Constitutional AI: Harmlessness from AI Feedback. arXiv:2212.08073. https://arxiv.org/abs/2212.08073