这篇文章来源于一个让我特别有感触的读者反馈。

他说他最近一个月把 RAG 的检索链路研究得很深——混合检索、Rerank 精排、Embedding 微调全都做了,召回率从 0.61 拉到了 0.87,他觉得系统差不多能交差了。结果上线内测第一天,业务方就截了个图过来:“你这系统搜到了正确的合同条款,但给的回答里多了一句话——这句话合同里根本没有。”

他当时以为是检索出了问题,查了日志发现不是——检索到的文档片段确实是对的,包含了用户需要的全部信息。但大模型在生成回答的时候,自己往里面"加了点料"。

👨‍💻后来他面阿里的时候,面试官恰好也问了这个:“你的 RAG 系统,检索到了正确的文档,但模型还是在胡说八道,你怎么解决的?”

🙋‍♂️他说在 Prompt 里加了一句"请根据资料回答"。

👨‍💻面试官追问:“加了这句话幻觉率降了多少?你量化过吗?”

🙋‍♂️他说没有。

👨‍💻面试官又问:“你知道 Lost in the Middle 问题吗?你给 LLM 塞了 10 段文档,它是不是真的每段都看了?”

🙋‍♂️他摇头。

👨‍💻面试官最后问:“你的回答有引用标注吗?用户怎么判断哪句话是文档里的,哪句话是模型编的?”

三个问题,全部哑火。

这件事让我意识到一个很多 RAG 开发者都有的认知偏差:大家把 90% 的精力花在了"怎么搜得更准"上,却忽略了"搜到之后怎么说得对"这个同样关键的环节。 检索只是把正确信息送到了模型面前,模型愿不愿意用、会不会用、有没有乱加东西——这是另一个战场。

今天把 RAG 生成阶段的幻觉压制、引用标注、上下文管理这些问题讲透。

简要回答

RAG 的幻觉问题跟普通大模型的幻觉不太一样。普通幻觉是"模型不知道还在编",RAG 的幻觉是"正确答案就摆在它面前了,它还是往里面掺假"。后者更隐蔽,也更危险——因为回答的大部分内容是对的,只有一两句是编的,用户很难发现。

压制这种幻觉要三层机制配合:

第一层是 Prompt 层面的硬约束 —— 不是简单写一句"请根据资料回答",而是要有具体的格式要求、Few-shot 示例引导、以及对"不知道就说不知道"的明确授权。

第二层是引用标注机制 —— 要求模型在回答时标注信息来源编号,这不仅是给用户看的,更是对模型的一种隐性约束:当它想编造信息时,找不到对应的来源编号,就会被迫收敛。

第三层是后处理检测 —— 在模型输出之后,用规则或者小模型检查回答中是否出现了检索文档中不存在的关键断言。

这三层缺一层,幻觉就很难压到可接受的水平。面试里只答"Prompt 里加了约束",在面试官看来等于什么都没做。

详细解析

为什么检索对了,模型还是会编

要理解这个现象,先要回到大模型生成文本的底层机制。

大模型生成回答的时候,本质上是在做概率预测——给定前面的所有 token,预测下一个最可能的 token。这个预测的依据有两个来源:一个是你通过 Prompt 传进去的上下文(包括检索到的文档),另一个是模型在预训练阶段已经"记住"的知识。

问题就出在第二个来源。当上下文里的信息跟模型的"记忆"有冲突时,模型不一定会以上下文为准。你告诉它"根据以下资料回答",但模型在生成过程中,某些 token 的概率分布可能更倾向于它预训练时学到的版本,而不是你塞给它的文档版本。

举个具体的场景。知识库里有一份 2024 年更新的员工手册,写着"年假天数为 15 天"。但模型在预训练数据里见过大量的"年假天数为 10 天"或"年假天数为 5 天"。你把 2024 年的手册片段检索出来塞进 Prompt,模型在生成"年假天数为"之后的那个 token 时,"15"这个数字的概率可能并不比"10"高多少——因为预训练的"先验知识"在拉扯它。

另一种更常见的情况是模型自行"补充"信息。文档里写了"该产品支持意外身故和全残保障",模型输出"该产品支持意外身故、全残保障和住院津贴"——“住院津贴"这四个字是模型自己加的,因为它"觉得"保险产品一般都会有住院津贴。这种基于预训练统计规律的"合理补充”,就是 RAG 幻觉最典型的形态。

