ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

大模型幻觉深度解析:成因、检测方法与RAG缓解实战

大模型幻觉深度解析:成因、检测方法与RAG缓解实战

这次想认真聊聊大模型幻觉问题。做了几年大模型应用落地,从最早的客服机器人到后面的行业知识问答,几乎每个项目都绕不开“一本正经胡说八道”这个坎。很多刚接触大模型的人会觉得幻觉是模型“笨”,其实真相远没那么简单——它是数据、训练方式、解码策略、用户提问方式共同作用的结果。这篇文章我会把幻觉的成因、检测手段、缓解方案以及我们在实际项目中踩过的坑,一次性讲清楚,希望能给正被幻觉折磨的同行一点参考。

1. 什么是大模型幻觉?先分清哪些算“病”哪些不算

幻觉这个词在学术界的定义是:模型生成的内容看起来流畅、语法正确、逻辑自洽,但与事实不符,或者根本没有任何事实依据。通俗点说,就是模型“编”了一个答案,而且编得特别像真的。

1.1 幻觉的两种主流分法

现在业界普遍接受的分法是两种:事实性幻觉(Factuality Hallucination)和忠实性幻觉(Faithfulness Hallucination)。

事实性幻觉主要指模型输出的内容与真实世界事实不一致。比如你问“某市面积多大”,模型报出一个和官方数据对不上的数字。这类幻觉多发生在涉及时效性信息、具体数字、近期事件、小众知识时。忠实性幻觉指的是模型输出与用户指令、上下文不一致。比如你给了一段产品文档,让模型写摘要,它却自己加了文档里根本没有的结论。这种情况在长文档处理里特别常见,模型沿着上文“顺着往下编”,编着编着就跑偏了。

还有一种很常见的分法是把幻觉分成“内在幻觉”和“外在幻觉”。内在幻觉指模型输出的内容与检索到的上下文冲突,外在幻觉则指内容无法被任何已知事实验证,但也不能说它错——比如让你做一道开放性设计题,模型给你提供的方案。

1.2 为什么大模型的幻觉问题尤其严重

很多人会拿传统搜索来做对比:搜索引擎返回的是网页,用户自己判断相关性;但大模型直接给你一个最终答案,而且没有提供任何参考链接。它天生就有“生成自信感”——语气笃定、结构工整,这让用户很难分辨对错。更麻烦的是,生成式模型在解码时会倾向于选择“概率上最合理的下一个词”,而不是“事实正确的下一个词”。在模型内部,事实正确性和语言流畅性是分开优化的,这本质上是个“表达能力”和“世界知识”拧巴在一起的问题。

所以,不要指望某个算法能“彻底消灭”幻觉。幻觉是大模型本身的属性,我们要做的是控制在可接受的范围。就像你不可能让一个健谈的人永远不说错话,但可以通过准备材料、转述规则、核对流程,把说错话的概率降到最低。

2. 幻觉从哪来?我把成因拆成三层看

只有理解了成因,你才能在具体场景里对症下药。我把幻觉的来源归纳成数据侧、训练解码侧、用户交互侧三个层面。

2.1 数据侧的根因:高质量事实知识占比太低

大模型的核心能力来自预训练语料,但语料本身的“知识密度”是参差不齐的。预训练数据里包含大量重复的论坛帖子、营销文案、小说对话、代码注释,模型在这些数据上学会了“语言的组织形式”,但并没有形成稳定的事实知识。比如你让它解释“牛顿第一定律”,它能写出标准定义,因为它见过成百上千遍;但你要问“某冷门作家的生平经历”,语料里只有零星片段,模型就只能靠语言习惯拼凑一个“看起来合理”的答案。

数据侧还有一个隐蔽问题:时效性缺失。模型的知识截止日期是固定的,之后发生的新闻、产品发布、人事变动完全不在知识范围内。如果用户问的是截止日期之后的事,模型会被迫“推理”出一个答案,幻觉就不可避免。

2.2 训练与解码:不确定性被强行“抹平”了

从训练角度看,交叉熵损失函数鼓励模型给“标准答案”分配高概率。当一个问题的上下文出现多个可能的实体、数字和事件时,模型会被迫选择一个最高概率的路径,而不是表达“我不知道”。再加上人类反馈强化学习(RLHF)阶段,标注员通常会倾向于给流畅、完整的回答打高分,这变相鼓励了模型“多编一点,别留空白”。

