LLM 的幻觉是结构属性而非缺陷,依赖 prompt 调优或 RAG 无法根治;必须设计自我纠正 Agent 循环并保持人类对高风险决策的参与。
原文首次发布于 tamiz.pro。
你的生产环境 LLM 助手刚刚告知一位客户他们的退款已处理完毕。实际上并没有。客户从未收到退款。这张工单现在成了一起法律纠纷,而你的工程师们正手忙脚乱地追查原因——明明在预发环境通过了所有安全基准测试的模型,为什么在生产环境中会如此自信地陈述虚假信息。
这不是提示工程的失败,也不是 RAG 流水线的 bug。当你把生产系统构建在根本上不可靠的文本生成器之上,然后称之为"完成了",这就是必然会发生的事。
我需要在这里阐明的硬道理很简单:幻觉并非 LLM 的缺陷——它是结构性属性。只要我们继续把大型语言模型当作甲骨文式的答题机器,我们就注定会交付破碎的系统。唯一可行的出路是范式转换:面向失败进行设计、实现自我纠错的智能体循环,并在高风险决策中保持人类有意义的参与。
在讨论解决方案之前,我们需要真正理解我们面对的是什么。下一个 token 预测器并不"知道"事实。它根据训练期间学到的统计模式来预测 token。当被问到超出其知识分布的问题时——甚至在分布之内时——模型内部并没有一个"我不知道"的开关。它拥有的是对整个词表的一个温度调节后的概率分布,并从中采样。
模型没有"真"的概念,只有"似真"的概念。
置信度与正确性是脱钩的。最自信陈述出来的幻觉仍然是幻觉。
随着上下文窗口扩展,模型从训练数据中组合信息,编造模式会复合累积。没有验证的思维链推理不仅不会减少错误,反而会放大错误。
学术界对这个问题早已知晓多年。诸如《对分布偏移的鲁棒性》、《大型语言模型的事实一致性基准测试》等论文,以及关于谄媚问题(The Sycophancy Problem)日益丰富的文献,都指向同一个发现:你无法通过微调或提示工程摆脱根本性的不确定性。
然而我们依然把 LLM 当作套在对话界面里的小型确定性服务来对待。我们把它们集成到面向客户的流程中、金融推荐引擎中、法律文档审查流水线中——然后当它们在生产压力下产生看似合理但错误的输出时,我们却感到惊讶。
COPS 框架——自我纠错生产系统(Self-Correcting Production Systems)——指的是一类智能体架构,其中模型不只是生成答案然后发出,而是在输出后运行一个验证循环,包含批评、修正和重新生成。模型不是权威。它只是一个多步骤推理流水线中的组件。
从高层次看,架构如下:
┌─────────────────────────────────────────────────┐
│ Input / User Query │
└──────────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ Step 1: Initial Generation │
│ (LLM produces candidate response) │
└──────────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ Step 2: Verification / Criticism │
│ (Separate model or prompt checks for │
│ factual accuracy, logical consistency, │
│ policy compliance) │
└──────────────────────┬──────────────────────────┘
▼
┌────────┴────────┐
│ │
VERIFIED NOT VERIFIED
│ │
▼ ▼
Return Output Step 3: Self-Correction
(Model revises based on
critique feedback)
│
▼
Re-enter Step 2
(bounded iterations)
关键的洞见在于:验证与生成是解耦的。同一个模型可能生成答案,但一个独立的批判性评估——无论来自另一个模型实例、规则引擎还是结构化的事实核查提示——来评判其正确性。这就是"学生答题"与"学生在被实时评分的情况下答题"之间的区别。
一个设计良好的自我纠错循环在三个阶段运作:
生成:主智能体产生输出。
批评:批评组件——可以是第二次模型调用、确定性验证器或混合方案——根据真实约束、策略规则或逻辑一致性检查来评估输出。
修正:如果批评识别出问题,智能体会修改输出并重新进入循环,直到达到有限次数的迭代上限。
这不是一个新概念。它直接映射到程序综合(program synthesis)中的思想(如 COP 等系统展示了自我改进的代码生成),以及人类反馈强化学习(RLHF)——但这是在推理时而非仅在训练期间进行操作化应用。
微调和 RLHF 优化模型趋向真实的能力。它们移动概率分布。但它们无法消除尾部——那些模型没有见过足够多相似模式、默认进行似真编造的场景。
推理时的自我纠错处理尾部问题。它把幻觉视为需要检测和修复的东西,而非仅靠训练就能预防的东西。这是一个根本不同的工程姿态:不是试图构建一个从不失败的系统,而是构建一个能识别并从失败中恢复的系统。
让我来详细讲解这在生产代码和系统设计中实际是什么样子。
最常见的模式是在生成器旁边运行一个批评模型。这不需要是一个独立微调的模型——可以是相同的基础模型配合不同的系统提示,或者一个更小、更便宜、针对验证任务优化的模型。
# 生产模式概念示例
async def self_correcting_inference(
user_query: str,
generator: LLMClient,
critic: LLMClient,
max_iterations: int = 3,
confidence_threshold: float = 0.85
) -> GenerativeOutput:
for iteration in range(max_iterations):
# 阶段 1:生成
response = await generator.generate(
prompt=user_query,
temperature=0.3 # 初始生成用较低温度
)
# 阶段 2:批评
critique_prompt = build_critique_prompt(user_query, response.text)
critique = await critic.generate(
prompt=critique_prompt,
temperature=0.1 # 评估用极低温度
)
# 阶段 3:评估裁决
verdict = parse_verdict(critique)
if verdict.confidence >= confidence_threshold:
return GenerativeOutput(
text=response.text,
iterations=iteration + 1,
verified=True,
critique_summary=verdict.summary
)
# 阶段 4:根据反馈自我修正
correction_prompt = build_correction_prompt(
user_query, response.text, critique.text
)
response = await generator.generate(
prompt=correction_prompt,
temperature=0.3
)
# 所有迭代耗尽——升级处理
return GenerativeOutput.escalate(
query=user_query,
last_response=response.text,
reason="max_iterations_exceeded"
)
注意这里几个重要的设计选择:
有界迭代:始终给修正循环设置上限。无限制的自我纠错是延迟和成本风险。
批评用低温度:批评模型应该是确定性的,而非创造性的。
升级路径:当循环在未验证的情况下耗尽自身时,系统不会返回一个尽力而为的幻觉结果。它会升级——要么升级给人工审核员,要么返回一个后备响应。
并非所有验证都应该通过模型。当你的生产系统处理结构化领域时——金融计算、法律规则检查、监管合规——你可以(而且应该)使用确定性验证器,或替代批评模型,或与之配合。
// 示例:金融建议流水线的确定性验证器
interface FinancialAdviceVerifier {
validate(output: string, context: ConversationContext): Verdict;
}
class RegulatoryComplianceVerifier implements FinancialAdviceVerifier {
private readonly restrictedClaims = [
/^guaranteed\s+return/i,
/^risk[- ]?free/i,
/^no[- ]?loss/i,
];
validate(output: string, context: ConversationContext): Verdict {
const violations = this.restrictedClaims
.filter(pattern => pattern.test(output))
.map(pattern => ({ pattern: pattern.source, matched: output.match(pattern)?.[0] }));
const factualCheck = this.checkNumericalConsistency(output, context);
return {
verified: violations.length === 0 && factualCheck.passed,
issues: [...violations.map(v => ({ type: 'regulatory', detail: v })), ...(factualCheck.issues || [])],
severity: violations.length > 0 ? 'high' : 'medium'
};
}
}
这就是大多数生产系统应该追求的混合方案:基于模型的验证用于语义和上下文正确性,确定性验证用于硬约束和策略执行。
自我修正可以降低但无法消除风险。总会有边界情况:批评模型本身被欺骗、修正循环收敛到一个看似合理实则错误的答案,或者领域过于新颖以至于无论多少轮迭代都无法产生可靠输出。
这时人工介入治理就变得不可或缺。设计原则不是"人工审查一切"——那不可扩展,而是:
人工审查高风险决策: 金融交易、法律结论、医疗建议、大规模内容审核。
人工审查低置信度输出: 当批评模型和修正循环都未能达到验证阈值时,转交给人工审核员。
人工反馈作为训练信号: 每次人工纠正都成为改进批评模型的数据点,形成良性循环。
运维架构如下:
┌──────────┐ 已验证 ┌──────────────┐
│ 用户 │──────────────▶│ 输出给 │
│ 输入 │ │ 终端用户 │
└────┬─────┘ └──────────────┘
│
│ 未验证 / 低置信度
▼
┌──────────┐ 标记 ┌──────────────┐
│ 人工 │◀──────────────│ 进入 │
│ 审核员 │ │ 审核队列 │
└────┬─────┘ └──────────────┘
│
│ 纠正 / 批准
▼
┌──────────────────────────────────────────────┐
│ 更新训练数据 → 微调批评模型 │
│ → 提升未来自动化验证能力 │
└──────────────────────────────────────────────┘
我在每次技术大会和无数工程 Slack 频道里都听过这种论调:"我们只需要更好的提示词。Few-shot 示例、思维链、更好的系统提示——问题就会消失。"
不会的。原因如下:
提示词塑造行为,但不改变架构。 更好的提示词可以通过引导模型产生更接地气的回答来降低幻觉频率。但它无法消除根本机制:没有真值保证的下一个 token 预测。你在优化的是概率分布,而不是安装一个验证层。
思维链推理不是验证。 自洽性和 CoT 技术提高了推理基准的准确率,但它们仍在生成——而不是在检查。一个逐步思考并得出错误结论的模型仍然是错误的,而且因为有推理的外观而错得更加自信。
对抗性差距在扩大。 随着模型越来越擅长产生看似正确的输出,"看起来正确"和"实际正确"之间的差距也在扩大。更好的提示词让模型成为更老练的编造者,而不是减少编造的可能性。
这不是当前提示词工程的局限。这是理论极限。正如关于 LLM 自我评估不可靠性的研究所示,模型无法可靠地判断自身输出的质量——其可靠性不会超过它最初生成质量输出的能力。
如果你在构建生产级 LLM 系统——我是说生产级,不是周末小项目——含义很明确:把你的系统设计成仿佛模型会说谎,因为它会的。
实践中这意味着:
像医生对待初步诊断一样对待 LLM 生成的内容。它是验证的起点,不是结论。你的系统应该在数据流中编码这一点:每个模型输出在到达终端用户之前都要经过验证阶段。
大多数团队把资源倾注在让生成器更聪明上。批评模型才是 ROI 所在。一个能以低误报率捕捉 95% 幻觉的调优良好的批评模型,比一个只将幻觉减少 5% 的生成器更有价值。
记录每个验证决策。追踪批评模型标记输出的频率、哪些类别的错误出现、以及纠正成功的频率。这些数据对两件事至关重要:持续改进你的验证流水线,以及出问题时可审计。
你的系统需要有明确的规则来决定何时信任自动化、何时升级。这些应该基于领域风险,而不是任意的置信度阈值。医疗诊断聊天机器人和客户支持机器人即使使用相同的模型,也有非常不同的升级需求。
如果你不测量幻觉率,你就是在盲目运营。实现评估工具,对生产输出进行采样并对照真值评分。这应该是持续的,不是一次性的基准测试练习。
我的论点直说如下:
生产级 LLM 的信任不来自于让模型更诚实,而来自于构建一个能检测模型何时不诚实并防止有害输出触达用户的系统。
自我修正智能体架构(COPS)和人工介入治理不是 LLM 系统的可选项。它们是任何声称可信的生产部署的基石。其他一切——更好的提示词、更大的上下文窗口、微调——都是建立在这个基石之上的增量优化。
所需的工程文化转变意义重大。这意味着接受 LLM 是概率工具,不是确定性服务。这意味着在堆栈的每一层都设计验证。这意味着投资许多团队目前忽视的评估基础设施。
但另一种选择——发布 LLM 驱动的产品并希望模型做对——是一种责任策略,而不是工程策略。
关于构建可靠 AI 系统和实用架构模式的更多内容,我在 Tamiz's Insights 上有深入报道,包括验证流水线、经济高效的自修正架构的深度解析,以及在监管环境中部署 AI 的运营现实。
Q:自我修正是否会给生产系统带来不可接受的延迟?
A:是的,会增加延迟——通常比单次生成多 2-3 倍。这是一个真实的工程权衡。缓解方法是:将自我修正保留用于高风险输出,对低风险交互使用快速单次生成配合轻量级过滤。并非每个 LLM 调用都需要完整的 COPS 流程。
Q:能用更小、更便宜的模型做批评模型吗?
A:完全可以。事实上你应该这样做。批评模型不需要生成能力——它需要的是判别判断能力。一个针对验证任务微调的 7B 参数模型可以胜过用作通用批评模型的 70B 模型,成本却只有后者的一小部分。领域特定的验证器(确定性规则 + 小模型)效率更高。
Q:如何处理生成器和批评模型都出现幻觉的情况?
A:这是最难的情况,也是人工介入必不可少的根本原因。当两个模型都失败时,系统必须升级而不是返回未验证的输出。关键防御是多样性:如果批评模型在架构上与生成器不同(例如,规则-based 验证器结合独立模型),相关联失败的概率会显著降低。