在金融、医疗、法律这些领域,这种"看起来合理但没有依据"的补充,可能导致严重的合规问题。

第一层防线:Prompt 硬约束——别只写一句"请根据资料回答"

这是最基础的一层,但大部分人做得太粗糙。

“请根据提供的资料回答问题”——这句话你写了,模型也"看到"了,但它的约束力远没有你想象的那么强。原因很简单:这是一条抽象指令,模型对它的理解是模糊的。什么叫"根据资料"?是只能用资料里的原文,还是可以在资料的基础上做推理?如果资料里没提到的信息,是直接说"不知道",还是可以用自己的知识补充?这些边界都没有定义清楚。

一个在实际项目中效果明显更好的 Prompt 模板长这样:

你是一个专业的知识问答助手。请严格根据【参考资料】回答用户的问题。规则:1. 只使用参考资料中明确提到的信息来回答,不要添加资料中没有的内容。2. 如果参考资料中没有足够的信息来回答问题,请直接说"根据现有资料无法回答此问题"。3. 回答时请在相关信息后标注来源编号,如 [1]、[2]。【参考资料】[1] {文档A标题}:{文档A内容}[2] {文档B标题}:{文档B内容}[3] {文档C标题}:{文档C内容}用户问题:{query}

跟简单的"请根据资料回答"相比,这个模板做了三件关键的事。

第一,明确禁止添加额外信息。"不要添加资料中没有的内容"这句话看起来跟"根据资料回答"差不多,但它的约束力更强——因为它明确指出了模型不应该做的事情,而不只是指出应该做的事情。在 Prompt Engineering 里,禁止性指令通常比引导性指令更有效。

第二,授权模型说"不知道"。很多幻觉的根源是模型被逼着给答案。如果你不告诉它"可以说不知道",它在找不到答案的时候就会编一个。明确授权"回答不了就说回答不了",能显著降低模型的"创作欲望"。

第三,要求标注来源编号。这不仅是给用户看的,更是给模型自己的一个约束信号——后面会详细展开。

除了模板本身,Few-shot 示例的效果也非常好。在 Prompt 里放 1-2 个标准的问答示例——包括一个"能回答"的例子和一个"资料不足、坦诚说明"的例子——模型会模仿示例的回答模式,比单纯靠指令约束更可靠。

第二层防线:引用标注——给模型戴上紧箍咒

引用标注这个功能,很多人觉得它是"锦上添花"的用户体验优化——让用户知道回答的出处,增强信任感。但在我看来,它最大的价值不在用户侧,而在模型侧。

当你要求模型"在引用信息时标注来源编号 [1] [2]“,你实际上给模型设了一个隐性门槛:每一句涉及事实判断的话,都需要有一个来源编号来"背书”。当模型想编造一个信息的时候,它面临一个困境——编的这句话没有对应的来源编号可以标注。虽然模型不一定每次都会因此停下来,但这个机制确实在统计意义上降低了它"自由发挥"的概率。

我自己在项目里管这个叫"引用即约束"——它看上去是做给用户的功能,实际上是套在模型头上的紧箍咒。

工程实现分三步。

第一步:检索结果带编号入 Prompt。 每个检索到的文档片段用 [1]、[2]、[3] 编号标记,同时把文档的元信息(标题、页码等)一起记录下来,但元信息不放进 Prompt——只给模型看编号和内容,元信息留着后处理时用。

第二步:模型输出中解析引用编号。 模型的回答里会出现 [1]、[2] 这样的标记。用正则表达式提取这些编号。

第三步:编号映射回原始来源。 把提取出来的编号跟检索结果的元信息做匹配,最终展示给用户的是类似"[来源:员工手册 2024版 第15页]"这样的可点击链接。

import redef add_citations(model_output: str, source_map: dict) -> str:    """    将模型输出中的编号引用替换为可读的来源标注。    source_map 格式:{1: "员工手册2024版 第15页", 2: "理赔指南 第3章", ...}    """    def replace_ref(match):        ref_num = int(match.group(1))        source = source_map.get(ref_num, "未知来源")        return f"【来源:{source}】"        return re.sub(r'\[(\d+)\]', replace_ref, model_output)
第三层防线:后处理检测——模型说完了,你再查一遍

Prompt 约束和引用标注能降低幻觉概率,但不能杜绝。所以还需要一道"出厂质检"。

