前言
在面试中聊到大模型幻觉,不少同学脱口而出就是“做个 RAG 外挂知识库就行”。但如果追问一句:为什么纯生成模型一定会胡编?RAG 具体靠什么机制把模型按在事实里?这篇文章把这套链条彻底拆开。
文章目录
- 前言
- 一、大模型为什么总爱一本正经胡说八道
- 1.1 纯生成模型的参数记忆缺陷
- 1.2 为什么只靠微调解决不了幻觉
- 二、RAG 是怎么把模型按在事实里的
- 2.1 事实锚定与边界约束
- 2.2 在代码中实现防幻觉上下文装配
- 三、动态按需检索与幻觉检测
- 3.1 观察 Token 不确定性来触发二次检索
- 3.2 忠实度评估与输出守门
- 四、RAG 会带来两类新问题
- 4.1 切片断章取义引发的新幻觉
- 4.2 检索延迟与系统复杂度的代价
- 写在最后
一、大模型为什么总爱一本正经胡说八道
很多人把大模型当成一个无所不知的超级数据库,这从一开始就理解错了。
大模型本质上是一个基于概率的文本续写器。它并没有真正理解客观世界,它的全部知识都压缩在成百上千亿的参数权重里(Parametric Memory)。
1.1 纯生成模型的参数记忆缺陷
当你在对话框里向 GPT 提问时,模型在底层做的事情只有一件:根据前面的文字,计算词表中几万个 Token 里哪一个出现的条件概率最高。
这里有一个非常典型的翻车案例。如果你问纯生成模型:“爱因斯坦为什么能拿到诺贝尔物理学奖?”
很多模型在没有外挂知识库的情况下,会脱口而出:“因为爱因斯坦提出了相对论。”
稍微了解物理学史的人都知道,爱因斯坦 1921 年获得诺贝尔物理学奖的真正颁奖理由是“发现了光电效应定律”,根本不是相对论。但大模型为什么会说错?
原因很简单:在互联网的海量公开语料里,“爱因斯坦”和“相对论”两个词绑定的频率实在太高了。在模型的参数权重里,它们的关联概率断层式领先。当模型内部缺乏精确的事实记忆时,为了保证语言的通顺度,它就会自然而然地按照最高概率顺着往下编。
这种仅靠参数记忆的生成机制,直接带来了两个致命短板:
- 时效性滞后:模型的知识完全定格在训练数据切断的那一刻,昨天刚刚发布的政策或财报,它不可能凭空知道。
- 细分领域弱:通识预训练语料往往很宽泛,面对企业内部的私有业务规范、冷门医学药理或精密工业参数,模型内部根本没有对应的深层记忆。
1.2 为什么只靠微调解决不了幻觉
有人可能会想:既然它记不住,那我用自己的领域数据对模型做微调(Fine-Tuning)不就行了吗?
在真实工程落地里,微调更多是用来教会模型“说话的风格、输出的格式或推理的步骤”,而不是用来给它灌输硬性事实。
用微调来更新事实知识,不仅训练成本极高、周期极长,而且极易引发模型的“灾难性遗忘”(Catastrophic Forgetting)——学会了新的产品手册,可能把原有的基础编程能力或者逻辑推理能力给搞坏了。想让模型说真话,最靠谱的做法不是强行篡改它的参数脑区,而是直接把证据摆到它面前。
二、RAG 是怎么把模型按在事实里的
RAG(Retrieval-Augmented Generation,检索增强生成)的核心思想,就是打破纯生成模型完全依赖参数记忆的死穴,把外部权威知识库与生成模型做深度结合。
它把原本要求模型“凭空背诵”的闭卷考试,变成了“带着资料抄答案”的开卷考试。具体到治幻觉上,主要靠两道防线。
2.1 事实锚定与边界约束
在 RAG 流程里,用户的提问不再直接扔给大模型,而是先走一套严密的检索链路。
第一道防线是检索召回与重排(Rerank)。系统会把外部知识库切分成几十到几百字不等的文本切块(Chunk),预先建立向量索引与倒排索引。当用户发起提问时,系统从知识库中召回语义最相近的切片,再通过交叉编码的 Rerank 模型计算精确相关度,挑选出最硬核的几条证据。
第二道防线是Prompt 强约束与拒答机制。很多大模型之所以出现幻觉,是因为它的指令对齐让它有一种强烈的“迎合倾向”——哪怕它心里没底,也拼命想凑出一个看起来像那么回事的答案。
在 RAG 的提示词模板里,必须给模型立下严格规矩。告诉它:你现在的唯一身份是一个严谨的资料分析员,你的回答必须完全基于后面给出的参考资料;如果参考资料里没有直接提到,请老老实实回答“根据现有参考资料无法回答”,绝对不允许凭空推测。
当证据链被摆在上下文里,且推测的退路被提示词堵死后,模型的自由联想空间被大幅压缩,幻觉自然就下来了。
2.2 在代码中实现防幻觉上下文装配
在实际开发中,我们可以利用 Spring AI 来清晰地实现这套检索与提示词防御装配。
环境基准:JDK 21 / Spring Boot 3.3.x / Spring AI 1.0.0-M1
下面这段代码展示了如何把检索到的文档片段安全地组装进系统提示词中,并带上防幻觉的拒答规则:
packagecom.crayontech.rag.service;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.document.Document;importorg.springframework.ai.vectorstore.SearchRequest;importorg.springframework.ai.vectorstore.VectorStore;importorg.springframework.stereotype.Service;importjava.util.List;importjava.util.stream.Collectors;@ServicepublicclassFactGroundedRagService{privatefinalVectorStorevectorStore;privatefinalChatClientchatClient;publicFactGroundedRagService(VectorStorevectorStore,ChatClient.BuilderchatClientBuilder){this.vectorStore=vectorStore;this.chatClient=chatClientBuilder.build();}publicStringgenerateFactBasedAnswer(StringuserQuery){// 1. 检索召回与过滤:获取 Top-4 且相似度高于 0.75 的真实切片SearchRequestsearchRequest=SearchRequest.builder().query(userQuery).topK(4).similarityThreshold(0.75).build();List<Document>matchedDocs=vectorStore.similaritySearch(searchRequest);// 如果检索不到任何支撑证据,直接触发系统级拒答,不浪费 Token,也不给大模型编造的机会if(matchedDocs.isEmpty()){return"根据内部知识库,未找到与该问题相关的权威材料,无法作答。";}// 2. 格式化拼接带来源锚点的上下文内容StringcontextContent=matchedDocs.stream().map(doc->String.format("[来源: %s] %s",doc.getMetadata().getOrDefault("source","知识库文档"),doc.getText())).collect(Collectors.joining("\n\n"));// 3. 构建强事实约束 Prompt:划定证据红线与拒答要求StringsystemPrompt=""" 你是一名严谨的技术支持助手。请严格根据下面提供的【参考证据】回答用户问题。 规则红线: 1. 答案必须严格源自【参考证据】,不得掺杂任何外部未经证实的推论。 2. 若【参考证据】不足以得出结论,请直接回复:'现有材料暂未覆盖该问题,无法作答'。 3. 回答中凡是引用的数据或结论,必须在句末标注对应的 [来源: xxx] 角标。 【参考证据】: %s """.formatted(contextContent);// 4. 调用大模型基于上下文完成证据整合输出returnchatClient.prompt().system(systemPrompt).user(userQuery).call().content();}}这段代码里有两个细节直接影响抗幻觉表现:
第一,在调用大模型之前先做相似度阈值检查。如果召回的分数很低,说明知识库里根本没有这件事,直接在代码层就拦截并返回,根本不让大模型接手。
第二,每个切片都打上元数据来源标记,并在提示词里强制要求模型在回答时标明角标,让最终生成的每一句话都具备可追溯性。
三、动态按需检索与幻觉检测
单次“检索一次 + 生成一次”的朴素 RAG(Naive RAG)能解决大部分简单问答,但在处理复杂业务时依然会有漏洞。现代 RAG 架构通常还会引入更深入的动态监测机制。
3.1 观察 Token 不确定性来触发二次检索
大模型在吐字(Generate Token)的时候,每个词都有一个置信度得分(即 Softmax 输出的概率值)。
如果模型输出一系列词时的置信度都接近 99%,说明它根据上下文答得非常笃定。但如果遇到某个专有名词或参数时,几个候选 Token 的概率非常分散(比如都在 15%~20% 上下徘徊),说明模型此时处于高度不确定的盲猜状态。
在一些前沿的主动检索机制(如 FLARE 框架)中,系统会实时监控生成 Token 的不确定性:
一旦发现模型在某句话上的置信度断崖式下跌,系统立即暂停生成,把这句话转换成检索关键词,从外部知识库拉取更详细的材料补充进去,然后再让模型继续回答。这种动态按需检索,把防幻觉的粒度从“单次问答”细化到了“句子甚至词语级”。
3.2 忠实度评估与输出守门
除了在生成前和生成中做约束,在生成后还可以挂载一道轻量级的自动化审查门禁,其中最常用的指标就是忠实度(Faithfulness)。
像 Ragas 这类专业的 RAG 评测框架,其核心逻辑就是校验答案对检索上下文的忠实程度:
- 提取原子事实:把大模型输出的一长段回答,拆解成若干句互不相干的简单陈述句(Atomic Claims)。
- 上下文求证:针对每一句陈述,逐字核对它是否能在检索出来的文档切片里找到因果或直接证据。
- 计算忠实度得分:如果在检索材料里完全找不到依据,说明这一句是大模型自己脑补出来的幻觉。当无支撑断言的比例超过安全水位时,系统判定答案存在幻觉风险,直接退回给模型重写或者给出降级回复。
四、RAG 会带来两类新问题
很多工程师刚接触 RAG 时容易走入另一个极端,以为把 RAG 搭好了就万事大吉,幻觉彻底清零了。
现实情况是:RAG 虽然压制了纯模型的自由编造,但它同时也引入了新的工程难题。如果处理不当,甚至会引发由检索本身导致的新幻觉。
4.1 切片断章取义引发的新幻觉
大模型本身没编造,但如果你喂给它的资料本身就是断裂的,它就会得出完全错误的结论。
假设你的企业知识库里有一份规范文档:
“在双十一等超高并发大促期间,为了保障核心结算链路,可以临时关闭积分抵扣服务;但是在日常平峰运行期,积分抵扣功能必须保持全天候开启,严禁擅自关停。”
如果你在做文本切块(Chunking)时,机械地按照 50 个字切一刀,刚好把前半句切进了Chunk_A,后半句切进了Chunk_B:
当运营人员在平峰期询问“现在可以关掉积分抵扣吗”,向量检索很可能只把包含“关闭积分抵扣服务”的Chunk_A送进了大模型的上下文。大模型严格遵守了提示词规矩,基于参考资料得出结论:“可以关闭。”
这在大模型评测里叫检索引入型幻觉(Retrieval-induced Hallucination)。大模型没有胡说,但它被残缺的上下文带进了沟里。
要解决这个问题,就不能依赖死板的固定字数切块,而应该采用父子文档检索(Parent-Document Retriever)或按自然段落与语义切分——检索时用细粒度的子切片匹配精准度,喂给大模型时替换为保留完整上下文的父文档段落。
4.2 检索延迟与系统复杂度的代价
引入 RAG 解决幻觉,在架构上付出的直接代价就是调用延迟的激增。
纯生成模型只需要一次网络往返就能开始流式输出;而一套完整的 RAG 链路,至少要经历:Query 改写 ➔ 向量 Embedding 计算 ➔ 向量数据库检索 ➔ Rerank 重排 ➔ Prompt 拼装 ➔ 模型生成。如果中间再加上前面提到的 Token 不确定性检查或动态二次检索,端到端的延迟很容易从原本的 500 毫秒飙升到 2 秒甚至更高。
在生产系统里,必须要配合语义缓存(对高频重复提问直接命中缓存结果)、向量索引量化(如 HNSW 结合 IVFPQ)以及异步并发召回等手段,才能在控制幻觉的同时把接口性能拉回可用范围。
写在最后
回到最开始的那个面试题:RAG 是怎么解决大模型幻觉的?
千万不要只轻描淡写地回答一句“外挂个知识库”。真正能打动面试官的回答,是讲清楚知识固化在参数里的局限,讲清楚从“检索召回、Rerank 提纯、提示词边界死守”的三层防御,再讲清主动检索与忠实度校验的进阶手段,最后客观指出切片断章取义可能带来的检索型幻觉与延迟代价。
当你把这一整套工程取舍与防御机制讲完整,对方就知道你不是背八股文,而是真的亲手在业务里踩过坑、调过优。
如果你觉得这篇文章帮你把 RAG 治幻觉的这套思路理顺了,记得点个关注!后续我还会继续拆解大模型实战与高频面试题里的硬核知识,我们下期见。