资讯动态

AI幻觉缓解实践:基于RAG的分层防御与落地路径

发布时间:2026/10/22 13:23:52 来源:尧图企业网站定制
1. 说在前面这个项目到底在解决什么这半年我一直在折腾一件事让一个基于大语言模型的AI原生应用面对真实业务问题时能老实回答知道的事并且坦率承认不知道的事。说白了就是跟幻觉死磕。先说背景。我们在给某团队做内部知识问答助手核心场景是客服问答和企业知识库检索。技术栈很直接——大语言模型加向量检索也就是大家常说的RAG路子。原型跑通很快两三天就能出Demo但真正往生产环境推的时候问题全冒出来了模型会一本正经地编造不存在的政策条款会把两个不同版本的规定混在一起说还会把文档里压根没写的口径当成事实输出。这类问题在传统软件里几乎没有对应物你有Bug就报错有异常就抛出但模型是自信地犯错而且每次犯错的姿势还不一样这让人非常头疼。这个项目就是围绕幻觉缓解展开的如何在不牺牲回答质量和响应速度的前提下把幻觉率压到一个可接受的范围。适合谁看如果你正在做大模型相关的应用开发尤其是知识库问答、智能客服、文档助手这类场景这篇文章应该能提供一条比较完整的落地路径。我不打算讲太多论文层面的理论更多是分享一套在真实业务里打磨过的组合方案以及那些文档里永远不会写的坑。2. 设计思路为什么不能指望单一技术2.1 幻觉从哪里来先得有个判断框架在动手设计缓解方案之前我花了很大精力把幻觉的来源做了一个分类。这个分类直接决定了后续的技术选型也是整个项目设计的基础。我把幻觉归纳成三类知识幻觉模型本身没有相关知识或者知识过时了但它又必须给出回答于是开始编。比如问一个2023年之后的内部新政策模型训练数据里根本没有它就会照着旧政策或者网上的相似内容脑补。关联幻觉知识库里其实有相关内容但模型没有正确引用而是把多个来源的信息强行拼凑在一起或者过度推断原文没有的结论。这类问题在RAG场景里特别常见因为检索结果是片段化的模型需要在有限上下文中做整合整合过程里就容易自由发挥。事实幻觉模型输出在语言上完全通顺、逻辑自洽但关键实体、数字、日期、名称是错的。比如把退款时效3个工作日说成7个工作日把产品名张冠李戴。这个分类框架的价值在于它告诉我们幻觉不是一个单一问题不存在一把万能钥匙。你需要一套分层防御体系每一层解决某一类问题。换句话说幻觉缓解是一个系统工程不是换一个模型、调一个参数就能搞定的。2.2 方案选型RAG、微调还是提示词约束项目启动时我们其实是按三个候选路线来对比的。微调这条路我们第一个否掉了。原因是业务知识更新频率高政策每个月都在变微调的周期以天甚至周计算根本追不上变化而且微调需要高质量的有监督数据构建成本非常高还有灾难性遗忘的风险。当然如果某个领域的知识基本稳定、专有名词极多微调是值得考虑的但对我们的场景不合适。纯提示词约束的路子我们也验证过。在系统提示词里写请严格基于给定的资料回答不要编造或者用few-shot给几个例子。实测下来这类约束在简单场景有效但对复杂问题的帮助很有限——模型不是不知道规则是做不到尤其在上下文较长、信息冲突较多的时候。它更像一种锦上添花而不是雪中送炭。最终我们选择的是以RAG为主干叠加一套输出侧校验与拦截机制的组合方案。RAG解决的是知识从哪来的问题它把外部知识实时注入上下文降低知识幻觉和过时知识的发生概率输出校验解决的是回答是否可信的问题它在生成之后做一轮交叉检查把仍然可能出错的答案拦截下来。2.3 整体架构长什么样整个系统分五层每一层的职责非常单一输入层受理用户问题做意图识别、敏感词过滤、问题改写。检索层把问题向量化在知识库中做相似度检索同时支持关键词检索作为兜底。生成层拼装上下文调用大语言模型生成回答。校验层对生成结果做事实一致性检查、引用来源核对、置信度评估。反馈层高置信度回答直接返回低置信度回答降级为抱歉我无法确认这个问题或者引导用户换一种问法。这套架构不复杂但每层都有对应的降级策略。我最想强调的一点是不要把所有的信心都押在大模型身上系统设计上要为模型犯错留出后路。这也是AI原生应用和传统软件的最大区别——传统软件假设组件是可靠的而AI应用必须假设模型是会出错的然后围绕这一点做防御。3. 核心实现幻觉缓解管线的每一个细节3.1 知识库的准备切分和清洗比选向量模型更重要很多人做RAG第一步就扎进了向量模型选型里然后发现效果上不去到处找原因。根据我的经验知识库的清洗和切分策略对最终效果的影响往往比向量模型本身更大。先说说清洗。我们知识库里有一部分是历史工单、客服对话记录质量参差不齐有的语句不通有的信息已过期。我的做法是先做一轮人工规则清洗把明显过期、互相矛盾、包含敏感信息的文档标记出来再让大模型辅助抽取关键信息生成结构化摘要比如每个文档涉及的主题、适用的时间范围、约束条件。这样做的目的是让知识库本身尽量干净不然上游脏数据进来下游检索再准也是白搭。切分策略方面我踩过不少坑。最开始直接按固定字符数切比如每块512个字符结果是大量上下文被截断一个完整的政策条款被拆成两半检索命中了一半回答自然就残缺不全。后来改成按语义边界切分——优先在标题、段落、列表项这些自然边界处断开同时设置重叠区域比如相邻两个块之间保留50到100个字符的重叠避免关键信息恰好落在切缝里。还一个重要细节每一个切分块在入库时我会额外保存它的原始文档ID、标题层级路径、段落序号。这些元数据不是为了检索而是为了后面的引用溯源——当模型说根据《退款政策》第3条的时候我们能够反查它是基于哪一块内容得出的结论。3.2 检索增强多路召回比单路检索更抗揍生成质量的上限很大程度上由检索质量决定。我实测下来的结论是不要把鸡蛋放在一个篮子里要做多路召回。第一路是向量检索也就是把用户问题embedding化在向量库里找语义相似的块。这里有个参数值得说一说top-k。很多教程默认让top-k等于5或10但实际要看你知识库的粒度。我们实验下来单轮检索取8到12个块比较合适太少了漏召回太多了噪声上升模型的注意力会被无关信息干扰。第二路是关键词检索用BM25这类稀疏检索方法。向量检索擅长语义匹配但对专有名词、编号、缩写这类精确匹配场景非常弱。比如用户问TE-2019号规定如果向量检索没命中BM25能通过精确词法匹配把它捞回来。这两路召回结果做融合按归一化得分加权排序最终取前N个块进入上下文。第三路是元数据过滤。知识库里的文档可能按部门、文档类型、发布时间做过分组如果用户问题能识别出明确的限定条件比如售后部门的退款流程就先把检索范围缩小到对应分组再去做前两路召回。这能显著减少无关内容的干扰。检索做完之后还有一个容易被忽略的环节重排序。原始的相似度得分和最终相关性之间的相关性其实很弱尤其当检索结果来自不同的文档、不同粒度的段落时。我们引入了一个独立的重排序模型对召回结果做一次精排再截取最高分的若干块进入提示词。这个环节对最终回答质量的提升非常可观我强烈建议不要省。3.3 生成阶段的约束提示词、参数和引用要求检索结果准备好之后生成阶段的核心任务是把上下文用明白。我用的提示词模板大致是这样你是某公司的知识助手只能依据下方提供的参考资料回答用户问题。 要求 1. 如果参考资料中没有直接依据明确回答资料中未找到相关信息不要推测。 2. 回答必须标明每一条关键信息的来源编号格式为[引用编号]。 3. 如果参考资料之间存在矛盾指出矛盾点并说明不同资料的表述差异。 4. 不要输出参考资料之外的额外结论不要重复用户问题。 参考资料 [1] {内容块1} [2] {内容块2} ... 用户问题{question}这个模板里我做了三个关键设计。第一显式给了不知道的出口模型在训练中已经形成了不知道时必须给回答的倾向你需要用明确的指令抵消这种倾向。第二要求标注引用编号这为后面的校验层提供了锚点模型如果标了一个不存在的编号或者引用的内容与回答不符校验层就能拦下来。第三冲突信息不只禁止而是要求指出冲突因为很多业务场景里不同时间、不同部门的文档存在差异是正常的回答应该呈现这种差异而不是强行统一。参数方面temperature我们设在0.1到0.3之间越低越好。有人觉得temperature低会降低回答的多样性让模型变得死板但对知识问答场景来说稳定性和确定性优先级远高于发散性。我们还关闭了类似润色的后处理让模型尽量贴着参考资料的语言风格走。另外一个容易被忽视的参数是max_tokens。有些模型输出过长反而容易失控因为生成得越长后续token对前文信息的依赖越容易被稀释幻觉累积的风险越高。我们限制回答在300字以内配合提示词里简洁作答的要求实测效果不错。3.4 输出侧校验最后一道闸门生成层的约束做得再好也不能100%保证模型不胡说。所以我们在输出侧加了一个校验层这才是整个系统里最有工程含量的一部分。校验层做了三件事。第一件事是引用一致性检查。我们拿模型输出的引用编号去对应的参考内容块里做一次相似度比对模型声称来源是[3]的内容实际上[3]里面到底有没有这句话如果相似度很低说明模型很可能在编造或者过度引申。这个检查我们用语义向量来做同时加上一个规则兜底——关键数字、专有名词如果出现在回答里必须能在对应的参考块里找到同词或近义词。第二件事是答案与问题的相关性检查。经常出现的情况是模型生成的回答内容本身没问题但不是用户问的那个问题。比如用户问退货流程是什么模型回答了一堆退货条件。这类偏差需要用一次额外的判断把问题和回答同时给一个便宜的小模型让它判断回答是否切题。这里注意不要用同一个模型来做校验因为你希望校验者是一个不同的视角如果主模型和校验模型是同一个错误倾向很可能是一致的。第三件事是置信度评估。我们并不是简单地把回答分为对和错而是输出一个综合置信度分数。这个分数由引用覆盖率、一致性相似度、回答长度、模型自身对答案的logprob等多个信号加权得到。落库的时候分数越低越倾向于走降级路径要么回复我暂时无法确认这个问题请咨询人工客服要么附带明显的免责说明。这个降级机制非常重要因为它给了系统一个体面的认怂方式而不是硬着头皮给用户一个看似权威实则错误的结果。4. 踩坑记录实测过程中遇到的典型问题4.1 命中了正确文档模型还是答错这是最让人抓狂的一类问题。检索明明返回了正确的内容块向量相似度也足够高但模型就是答错——要么概括错了要么漏掉了关键限定条件。排查之后发现原因有两类。第一类是上下文顺序问题。进入提示词的参考块是有先后顺序的模型对前面的内容注意力更强如果关键答案在第8块之后模型经常看漏。我们的处理方式是把重排序之后得分最高的块放在最前面同时尽量压缩参考块总数量把每块的长度控制在合理范围。第二类是参考块之间信息互相干扰。比如两个不同版本的退款政策同时进入上下文模型不知道该以哪个为准于是自己编了一个折中方案——实际上哪个版本都不对。处理方法就是我在提示词模板里写的明确要求模型如果存在矛盾请指出矛盾而不是调和同时尽量通过元数据把不同版本的文档分开检索。4.2 检索质量差答非所问检索不到正确内容生成再好也白搭。我遇到的最典型问题是用户的问题很短、很口语化比如为什么我的券用不了向量表征很难捕捉到背后真正想查的优惠券使用规则。我们的解决方案是加一层问题改写模块先用一个小模型把用户口语问题改写成适合检索的标准查询补全省略的实体和业务词比如改写成优惠券无法使用的条件有哪些。这个改写模块本身不直接生成回答它的任务非常聚焦出错率低了很多。还有一招是query扩展把改写后的主问题加上同义词和上下游相关词拆成几个检索子查询分别去检索再把结果合并去重。这能有效应对口语表述和文档书面语之间的gap。4.3 自检层误伤太多正常回答校验层上线之后我们发现误拦截率不低——很多明明正确的回答被打上了低置信度标签导致用户体验直线下降。逐条排查后发现问题出在引用一致性检查的算法上我们把回答里的关键实体逐词拿到参考块里比对但如果回答用的是同义改写比如参考块写退还回答写退回规则就直接判不匹配。后来我把检查策略从词级匹配改成了语义级匹配用向量相似度加阈值判断同时把比较粒度从整句调整为关键论元主体、动作、对象、数量。再配合一个白名单机制如果参考块本身很短、信息密度很高且回答和参考块的语义相似度超过阈值就跳过细粒度的实体比对。改了之后误伤率直接下降了一半还多同时真正的问题回答仍然能被拦下来。4.4 延迟和成本能不能扛住整套方案跑下来最大的工程压力不是算法而是延迟。一条用户请求要经过问题改写、多路召回、重排序、生成、三层校验最慢的时候整条链路要8秒。对客服场景来说这不可接受。我们做了三个优化。第一是缓存同一问题在24小时内的检索结果直接缓存不重复做向量搜索高频问题的完整回答也做了缓存命中率接近30%。第二是并行化问题改写、多路召回之间没有强依赖改成并行执行整体时间省了将近一半。第三是小模型分流校验层的相关性检查原本用完整的大模型来做成本高速度慢后来换成了一个小参数模型性能基本持平延迟从1.2秒降到0.3秒成本降了一个数量级。最终整套链路稳定在2到3秒业务上可以接受。5. 评测与观测如何证明幻觉真的变少了5.1 评测指标不要只盯着准确率幻觉缓解做得好不好不能靠感觉必须有可量化的指标。我们上线前和上线后都跑了一套固定的评测集指标分成三个维度忠实度回答中的每一个关键论断是否都能在给定的参考文档中找到依据。这是幻觉缓解的核心指标我们按句为单位标注完全有依据部分有依据无依据然后计算有依据句子占比。答案相关性回答是否直接回应了用户问题有没有跑题。比如用户问A问题模型回答了一段B问题的内容即使内容正确也算低相关性。引用质量引用的参考块编号是否真实存在引用的内容是否与对应论断一致。这三个指标各有侧重单看哪一个都不够。我见过不少团队只盯着准确率结果模型非常准确遇到不会的问题也硬答——准确率看起来不低但对用户来说毫无价值因为它没有区分答对了和答错了但看似权威。评测幻觉缓解必须把不知道就承认不知道的行为也作为加分项。5.2 评测集的构建艰难但必须做构建评测集是这个项目里最磨人的工作。我们从三个渠道收集测试问题一是线上真实用户日志里抽样二是业务方提供的经典问题清单三是我们对知识库自行生成的边界测试问题。每一条测试数据都要人工标注参考答案和期望行为工作量很大但这个是值得的——没有评测集就没有迭代方向。我特别想强调边界测试问题的价值。我们设计了几类刁钻问题与知识库完全无关的问题、知识库内容互相矛盾的问题、问题包含多个子问题的组合题、只给了一部分信息的半截问题。这些边界问题最能暴露幻觉问题因为正常问题模型处理得很好恰恰是那些不该答的问题才考验系统的定力。比如公司有没有规定外星人加班补贴知识库肯定没有但模型在早期会编造一条看似合理的政策出来。评测集里一定要塞够这类题它直接影响你对系统的信心。5.3 上线后的持续观测评测集是一锤子买卖上线之后还要做持续观测。我们的做法是给每一次回答都打上完整的追踪标记包括检索命中的内容块、引用编号、校验层的各项得分、置信度分数。这些数据全部落日志然后做两项分析。一项是主动发现新幻觉案例。每天从低置信度回答里抽样人工复查把真正的问题回填到评测集里。这样评测集是活的能跟着业务演进。另一项是做趋势看板按天统计置信度分布、降级率、引用覆盖率一旦某个指标出现异常波动比如降级率突然升高往往意味着知识库更新出问题了或者上游文档质量下降了。这套观测体系上线之后我们对系统的信心明显增强了。因为每一次迭代都可以用数据说话这周版本比上周版本的忠实度提高了多少、误伤率降了多少而不是靠感觉好像更准了来驱动决策。6. 最后说点实际操作中的体会整套方案做下来我最深的感受是幻觉缓解没有终点只有持续的攻防。你堵住了知识幻觉关联幻觉又冒出来你修好了引用检查发现模型开始过度引用——明明没有实际参考硬是标一个编号糊弄过去。所以心态上一定要接受不完美目标不是零幻觉而是把幻觉率压低到业务可接受的范围内并且让系统在犯错的时候有一个体面的出口。另外一个很实际的心得是不要一开始就把方案设计得过于复杂。我们早期堆了一大堆模块结果问题定位非常困难根本说不清是哪个环节导致了回答质量下降。后来重构为最小可用的RAG一层校验先把基线跑通再逐步加模块每一步都通过评测集验证有没有正向收益。这样整个系统的行为是可控的出了问题也能快速定位。最后分享一个小技巧也是我们后期用得最多的一个手段在知识库更新的时候强制对大模型做一轮新知识检查。把新增或变更的文档内容拿出来问模型几个预先设计好的问题看它是否能在回答中正确反映新内容、并且不再提及旧版本的说法。这相当于给系统定期做体检能提前发现知识库变更带来的幻觉回归。这个习惯我们一直保持到现在每次更新知识库之后的第一周评测集上的忠实度指标都会明显波动及时修正比事后补救省事太多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