最简单的后处理检测方式是关键实体核验。从模型回答中提取所有关键实体(数字、日期、产品名、条款编号等),然后去检索到的原始文档中做精确匹配。如果回答里出现了一个原始文档里完全没有的数字或术语,就标记为"疑似幻觉"。

比如模型说"该产品的等待期为 90 天",你去原始文档里搜 “90” 这个数字,搜不到——文档里写的是"等待期为 30 天"。这就是一个可以被自动检测到的幻觉。

更精细的做法是训练一个专门的幻觉检测分类器。输入是(模型回答, 检索文档),输出是"忠实 / 不忠实"的二分类。用 NLI(自然语言推理)模型的思路来做——检索文档是前提(premise),模型回答是假设(hypothesis),判断假设是否能从前提中推导出来。如果不能,就标记为幻觉。

检测到幻觉之后怎么处理?有三种策略。保守策略是直接拦截,返回一个更安全的回答(比如"根据现有资料,该产品的等待期为 30 天",只输出文档中明确有的信息)。中间策略是在疑似幻觉的句子旁边加一个提示标记,告诉用户"此部分信息可能不准确,请以原始文档为准"。激进策略是重新生成——把检测结果作为反馈注入 Prompt,让模型重新回答,这次会更加保守。

在金融合规场景下,我建议用保守策略。宁可少说,不能说错。

还有一个容易被忽视的坑:Lost in the Middle

2023 年有一篇很经典的论文,标题就叫"Lost in the Middle",揭示了大模型在处理长上下文时的一个显著弱点:模型对上下文开头和结尾的信息关注度高,对中间部分的信息关注度低。

这对 RAG 的影响非常直接。如果你检索到了 10 段文档,按默认顺序塞进 Prompt,最相关的那段恰好排在中间位置(比如第 5 段),模型很可能"没看到"它,反而基于排在开头或结尾的次相关文档来回答。你明明检索对了,但因为排列位置的问题,模型等于没看到正确答案。

解决方案有两个。

第一个是控制数量。不要无脑塞 10 段 15 段文档,通过 Rerank 精排后只取 Top 3-5 段最相关的。文档越少,Lost in the Middle 的影响越小——3 段文档基本不存在这个问题。

第二个是优化排列顺序。把相关度最高的片段放在最前面(Rerank 分数最高的排第一),次相关的放在最后面,最不相关的放在中间。这样利用了模型对开头和结尾的高注意力,确保最重要的信息一定会被模型"看到"。

实际项目中,这两个策略通常配合使用。我们在内测中做过一个对比实验:同样的检索结果,只是调整了文档片段在 Prompt 里的排列顺序——把最相关的从中间移到开头——回答准确率直接提升了近 10 个百分点。代码上就是排个序的事情,几乎没有成本,但效果非常显著。

面试里怎么谈

这道题是 RAG 面试的高频题,而且它考的不是检索能力,而是你对生成阶段的工程把控。

第一个容易翻车的点:只说"Prompt 里加了约束"。 面试官一定会追问"加了什么约束",你如果只说"请根据资料回答"这种笼统的话,说明你没有深入思考过 Prompt 设计。要能讲出具体的策略——禁止性指令比引导性指令更有效、授权模型说"不知道"能降低编造概率、Few-shot 示例能引导回答模式。

第二个容易翻车的点:不知道 Lost in the Middle。 这是 RAG 生成阶段最经典的问题之一,2023 年论文发出来之后已经成了面试常考点。如果你做过 RAG 项目却不知道这个问题,面试官会质疑你有没有认真做过效果分析。

第三个容易翻车的点:没有量化过幻觉率。 面试官问"你的系统幻觉率是多少",你说"不太清楚"——这就暴露了你没有做过系统性的评测。幻觉率可以用 Faithfulness 指标来量化:准备一批标注过的问答对,让系统逐条回答,然后判断回答中是否有检索文档不支持的断言。哪怕你只做了 100 条的小规模测试,能说出"我们的幻觉率从 18% 降到了 7%",就比说"加了 Prompt 约束效果好了很多"有说服力得多。

