RAG与Agent闭环:从幻觉根源到生产级问答系统实战

📅 发布时间:2026/10/20 19:29:25
RAG与Agent闭环:从幻觉根源到生产级问答系统实战
做生成式AI应用这一年多我被问得最多的一句话是“大模型又在编了怎么办”这里的“编”就是业内说的幻觉也就是模型一本正经地说出没有依据的内容语气越自信越危险。市面上最常见的解法是RAG全称检索增强生成思路是先捞回相关资料再让模型对着资料回答。另一条更热闹的路线是Agent让模型自己决定查什么、怎么查、答完要不要改。单说我的结论单独的RAG解决不了幻觉单独的Agent反而会放大幻觉真正值得投入的是把两者揉成一套闭环——先判断意图再规划检索然后生成答案最后做事实核查错了就带着反馈回头重来。这篇文章适合正在做客服问答、知识库助理、文档分析工具的人看。如果你已经被“回答得很流畅但内容全错”折磨过那下面这套思路值得你花十分钟看完。我不打算吹“终极方案”这个词工程上不存在那种东西我只讲怎么把RAG和Agent一步一步放进生产环境里以及过程中那些文档里不会写的坑。1. 幻觉的根子在模型结构RAG只是在打补丁1.1 为什么大模型天生就爱“编”大语言模型本质上是一个概率模型它在生成每一个词的时候核心参考不是“这件事在现实世界是否成立”而是“这句话在人类语言统计里是否自然”。训练目标里本来就没有“正确性”这个维度所以幻觉不是bug而是模型架构与生俱来的特性。用一个生活场景来类比你身边有一位模仿能力极强、但记忆力很差的同事。你问他某件事他能说得头头是道但其中一半是根据上下文现推的他自己都分不清哪些是真话。大模型就是这位同事的超级强化版它在海量文本上学会了“像人话”的表达模式却没学会“符合事实”的验证能力。这个特性跟模型参数大小有关系吗有但并不是越大越安全。更大的模型在更多数据上训练的表达更流畅事实一致性表面上更好于是幻觉反而更隐蔽——它能把一个不存在的细节填得极其自然让谎话听起来比真话还真。做工程的人必须先接受一个前提幻觉无法被彻底消灭只能被约束、被发现、被纠正。谁要是告诉你某个方案能100%消除幻觉你基本可以判定他没做过生产环境。1.2 RAG干的事把回答变成开卷考试RAG的思路非常直白。先从知识库里检索出与问题最相关的片段把片段拼进提示词再让模型基于这些片段生成回答。表面上看这一步把模型从“闭卷考试”变成了“开卷考试”答案范围被限制在已检索到的文档里幻觉出现的概率自然下降。但请留意RAG只解决了“有资料可依”的问题并没有解决“模型是否真的照着资料答”的问题。模型完全可能在参考资料正确的情况下为了语气自然加入一些原文没有的细节。更常见的是参考资料本身过时、错误、或者压根不相关模型照样会把它们圆融地融进回答里。很多团队在接上RAG之后幻觉率只是从20%降到10%并没有消失就是这个原因——检索框住了范围但生成阶段仍然失控。1.3 静态RAG的死穴没有反省能力传统RAG的流程是固定的收到问题向量检索拼接上下文生成回答结束。整条链路只有一个方向没有任何反馈入口。系统不知道自己的答案是否被资料支持也不知道刚才检索到的资料质量如何。这个“一条道走到黑”的设计决定了它的效果上限是由检索质量决定的。检索器给的是垃圾生成器就会把垃圾包装得像模像样。要突破这个上限必须在生成之后再加一层检查与纠错环节而这恰恰是Agent模式的强项。于是很自然地想到能不能让模型自己发现问题、自己重新检索这就是RAG和Agent结合的起点。2. 单靠Agent为什么也不行会跑不等于跑得稳2.1 Agent的优势同时也是风险源Agent的核心理念是把任务交给模型自主规划拆解目标、选择工具、执行动作、观察结果循环直到任务完成。把Agent引入RAG场景意味着模型可以自己决定要查几个子问题、要不要二次检索、甚至自己判断哪些证据已经足够。听起来很好但如果你直接把“查询知识库”当成Agent众多工具之一丢给它问题会更麻烦。Agent每多一次自由决策就多一次发散机会。规划阶段可能把一个简单问题拆成三个子问题然后检索出三堆不相关的内容生成阶段又为了把多轮信息拼成完整答案脑补缺失的逻辑链条。结果流程变长了幻觉没减少反而新增了“中间过程幻觉”——你甚至不知道幻觉发生在规划、检索还是生成环节。2.2 没有验证能力的Agent就是脱缰的野马我见过不少团队做“Agent问答”最典型的现象是模型宁可相信自己的“常识”也不相信刚检索回来的证据。原因在于生成模型的注意力很容易被自身参数里的预训练知识吸引上下文里的证据反而成了弱信号。如果没有外部机制强制它对证据、查逻辑Agent就会在错误的推理方向上越走越远。这里有一个容易被忽略的工程细节当你让大模型扮演“规划者”的时候它的每一步决策本身也是个概率生成过程同样会产生“规划幻觉”。比如它认为需要查A、B、C三个问题实际上A根本不重要B和C之间也没有因果关系。所以Agent每一步输出都需要被“观察到的结果”校正。这就是为什么整套方案里必须有一个验证器来形成闭环而不是让Agent在真空中自由发挥。2.3 组合的关键控制循环而不是放任自主把RAG和Agent结合不是简单地把检索函数挂在Agent的工具箱里而是要把整个问答过程设计成一个受控循环。循环里既要有Agent的自主性——负责判断、拆解、规划也要有强制的约束——每一步都缩小候选范围每一步都留下证据最后一步必须做事实核查。我自己的经验是RAG负责“圈地”Agent负责“在地里干活”验证器负责“检查收成”。三者缺一个方案都会塌。只做RAG就是地圈好了但没人管草长什么样全看运气只做Agent就是地没圈人越跑越远只有闭环跑起来每一步都能被检查和纠正效果才真正稳定。3. 把RAG塞进Agent循环四个关键机制拆解3.1 检索路由不是所有问题都需要开卷一个真实的知识库问答系统每天接收的请求里有相当一部分是闲聊、计算、或常识问题它们根本不需要走检索。强制检索反而会让模型把答案建立在无关文档上制造幻觉。所以Agent循环的第一步应该是判断这个问题需不需要外部知识如果需要需要的是哪种外部知识这一步就是检索路由。以我常用的设计为例路由层会输出四类意图需要文档检索的knowledge类、需要查询结构化数据的database类、不需要检索直接回答的direct类以及不适合处理的refuse类。做了路由之后最明显的变化是延迟降低、答案更稳因为模型不再被迫拿无关资料“凑答案”。顺带省下的token费用也很可观尤其在高并发场景下。3.2 查询重写与子问题分解把模糊问题变清晰用户问“它对上一季度营收有什么影响”系统如果直接拿整句话去向量检索效果通常很差。原因有两层一是代词“它”需要结合对话历史才能确定二是“对营收的影响”属于关系型问题在碎片化文档片段里很难直接命中。Agent在这里需要做两件事。先做指代消解把问题补全成完整表述比如“它对上一季度营收有什么影响”改写成“A公司在2024年第四季度推出产品X后对公司上一季度营收有什么影响”。再判断是否需要拆成多个子问题。比如“这个产品2023年的销量和2022年相比发生了什么变化”应该被拆成“查询2023年销量”和“查询2022年销量”最后再由归纳环节来做比较。子问题拆得越清晰检索命中率越高回答越有据可循。实际操作时我建议用明确的Prompt让模型输出JSON数组格式的子问题列表方便程序逐条执行。3.3 证据采集与精炼多源检索去重压缩子问题确定之后Agent开始调用检索工具取证据。这一步有些团队会做成“一个子问题配一次向量检索”但更稳妥的做法是同时发起多个来源的检索——向量库、关键词索引、结构化数据接口各查一遍然后对结果做去重和重排。为什么这么麻烦因为向量检索擅长语义模糊匹配但在查代码、查编号、查人名时关键词精确匹配往往更可靠。两类检索天然互补。拿回一堆文档片段后不要急着全塞给生成器。上下文窗口有限片段越多噪音越大模型反而找不到重点。这时候要做“证据压缩”按子问题相关度排序保留Top K然后让一个小模型把每段压缩成两三条核心事实。经过这一步送给生成器的证据才是干净的而不是一堆原始文档的堆砌。3.4 生成后验证从信任模型到信任证据生成器给出回答之后验证器登场。它是整个闭环的灵魂把“问题回答证据片段”三样东西同时交给一个语言模型让它逐条判断回答里的关键陈述是否被证据支持。输出通常分三类支持、不支持、证据不足。如果结论是“不支持”说明生成器跑偏了需要带着“上次为什么不被支持”的反馈重新进入检索环节换个角度找证据。如果结论是“证据不足”可能证据本身不完整需要触发补充检索。如果结论是“支持”才放行给用户。这一环看似简单但能把幻觉率再砍掉一大半。它把原本不可观测的“模型在编”拆成了两个可以观测的状态到底是检索失败还是生成失败。这个区分在排查问题时价值极大。4. 落地实战一套可复现的RAGAgent问答流程4.1 模块与调用关系先把整体架构用文字描述出来。我习惯把系统分成五个模块路由模块负责意图判断规划模块负责生成子问题检索模块负责执行向量检索和数据库查询生成模块负责产出答案验证模块负责检查答案与证据的一致性。调用顺序是路由 - 规划 - 检索 - 生成 - 验证。验证失败时携带反馈回到规划或检索环节形成一个最多执行N轮的循环。N一般取2到3防止死循环。整个系统不是一个“智能体”在自由发挥而是一个带反馈回路的流水线。每一步的输入输出都是结构化数据方便记录日志、做效果评估。4.2 路由与规划的Prompt模板路由环节的Prompt我会写成这样核心是约束输出格式你是一个检索路由员。用户的问题是{question} 请判断需要哪一种处理方式只输出一个选项 - knowledge: 需要从知识库检索 - database: 需要查询结构化数据 - direct: 直接回答即可不要检索 - refuse: 内容不适合处理 如果选择knowledge请先补全问题中的指代输出完整的检索问题。 如果选择database请提取出需要查询的字段和过滤条件。规划环节的Prompt侧重点是子问题分解你是问答规划员。针对用户目标{question}请给出需要独立检索的子问题列表。 要求 1. 每个子问题都是单一事实性问题能被一段资料直接回答。 2. 不包含模糊代词。 3. 输出JSON数组不要解释。 示例输出[A公司2023年第三季度营收是多少, B产品在2024年的市场份额是多少]这里有一个经验路由Prompt里的选项名称最好和代码里的枚举值保持一致。否则模型输出了一个“knowledge”代码里却定义成“doc”解析时就会出低级错误。别问我怎么知道的。4.3 Agent循环的核心伪代码下面这段伪代码展示了整个闭环的控制逻辑。它不算复杂但直接把“反馈”这个关键动作落到代码里def ask(question): intent route(question) if intent direct: return generate(question) if intent refuse: return 抱歉我无法处理这个问题。 feedback for round in range(MAX_ROUNDS): sub_questions plan(question, feedback) # 如果上一轮验证失败feedback里会带着失败原因 # 规划器就能在下一轮改写查询方向。 evidences [] for sq in sub_questions: raw retrieve(sq, top_k20) reranked rerank(sq, raw)[:5] compressed compress(reranked) evidences.append(compressed) answer generate(question, evidences) verdict verify(question, answer, evidences) if verdict.is_supported(): return answer feedback verdict.feedback() return answer # 达到最大轮数后可以返回低置信度提示解释一下其中的关键feedback是闭环的核心。它把验证器的结论转化成人话例如“回答中提到2023年营收为3.2亿但证据中只找到2022年的数据”然后作为下一次规划器的输入。这样规划器不是盲目重试而是根据失败原因调整检索方向。这个设计直接决定系统能不能从错误中学习。4.4 验证器的三种返回状态怎么用验证器的返回需要结构化程序才能做判断。我一般约定返回一个JSON对象同时包含事实级别和整体结论{ facts: [2023年营收3.2亿, 同比增长12%], verdicts: [support, unsupported], reason: 未找到2023年营收的原始证据只有2022年的数据, overall: unsupported }程序拿到这个结果后决策逻辑简单直接verdicts里出现“unsupported”就触发重试出现“insufficient”就补检索全部是“support”才输出。overall字段给监控系统看用于统计系统整体的忠实度。这里有个容易被忽视的坑验证器如果太严格会把“意思一致但表述不同”的句子判成不支持导致大量无意义重试。比如证据里写“营收下降12%”回答里写“营收减少一成二”验证器可能因为数字对不上判失败。所以验证Prompt里我会明确强调只要关键含义能从证据中推断出来就算支持不要求逐字一致。把验证粒度放在“关键数字、实体、结论”上而不是整句话。5. 组件选型与参数调优让方案从能跑到好用5.1 向量检索的核心参数向量检索里影响最大的参数是分块大小和重叠长度。我实测过的常见范围是256到512字符之间重叠50到100字。块太小语义不完整遇到宏观问题答不出块太大噪音多命中精度差。按文档类型还需要再细分技术文档用256字符加64重叠适合问答密集的场景制度类长文用384字符加96重叠因为里面很多内容需要上下文才能理解。这些数字没有绝对最优但可以作为起点再用评测集做小范围搜索调优。调参时盯着“检索命中率”而不只是最终答案质量因为命中率更直接反映参数变化的影响。5.2 有了向量检索为什么还要重排序向量检索本质上是模糊匹配Top结果里通常混着几个看似相似、实则跑题的片段。重排序模型会逐对计算问题和片段的相关性把真正相关的排到前面。在RAGAgent架构里重排尤其关键因为Agent后续还有验证阶段如果第一轮证据就是偏的后面的反馈再丰富也是在错误方向上打转。我一般安排向量检索先取Top 20重排后只取Top 5。重排多花几十毫秒但对最终效果的提升非常明显。如果系统里还没有重排层这是我最优先建议补上的组件优先级甚至高于加一个复杂的Agent规划器。5.3 分层调用小模型做大决策大模型做最终生成Agent循环里的每个环节都在消耗token。如果所有步骤都调用同一个高性能大模型一次问答的成本会高到没法上线。我推荐分层策略路由和证据压缩用开源小模型或规则规划和验证用中等规格的模型只有最终生成时才用性能最好的大模型。实测下来路由准确率并不输大模型但成本少了接近一个数量级。规划器对语义理解要求高一些但也不需要顶配验证器对逻辑判断要求最高但它接收的是结构化证据中等模型配合明确的Prompt也能胜任。这套分层方案在并发量上来之后效果差异会非常明显。5.4 上下文管理与证据控制的细节点上下文管理有几个细节点容易出问题。第一限制检索片段的总长度。我一般限制在3000字符以内超出的部分用摘要替代绝不放原始文档全文。第二给证据加来源标记让验证器看到“这条证据来自哪份文档”方便处理多文档冲突。第三记录每个答案的证据快照生成时就存下证据ID和原文片段出问题时能迅速回溯。这最后一条算运维侧的经验但做生产系统必须提前考虑否则事后想查“这条答案当时依据的是什么”根本无从下手。6. 运行中踩过的坑与排查速查6.1 路由误判把闲聊问题送进知识库现象用户说“今天天气不错”系统依然触发检索然后回答了一堆知识库里的内容看着莫名违和。排查翻路由日志发现意图分类模型被“天气”一词误导直接把问题划到了knowledge类。解决在路由Prompt里增加负面示例明确写出“当问题不涉及业务知识时不能触发检索”同时给direct类加一个置信度门槛只有超过阈值才允许走检索。这样闲聊问题会被挡在检索链路之外。6.2 验证器误杀好好的答案被反复重试现象答案本身正确但验证器因为某个数字的表述差异判成不支持导致Agent反复跑第二轮用户明显觉得响应变慢。排查把验证器输出和原证据放在一起看发现它要求数字必须逐字一致。解决在验证Prompt里加强调“允许等价表述和同义改写”同时把验证粒度从“整句”调整成“每个关键数字和实体”。这样验证器会更宽容也更能聚焦在真正重要的事实上。6.3 多文档冲突同一个事实两种说法现象新旧文档里同一个指标数值不一致Agent每次都很自信地选择其中一个但用户拿着旧文档来投诉。解决在证据压缩阶段保留文档时间戳和版本号验证阶段增加“以最新文档优先并在回答中标注来源”的规则。如果版本冲突仍然无法消解就返回“资料存在矛盾请核对原文”而不是强行选边。这一点在金融、法律这类对准确率要求极高的场景里尤其关键。6.4 成本失控一次问答烧掉几千token现象单轮测试时一切正常压力测试后发现每道题平均调用大模型十几次成本飞涨。解决加两道闸。第一道路由阶段就拒绝掉无需检索的请求这一步能在源头省下大量token。第二道把重试上限从5次压到3次同时验证阶段只对“关键事实”做检查不做全文逐句评判。实测下来这两道闸能把平均调用次数从十几次压到四五次成本下降非常明显。6.5 效果评估与回归测试做一套稳定的效果评估机制比调任何参数都重要。我建议准备一个包含200条问题的小评测集每条标注标准答案和是否可检索。每次改动系统之后跑一遍对比忠实度和准确率。这里的忠实度指“回答中的关键数字、实体、结论能否在证据来源里找到依据”准确率指“答案与标准答案是否一致”。除了这两个指标还要盯“拒绝率”——如果回答不靠谱拒绝回答比强行回答更安全。很多团队只关心回答多漂亮忽略了“沉默是金”的价值。7. 上线后的数据与个人体会7.1 我观测到的一组效果数据以我实际搭过的一套知识库问答系统为例从单程RAG升级到RAGAgent闭环后核心指标变化大致如下答案忠实度从约78%提升到约94%也就是回答里的关键数字、实体、结论绝大多数都能在证据来源里找到依据。无法回答率从5%提高到8%。这个指标看起来变差了但我反而认为这是好事——系统开始学会说“我不知道”而不是硬编一个答案。平均响应时间从1.2秒升到2.8秒多出来的时间主要花在重排和验证上。但用户的投诉率明显下降因为错误答案少了。从成本角度看分层调用和路由过滤带来了约40%的token费用节省。当然这些数字依赖具体业务场景不能直接搬用但它们说明了一个方向用一点延迟和成本换取正确性在大多数生产场景里是值得的。7.2 我个人的最终体会“终极方案”这个说法我始终不太认同。任何追求“百分之百消灭幻觉”的思路都不现实因为幻觉是大模型的结构性特性不是表层bug。RAG和Agent结合真正解决的问题不是消灭幻觉而是让幻觉变得可发现、可验证、可纠正。在工程上我最大的体会就是把每一步都做成显式的别让模型在一个黑盒里完成所有事。路由是显式的子问题是显式的证据是显式的验证结论也是显式的。凡是能被记录、能被检查、能被反馈的环节幻觉就无处躲藏。最后分享一个小技巧给Agent循环里的每个子问题打印一条结构化日志记录“子问题是什么、查到了哪些证据、验证结论是什么”。这套日志在调试时的价值远超任何监控面板。这套思路也不止适用于文档问答客服机器人、行业报告生成、智能投研这些场景都可以复用。如果你正准备搭类似的系统我的建议是从一个小领域开始把闭环先跑通再慢慢加知识源别一上来就追求大而全。