从解码角度看,采样参数也有讲究。温度太高时,生成随机性增大,更容易出现语义漂移;温度太低时,模型容易陷入重复,但也可能陷入“高频词陷阱”——比如在所有不确定的环节都填上一个最常见的答案,让错误变得隐蔽。

2.3 用户交互侧:提问方式能放大幻觉

这一点很容易被忽略。当用户给出一个带有预设的、误导性的问题时,模型会顺着用户的思路回答。比如你问“A公司和B公司哪家研发投入更高”,这个问题本身默认了“两家都高”,模型不会主动纠正这个前提,而是直接给出对比结果。更常见的是,问题过于模糊、范围太宽,模型只能“猜”你的意图,猜得越努力,编得越远。

还有一个典型场景:多轮对话中的“语境粘附”。前面几轮聊的内容如果出现了错误信息,模型会在后续回复中沿用这个错误,因为对话历史本身就是它的上下文依据。这就是为什么有时候你越追问,模型错得越“坚定”。

3. 怎么发现幻觉?我常用的三类检测思路

聊完成因,下面说检测。幻觉检测在生产环境里不是可选功能,而是一个必须落地的质量关卡。我的经验是:不要依赖单一检测手段,至少叠两到三层。

3.1 基于事实核查的检测

这是一种“事后校验”思路:让模型生成了答案之后,我们用另外一个模型或者检索工具去核对答案里的“事实性断言”。具体做法是先把答案拆成若干个最小的事实单元,称为原子断言,然后逐个验证。

举例说明。假设模型回答:“结构化提示是2025年3月起面向企业用户开放。”拆成的断言是“结构化提示在2025年3月推出”“企业用户可以访问”。我们拿这些断言去检索,如果找不到对应信息,就标记为“无法验证”;如果找到的信息与断言冲突,就标记为“错误”。这种方法适合信息密度高的场景,比如新闻摘要、医疗知识问答。

3.2 基于一致性的检测

一致性检测的核心逻辑是:让模型对同一个问题重复回答多次,比较答案是否一致。如果多次回答不断出现关键实体、数字、结论的变化,大概率是在“编”。

这里有两种常用做法:一种叫“采样一致性”,就是固定温度高于1.0,对同一个问题生成5到10次,编辑距离或者语义相似度低于阈值就判为高风险;另一种叫“反向校验”——先生成答案,再故意提出一个和答案相反的断言,问模型是否同意。如果模型对自己生成过的答案表现出高度不确定,说明本身就不稳。

3.3 基于不确定性的检测

模型在输出时其实对每个 token 都有一个概率值。很多时候,模型“知道自己不确定”,只不过最后输出的那一串文本掩盖了这一点。我们可以通过捕获这些概率值来评估不确定性。

我在项目里常用的一种方法是序列概率归一化——对生成的答案计算平均对数概率。平均概率越低,幻觉风险越高。我在这里用一段伪代码说明思路:

from transformers import pipeline import numpy as np generator = pipeline("text-generation", model="某开源7B模型") def sample_generation(prompt, temperature=1.0): # 额外返回每个token的logprob return generator( prompt, max_new_tokens=200, temperature=temperature, return_full_text=False, output_scores=True, return_dict_in_generate=True, ) def avg_logprob_score(sample_result, tokenizer): scores = sample_result["scores"] # 每个token位置的概率分布 sequences = sample_result["sequences"] logprobs = [] for pos, score in enumerate(scores): expected_tokens = sequences[0][pos + 1] # 实际被选中的token logprob = score[0, expected_tokens.item()] logprobs.append(logprob.detach().numpy()) return float(np.mean(logprobs)) prompt = "某公司的股东结构是怎样的?" gen_result = sample_generation(prompt) if avg_logprob_score(gen_result, generator.tokenizer) > -1.0: print("低风险")

注意,这里的-1.0是经验值,不同模型差异很大,使用前先在自己数据集上校准一下。基于不确定性的检测好处是速度快、不依赖外部检索,适合在低延迟要求的场景中做第一道初筛。

4. 缓解幻觉的实操方案:RAG、微调、Prompt 与解码策略

检测是发现问题的,缓解才是核心目标。接下来分享我们项目里真正用下来有效的几套方案。

4.1 RAG 不是万能药,关键在于“召回密度”与“提示构造”