一个比较完整的回答框架:先定义问题(RAG 幻觉 ≠ 普通幻觉,是"有正确资料还在编")→ 讲三层防线(Prompt 硬约束 + 引用标注 + 后处理检测)→ 讲 Lost in the Middle 问题和排序策略 → 给一个量化数据(Faithfulness 从 xx 提升到 xx)。如果面试官继续追问,你还可以展开聊"模型自检机制"——生成完答案后让模型再检查一遍自己的回答是否都有文档支撑,发现没有支撑的就自动修正。这个机制代价是多一轮 LLM 调用,通常只在高风险场景(金融合规、医疗问答)中开启。

写在最后

RAG 系统有两个战场:一个是检索,一个是生成。大部分人在检索战场上打得很卖力——混合检索、Rerank、Embedding 微调、分块策略优化,每一个环节都有人研究得很深。但到了生成战场,很多人就松懈了,觉得"检索搞好了,大模型自然能答对"。

事实不是这样的。大模型是一个概率模型,不是一个复读机。你把正确答案送到它面前,它在生成回答的时候依然会受到预训练知识的"拉扯",依然可能添油加醋、自由发挥。这种幻觉比检索不到正确文档更可怕——因为回答的 90% 是对的,只有 10% 是编的,用户很难察觉。

所以 RAG 的生成阶段不是"交给大模型就行了",它需要同样严肃的工程化处理:Prompt 设计要精细到每一条规则,引用标注要做到每一句话有出处,后处理检测要能抓住每一个可疑的实体,文档排列顺序要考虑模型的注意力分布特征。

这些东西不像检索优化那么有"技术感",但恰恰是决定 RAG 系统能不能真正上线、能不能让业务方放心用的关键一环。

2026年AI行业最大的机会,毫无疑问就在应用层

字节跳动已有7个团队全速布局Agent

大模型岗位暴增69%,年薪破百万!

腾讯、京东、百度开放招聘技术岗,80%与AI相关……

如今,超过60%的企业都在推进AI产品落地,而真正能交付项目的 大模型应用开发工程师 **,**却极度稀缺!

落地AI应用绝对不是写几个prompt,调几个API就能搞定的,企业真正需要的,是能搞定这三项核心能力的人:

✅RAG:融入外部信息,修正模型输出,给模型装靠谱大脑

✅Agent智能体:让AI自主干活,通过工具调用(Tools)环境交互,多步推理完成复杂任务。比如做智能客服等等……

✅微调:针对特定任务优化,让模型适配业务

目前,脉脉上有超过1000家企业发布大模型相关岗位,人工智能岗平均月薪7.8w!实习生日薪高达4000!远超其他行业收入水平!

技术的稀缺性,才是你「值钱」的关键!

具备AI能力的程序员,比传统开发高出不止一截!有的人早就转行AI方向,拿到百万年薪!👇🏻👇🏻

图片

AI浪潮,正在重构程序员的核心竞争力!现在入场,仍是最佳时机!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

⭐️从大模型微调到AI Agent智能体搭建

剖析AI技术的应用场景,用实战经验落地AI技术。从GPT到最火的开源模型,让你从容面对AI技术革新!

大模型微调

  • 掌握主流大模型(如DeepSeek、Qwen等)的微调技术,针对特定场景优化模型性能。

  • 学习如何利用领域数据(如制造、医药、金融等)进行模型定制,提升任务准确性和效率。

RAG应用开发

  • 深入理解检索增强生成(Retrieval-Augmented Generation, RAG)技术,构建高效的知识检索与生成系统。
  • 应用于垂类场景(如法律文档分析、医疗诊断辅助、金融报告生成等),实现精准信息提取与内容生成。

AI Agent智能体搭建

  • 学习如何设计和开发AI Agent,实现多任务协同、自主决策和复杂问题解决。
  • 构建垂类场景下的智能助手(如制造业中的设备故障诊断Agent、金融领域的投资分析Agent等)。

图片

如果你也有以下诉求:

快速链接产品/业务团队,参与前沿项目

构建技术壁垒,从竞争者中脱颖而出

避开35岁裁员危险期,顺利拿下高薪岗

迭代技术水平,延长未来20年的新职业发展!

……

那这节课你一定要来听!

因为,留给普通程序员的时间真的不多了!

立即扫码,即可免费预约

「AI技术原理 + 实战应用 + 职业发展

「大模型应用开发实战公开课」

👇👇

在这里插入图片描述

👍🏻还有靠谱的内推机会+直聘权益!!

完课后赠送:大模型应用案例集、AI商业落地白皮书

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