用大模型久了都会遇到这个场景:让它介绍一本书,它写得头头是道,作者、出版社、章节名一应俱全,但你去搜发现根本没有这本书。这类现象业界叫“幻觉”(Hallucination)。它不是偶发故障,而是大模型工作方式决定的常态。
幻觉是大模型生成的、听起来合理但和事实或输入不符的内容。
关键在“听起来合理”。如果模型胡言乱语明显不通,用户一眼就能识别。真正麻烦的是那些语法通顺、语气自信、细节丰富,但事实是错的输出。
为什么会有幻觉
大模型的训练目标是预测下一个 token。给定前面的上下文,选一个概率最高的 token 输出,如此循环。这个目标里没有“讲真话”这一项。
具体到几个层面:
训练数据本身不完美。互联网语料里有过时信息、错误信息、观点冲突。模型不知道哪个是对的,只学到“这些说法都可能出现”。
参数化压缩有损。模型把万亿 token 的知识压进几千亿参数里,注定要牺牲精度。常识和高频事实压得住,冷门细节压不住。压不住的部分不是“消失了”,而是变成了模糊的记忆,生成时会被相邻的语义拉过去。
生成过程是概率采样。哪怕最高概率的 token 是对的,采样时也可能选到第二第三概率的。温度调高时更明显。
上下文长度有限。模型无法记住训练时见过的每一条事实。真到需要用的时候,它只能“感觉这里应该是什么”,而不是“我确切知道是什么”。
训练时鼓励说话。RLHF 阶段人类偏好“给出答案”的回复,模型学到“回答比拒答更受欢迎”。结果就是它宁可编也不愿意说“我不知道”。
这几层叠加起来,幻觉就是必然产物,不是训练不够多能解决的。
常见的几种类型
事实性幻觉:编造不存在的人、书、论文、API、参数。写代码时最容易遇到——让它用某个库,它调用一个根本不存在的方法名,签名倒是很像。
上下文幻觉:给了它一段文档让它总结,它总结出文档里没写的内容。RAG 系统里最常见的故障模式。
逻辑幻觉:前提正确、结论合理,但推理链里有一步是错的。数学题、多步推理题里高发。
指令幻觉:假装自己完成了没做的操作。比如让 Agent 调工具查数据库,它没查,直接编了一段“查到的结果”。
元幻觉:吹嘘自己的能力。“我可以访问实时网络”、“我记得我们上次聊过 X”,实际都没有。
一个具体例子
下面是让模型写一段 Python 代码的场景:
# 用户:帮我用 requests 库发一个带重试的 GET 请求
import requests
def fetch(url: str, max_retries: int = 3):
session = requests.Session()
session.mount('http://', requests.adapters.HTTPAdapter(
max_retries=max_retries,
backoff_factor=0.5,
))
return session.get(url).json()代码看起来非常专业。问题是 HTTPAdapter 的构造函数根本没有 backoff_factor 参数——backoff_factor 是 urllib3.Retry 的字段,模型把两个类的接口混起来了。跑一下就报错。
这种幻觉最难防:签名对、名字对、上下文对,唯独现实里不存在这个用法。
幻觉率的粗略量级
不同任务下的幻觉率差别很大。用一份公开评测(Vectara 的 HHEM Leaderboard,专门测总结类幻觉)的数据粗略感受:
| 任务类型 | 主流模型幻觉率 |
|---|---|
| 有明确文档的总结 | 1%~4% |
| 常识问答 | 5%~10% |
| 冷门事实问答 | 15%~30% |
| 引用来源、日期、编号 | 更高 |
| 代码 API 调用 | 因场景而异,常见 5%~20% |
冷门事实上没有一个模型是安全的。GPT-5、Claude 5 也不例外——它们只是比早期模型出错的时候更少,一旦出错还是同样自信。
工程上怎么压
幻觉压不到零,但可以压到“可接受”。手段大致分四层:
改 prompt。明确告诉模型“资料里没有的信息就说不知道,不要编”。这一句加与不加,很多任务上幻觉率能差好几倍。
加检索。把可靠资料通过 RAG 塞进上下文,让模型基于资料回答而不是靠记忆。这是最有效的一层。
加工具。需要事实性回答的场景,让模型调用搜索、数据库、API,而不是自己编。Function Calling 就是干这个用的。
加校验。生成后再走一次校验:调用真实 API 确认引用的链接存在、跑一遍代码确认能通、用另一个模型评估回答质量。这层叫 self-check 或 verifier。
四层从便宜到贵、从粗到细。真实系统里通常几层叠加。
Prompt 层的一个小技巧
下面这两版 prompt 效果差距很大:
[!code --]
你是一个助手。基于以下资料回答问题。
资料:{context}
问题:{question}[!code ++]
你是一个助手。基于以下资料回答问题。
严格要求:
1. 只使用资料中明确写出的信息,不要补充资料外的内容。
2. 如果资料里找不到答案,直接回答"资料中没有相关信息",不要猜测。
3. 引用资料内容时,标注它出现在哪一段。
资料:{context}
问题:{question}第二版让模型有一个“体面的退路”——说不知道是被允许的、甚至是被鼓励的。这解除了它“必须给答案”的压力,幻觉会明显下降。
什么场景幻觉最危险
按后果严重程度排:
医疗、法律、金融建议:错的答案可能造成真实伤害或经济损失。
代码生产环境:调用不存在的 API、数据库操作参数错误、安全配置错误。
引用和来源:编造论文、法条、判例,学术和法律场景不可接受。
多步 Agent:一步幻觉后面全崩,且模型自己不知道错了。
面向公众的输出:客服回复、公告生成,错误会被放大。
这些场景不应该只依赖 prompt 层的防御,必须叠工具调用、校验、人审中的至少一层。
什么时候可以放任
有些场景幻觉反而是好事:
- 创意写作、故事生成、头脑风暴——本来就要求“编”。
- 代码脚手架、想法探索——生成后本来就要改。
- 私人使用的娱乐场景——错了也无所谓。
判断标准是:生成物会被谁、以什么方式验证。如果用户会读、会改、会跑,幻觉可以容忍;如果直接输出到用户或生产环境,就必须防。
一些工程经验
- 默认认为模型在幻觉。所有事实性输出先假设不可靠,再决定校验粒度。
- 具体细节最不可信。日期、编号、URL、精确数字、API 参数,全部另找可靠来源核对。
- 越具体的问题越容易幻觉。让它讲“React 是什么”没事,让它讲“React 18.2.14 引入了哪些 API” 就危险。
- 模型的自信程度不代表准确性。它对错误答案和正确答案通常同样确信。不要因为“它讲得挺笃定”就信。
- 多模型交叉不完全可靠。两个模型可能因为相同的训练偏见给出相同的错答案。真正的验证要落到工具或外部资料上。
- 让模型标注不确定。让它对回答里的每个事实标“确定/不确定”,虽然不完美,但比不做强。
写在最后
幻觉不会因为模型更大而消失,只会变得更隐蔽。一个总是 60% 幻觉的模型很好防,因为用户天然警惕。一个 95% 时间都对的模型反而危险——用户放松警惕,那剩下 5% 的错误就直接过关了。
对使用者来说,“知道它会错、知道它在哪些场景更容易错、知道怎么设计防御”,比追逐更强的模型更重要。