检索增强生成(RAG)是目前生产环境中的主流方案,但它经常给人一种虚假的安全感——觉得接了知识库就不会幻觉了。实际上,RAG 的幻觉问题经常出在“上下文没被用到”。

我在实际项目里观察到一个现象:当检索到的文档与问题相关度足够高时,模型会优先参考文档。但相关度一旦出现“模糊”,比如检索到了两篇互相矛盾的文档,模型就会自由发挥了。

为了缓解这个问题,我建议在三个位置做精细处理。第一,检索阶段不要只用一个向量数据库,同时做关键词检索混排。向量检索擅长语义匹配,BM25关键词检索擅长精确匹配,二者结果做 RRF 融合,召回质量提升明显。第二,提示词里要明确给出“引用约束”:“你只能基于以下上下文回答。如果上下文不包含答案,请回答不清楚,不要猜测。”第三,对检索文档做重排序,把最相关的段落放在距离问题最近的位置。上下文顺序对生成效果有直接影响。

训练数据的经验是,必须加入“对抗性样本”——即在上下文中故意不包含答案,迫使模型学会说“不清楚”。如果 RAG 数据里全是“上下文刚好有答案”的场景,模型就会被训练成默认上下文里一定找得到答案,这反而会加剧幻觉。

4.2 微调:别指望微调能补充新知识

很多人误以为微调可以让模型“记住”大量新知识,进而减少幻觉。这里必须说清楚:低秩适配微调的参数量远不足以编码大量事实知识。它的作用是改变模型的“行为模式”,而不是更新知识库。

如果你要做领域微调,我建议把重点放在“形式规范”和“拒答行为”上。比如让模型面对超出知识范围的问题时,统一回复为“当前知识库暂无相关资讯,建议咨询专业人士”;让模型在生成答案时强制以“根据提供的信息”作为开头;让模型输出结构遵循固定的 JSON 或者“结论-论据-来源”三段式。这些都是微调能切实改变的东西,比硬塞知识有效得多。

有一个必须避开的坑:微调数据不能直接从公开数据集里复制,要针对你自己的领域做清洗。如果微调数据里本身就存在前后矛盾的句子,模型学会的就不是正确决策,而是“混乱”。我之前踩过这个坑:某次微调用了自动抓取的产品页面数据,没有做时效性过滤,结果模型把已废弃产品的信息当成了新特性输出,整个线上应用出了问题。

4.3 解码策略与 Prompt 约束:“让模型承认不知道”是训练出来的

解码层面的调整是成本最低的干预。温度参数的影响很多人知道,但很少有人会刻意调高top_p和frequency_penalty的组合效果。在事实问答场景,我通常会把温度设到 0.2 或更低,top_p设为 0.9。但这里有个细节:如果任务带有创意性质,比如写营销文案、头脑风暴,温度则要放开到 0.7 以上,否则会显得机械重复。不同任务的性质决定了要调适度的参数。

Prompt 约束也很重要。在提示词里加入“事实核查指令”能显著降低幻觉:明确要求模型在回答之前先自检,把每一个断言和自己知道的事实进行比对;要求模型把不确定的部分标注出来。同时支持让模型明确说“不确定”——这在很多场景中其实比错误答案更有价值,尤其是医疗、法律、金融这类高风险领域。我们可以把规范化的拒答句式写进提示词系统层,类似“对不起,我无法确认该信息的真实性,请提供更多上下文或查阅官方来源。”

4.4 评估闭环:没有评估体系的幻觉缓解都是空谈

很多团队做幻觉优化是“拍脑袋式”的:出一个方案,人工看几个例子,觉得不错就上线。这样在大规模场景下完全不可靠。我强烈建议搭建一个自动化评估集,至少包含三类样本:

样本类型数量建议示例
标准问答样本200-500条领域内高频问题,附带标准答案
陷阱样本100-200条问题上下文不包含答案,检验拒答能力
对抗样本50-100条包含预设错误前提的问题,检验纠错能力

评估指标上,声誉法可以用快速精确匹配计算准确率,但更推荐用模型作为评判员给答案打分,再结合事实核查对断言进行验证。这样能同时覆盖“是否回答正确”和“是否包含幻觉断言”两个维度。

顺便提醒一下:评估集要定期加入线上出现的真实错误样本。每次线上用户反馈出幻觉问题,就把它纳入回归测试集。这个做法帮我避免了很多次“修了东墙漏西墙”的情况。

5. 一个可落地的综合案例:给某行业知识问答系统做幻觉治理

