RAG聊天机器人为何仍然幻觉?5个设计错误与修复方案

RAG幻觉多源于检索上游的分块、搜索与数据更新缺陷,而非模型本身。
RAG聊天机器人出现幻觉,问题往往不在生成模型,而在检索环节的上游设计。文章归纳了五类反复出现的错误:固定长度分块割裂语义、仅依赖向量搜索丢失精确匹配、索引数据过时且版本冲突、缺乏量化评估只能凭感觉调参、以及模型缺少说"我不知道"的退出机制。针对每类错误,文章给出了具体修复方案——按结构分块并附加标题元数据、用BM25与向量混合检索加重排序器、存储版本与更新时间元数据、建立30-50个真实问题的检索与生成分离测试集、通过提示词约束和检索分数阈值让模型拒绝回答。最后提供了一套四步调试顺序:先确认信息在索引中,再确认被检索到,再确认排名足够高,最后才怀疑模型。
你搭建了一个RAG聊天机器人。文档已索引,向量数据库运转正常,演示效果也不错。然后用户问起退款政策,机器人自信地引用了一条去年就已废止的规则。

RAG本应减少幻觉。确实如此,但前提是检索质量足够好。整个流程分两步:找到相关文本,然后基于它生成答案。如果检索到的文本本身错误、不完整或已过时,模型会毫不犹豫地在上面写出一段流畅而自信的回答。
多数项目中,问题不在模型本身,而在模型上游的设计。以下五个错误反复出现。
错误一:分块方式把语义拦腰截断
把每份文档切成固定的500个token片段很简单,但这样做会把表格切成两半,把步骤与其警告分离,把定义与它所定义的术语拆开。当一个文本块单独拿出来读不通时,基于它构建的答案也必然不通。
修复方案:
- 优先按结构切分:标题、段落、列表项
- 相邻文本块之间保留少量重叠
- 给每个文本块附上文档标题和章节标题
- 表格和步骤列表保持完整
一个快速验证方法:随机抽取20个文本块阅读。如果不看原文其余部分,你能理解每一个吗?如果不能,你的模型也不能。
错误二:仅依赖向量搜索
嵌入向量擅长语义匹配,却对精确匹配无能为力。产品编号、错误ID、版本号和名称经常被丢失。用户搜索“错误E4021”时,并不想要一些关于错误的模糊内容。
修复方案: 使用混合搜索。将关键词搜索(BM25或类似算法)与向量搜索结合,然后把前20到50个候选结果交给重排序器,由它选出最佳的3到5个送入提示词。一个好原则:宽检索,窄重排。
BM25是什么? BM25(Best Matching 25)是一种经典的稀疏检索算法,属于TF-IDF的改进版本。它根据词频、逆文档频率以及文档长度归一化来给文档打分,核心优势在于精确词匹配:当查询包含"E4021"或"RFC-7231"这类罕见但关键的token时,BM25能直接命中包含该字符串的文档,而向量模型往往会把它压缩成一个模糊的语义方向。
混合搜索为什么有效? 向量搜索和BM25是互补的:向量负责"意思相近",BM25负责"字面相同"。常见做法是分别执行两路检索,再用倒数排名融合(RRF)或加权分数合并候选集。
重排序器(Reranker) 通常是一个交叉编码器(cross-encoder),它把查询和每个候选文本块拼接后一起过模型,直接输出相关性分数。由于要为每个候选单独前向计算,速度远慢于向量检索,所以只在少量候选(20-50个)上使用。这就是"宽检索、窄重排"的由来:用便宜的召回换广度,用昂贵的重排换精度。
错误三:数据过时且相互冲突
文档会更新,索引通常不会。更糟的是,旧版和新版政策可能同时留在索引里,检索器根本不知道哪个是当前版本。
修复方案:
- 为每个文本块存储元数据:来源、版本和最后更新日期
- 文档变更时重新索引,或按固定周期重建索引
- 移除或过滤掉已被取代的版本
- 在答案中显示来源及其日期,让用户自行判断
错误四:没有评估,只凭感觉
“看起来能用”不是指标。没有度量,你无法判断新的分块大小到底是有帮助还是有损害。
修复方案: 构建一个小型测试集。从30到50个真实问题开始,每个问题附带正确答案和包含答案的文档。然后分别衡量两件事:
- 检索: 正确的文本块是否出现在靠前的结果中?
- 生成: 最终答案是否确实由检索到的文本支撑?
每次改动后重新运行测试集。这能让调参不再靠猜。
错误五:没有“我不知道”的能力
语言模型总是想帮忙。如果检索到的上下文不包含答案,许多模型会用看似合理的内容填补空白。这正是用户注意到的幻觉。
修复方案:
- 指示模型仅根据提供的上下文回答
- 当答案不存在时,给它一个明确的退出方式
- 要求每个论断都附带引用
- 设置检索分数阈值;低于阈值时,拒绝回答或提出澄清问题
- 记录被拒绝的问题,因为它们暴露了文档的空白之处
一个入门提示词:
仅使用以下上下文回答问题。如果上下文不包含答案,回复:“我在文档中找不到这个内容。”为每个论断引用来源标题。上下文:{retrieved_chunks} 问题:{question}
为什么模型不愿说"不知道"? 指令微调和基于人类反馈的强化学习(RLHF)会奖励"给出有用回答",久而久之模型对空白上下文产生了强烈的补全倾向。当上下文中确实没有答案时,模型不会把这当作"无法回答"的信号,而是把它当作一个生成任务,用语料中相似的措辞拼出一个看似合理的答案。
检索分数阈值的作用 是将"该不该回答"的判断从模型搬到检索层。向量检索通常返回余弦相似度或内积分数,可以为它设一个下限:低于下限说明没有文本块与问题足够接近,此时直接返回"未找到",不进入生成阶段。阈值需要用评估集调校——设得太高会拒答本可回答的问题,太低则形同虚设。记录被拒绝的问题还有额外价值:它们往往指向文档缺失或分块不当,是改进知识库的免费信号。
一个节省时间的调试顺序
当你看到错误答案时,按以下顺序排查:
- 正确信息是否在索引里?
- 它被检索到了吗?
- 它的排名是否足够高,进入了提示词?
- 模型实际使用它了吗?
大多数bug出现在前三步,远早于你需要归咎于模型的时候。
如需深入了解完整架构(数据摄入、嵌入、向量数据库和检索),可参阅ScaleDojo上的RAG与向量数据库指南,其中逐一讲解了每个组件。
这个排查顺序本质上是在做逐层归因:把端到端的失败拆解为索引、检索、排序、生成四个可独立验证的环节。
第1步"正确信息是否在索引里"排查的是数据摄取(ingestion)——文档解析、分块、嵌入是否把内容正确写入了向量库。可以绕过检索,直接在索引里做全文扫描来验证。
第2步"它被检索到了吗"把范围收窄到召回层。如果混合搜索的前50个候选里都没有正确的文本块,问题出在分块或嵌入模型上。
第3步"排名是否足够高"检查的是重排序和截断——正确文本块可能被检索到了,却排在第12位,而提示词只塞得下前5个。
第4步才轮到模型本身。如果前三步都通过,模型仍然给出错误答案,那才是提示词、上下文顺序或模型能力的问题。经验上,大多数bug都终结在第2步和第3步。
相关推荐

Workbuddy零基础入门:桌面AI智能体如何落地工作流
Workbuddy桌面AI智能体零基础教程解读:从安装、积分领取到文件管理与自动化工作流搭建,对比CodeX的适用场景与成本差异,帮助职场人完成从AI提问者到AI管理者的思维转变。

OpenAI智能体新栈:计算机操作、决策API与超速工作流
OpenAI Dev Day发布智能体新栈:Computer Use操作速度超越普通人,Decisions API基于Luna实现极低延迟分类,Agents API开放同源计算机操作能力,GPT-6.1 Sol成本仅为Astra七分之一。本文梳理核心更新、实测数据与开发者落地要点。

梁文峰开源推理框架DeepInfo,硬刚美国禁令
DeepSeek在开源模型后再开源推理框架DeepInfo,包含GPU/CPU交叉流水线、小模型预判大模型复核、华为昇腾与英伟达芯片全面适配等技术,直面美国联邦禁令。本文解析其对AI产业落地的意义与开源策略。