下面结合我在一个模拟项目里的经历,完整介绍一套从问题发现到效果提升的实施路径。这个系统服务于某垂直行业从业者的日常查询,答案必须准确、可溯源,对幻觉容忍度极低。

5.1 场景与方案设计

系统上线初期的基础模型是某开源大模型,直接调用。刚上线时的问题率高得惊人:经过人工抽检,我们认为有“明显错误或无可验证依据”的回答占比约25%。这个数字对于内部测试或许尚可接受,但对生产环境来说完全无法忍受,几乎每四条答案里就有一条存在问题。

我做了三步整改。第一步,放弃直接裸用基础模型,接上领域知识库做 RAG,同时对提示词进行了严格的引用约束。第二步,用领域语料做了低秩适配微调,训练重点是规范化输出格式和拒答行为,而不是灌输知识。第三步,搭建了基于事实核查和采样一致性的双层幻觉检测服务,对模型的输出进行实时把关拦截。

5.2 效果实测

经过两周的迭代,我们对三个阶段的版本都做了乱序测试,每组 300 条问题。这三个版本分别是:基础模型、加了 RAG 的版本、RAG+微调+检测的完整版本。结果如下:

指标基础模型RAG版本完整版本
事实性准确率71%82%89%
拒答率(回答“不清楚”)5%10%18%
答案可追溯率0%68%74%
明显幻觉占比25%11%6%

这个表里的数据有几个值得注意的地方。加了 RAG 之后,拒答率反而提高了,这不是坏事——说明模型开始意识到“没有资料就不能硬答”。完整版本中明显幻觉占比降到了 6%,剩余的错误集中出现在用户提供的专用名词、缩写拼写不规范等小众场景,说明数据侧仍存在边缘盲区,这类问题没法靠模型层彻底解决,只能靠持续补充知识库。

5.3 踩坑记录与经验沉淀

整个改进过程踩了不少坑,挑三个最典型的分享。

第一个坑:最初测试 RAG 时把检索段落数量设成了 6,以为“上下文给得越多越好”。结果模型把多个不相关段落里的信息做了“缝合”,反而产生了幻觉。后来把段落数量缩到了 3,并加了“只引用与问题最相关的一段”的指令,错误明显下降。

第二个坑:微调数据里加入了一批“带标准答案”的问题,模型在微调后答题率大幅度提升的同时,出现了“过度自信”问题。它对所有问题都倾向给出一个答案,哪怕没有依据。后来我们在微调数据里专门增加了一批“无答案”样本,告诉模型什么是“不知道”,才算扭回来。

第三个坑:事实核查依赖外部检索时,如果检索库本身数据质量差,会把正确的答案标记成幻觉。我们在项目里花了很多精力清洗知识库、建立同义词映射,然后才让核查服务上线。检测服务只有在知识库可靠的前提下才可信。

6. 最后分享几个实用小技巧

上面讲了这么多方法论,最后分享几个可以直接抄作业的经验点。

技巧一,做知识库预处理的时候,统一将文档按语义切块,同时保留块与块之间的标题层级关系。每个块都附上来源标签、更新日期、所属分类,这样在生成阶段可以强制模型输出来源,便于用户溯源。溯源成本很低,但对治理幻觉有奇效,因为它倒逼模型“引用而不是胡编”。

技巧二,部署线上系统时,对所有模型输出都做一遍“低置信度拦截”。我们内部的做法是:当序列平均对数概率低于阈值时,不直接输出给用户,而是把回答降级为“我未能找到足够权威的资料,请换个说法重试”,或者触发人工客服介入。与其让用户看到错误答案,不如让用户看到诚实的回应。

技巧三,每隔一段时间用“错误案例复盘会”的方式,找几个线上典型幻觉样本,让研发和标注团队一起定位出错环节。你会发现很多问题的根因不是单一模块,而是检索召回错误、知识库信息过期、提示词指令含糊等多个环节叠加的结果。这种复盘比任何新算法都更帮你理解系统短板。

幻觉问题不会消失,但随着你对模型行为、数据质量、交互设计三者的理解加深,它是可以被压到可接受范围的。我个人的体会是:治理幻觉没有银弹,但系统性工程手段一定比任何花哨的模型技巧都有效。先用评估体系把问题量化,再用 RAG、微调、检测拦截逐层压实,你就能在一个“会说错话”的模型上构建出可靠的产品。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进