[控场AI]
· 12 分钟阅读· 6,102 字

RAG系统:LLM不是难点,检索质量才是关键

RAG系统:LLM不是难点,检索质量才是关键

RAG失败多因检索未提供充分证据,应按检索、分块、评估的顺序系统排查。

文章指出,RAG系统最常见的失败并非模型能力不足,而是检索环节没有提供回答所需的证据——搜索有结果、模型有输出,但决定性条款从未被召回。作者强调检索相关性不等于答案相关性,并逐阶段梳理管道故障:文档来源、摄入、分块、索引、检索、过滤、重排序与生成各有独特失败模式。分块应被视为知识建模决策,需保留条件、例外、表格关系与元数据;向量搜索不应包办所有查询,混合检索结合关键词与语义匹配更可靠。评估上应先用Recall@K等指标独立测量检索,再单独评估生成,并管理文档版本、生效日期与权限等生命周期问题。最后给出从验证源材料到监控退化的九步改进顺序,并主张系统应具备证据不足时弃权的能力。

核心观点:检索增强生成(RAG)的失败往往不是模型不够强,而是检索环节没有提供足够的证据。本文从检索相关性、分块策略、混合搜索、评估方法等角度,剖析RAG工程中真正困难的部分。

RAG系统架构示意图

为什么RAG系统会“看起来正常”却答错?

一个典型场景:用户问“合同续约后,客户还能申请退款吗?”知识库里有通用退款政策、合同续约流程,以及一份已被替换的旧政策。系统检索到了相关内容,模型生成了流畅的回答,应用也成功返回响应——但答案缺乏依据。

这就是RAG系统的隐蔽失败:搜索有结果,模型有输出,但关键证据从未被检索到。检索增强生成(RAG)的概念很简单:索引文档、检索相关段落、交给语言模型生成答案。但构建可靠系统的难点在于——找到关于某个主题的文本,不等于找到回答问题所需的证据。

真正困难的工作发生在生成之前。

检索相关性不等于答案相关性

传统搜索的目标是返回与查询匹配的文档。RAG的责任更具体:检索出能支撑答案的证据。

向量搜索可能找到通用退款政策,却遗漏了包含决定性条件的续约流程。检索到的文本语义相关,但不足以回答问题。模型无法可靠地恢复它从未见过的规则——它可能猜测、组合不相关的条件,或以过度的自信给出不完整的答案。

这一区别改变了调试思路:如果失败点是检索,修改提示词或升级模型只会增加成本,而无法解决问题。

向量搜索(也称语义搜索)将查询和文档分别映射为高维空间中的稠密向量,通过余弦相似度或点积衡量语义接近程度。其优势在于能跨越字面差异找到概念相关的内容,例如查询“退款”可以匹配到“返还货款”的段落。然而向量表示是压缩后的语义摘要,会丢失精确标识符、否定词、数值边界等细节,也可能把语义相近但结论相反的文本排在前面。这正是文中“语义相关但不足以回答”的技术根源:相似度衡量的是主题接近,而非证据充分性。

RAG管道的每个阶段都可能引入不同的故障

一个完整的RAG管道包括:文档来源→摄入→分块→索引→检索→过滤→重排序→LLM生成→答案。

每个阶段都有独特的失败模式:

  • 文档来源:文档缺失、重复或过时。
  • 摄入:内容提取错误。
  • 分块:规则与例外被分离。
  • 索引:表示缺失或陈旧。
  • 检索:相关证据未被找到。
  • 过滤:有用或已授权的证据被移除。
  • 重排序:相关段落排名过低。
  • 生成:证据被误解或添加了无依据的声明。

答案质量取决于每一个阶段,而不仅仅是语言模型。

分块策略本质上是数据建模决策

分块常被当作配置选项:选个token上限、加点重叠、索引结果。但更有用的问题是:在这个应用中,知识的最小有意义单元是什么?

假设退款政策在一节说明通用规则,另一节说明续约例外。固定大小的切分可能将例外与它所修饰的规则分开。两个块都是有效文本,但单独检索时都无法提供足够上下文。

分块边界应反映源材料的结构:

  • 政策需要保留条件、例外和章节标题。
  • 合同可能需要条款边界和交叉引用。
  • 产品文档宜将版本细节与功能描述放在一起。
  • 表格需要标题、单位和值保持关联。

元数据(如文档标题、章节、版本、生效日期和来源标识)可以帮助保留上下文,而无需在每个块中重复整个文档。

一张产品限额表,如果索引管道提取了数值但丢失了列标题,检索到的文本可能包含正确数字却没有说明其含义。模型不得不推断原始文档已经定义的关系。

分块是知识建模的一部分,而不仅仅是文本预处理。目标是创建足够聚焦以便检索、足够完整以便解释的单元。

分块(Chunking) 指将长文档切分为适合索引和放入上下文窗口的文本单元,常见做法包括固定 token 窗口加重叠、按段落或标题切分、按语义相似度动态合并等。块大小存在权衡:块太小则上下文缺失、指代无法解析;块太大则检索精度下降,且一个块内混杂多个主题会稀释相关性信号。重叠窗口可缓解边界切断问题,但会增加索引体积和重复召回。实践中常配合元数据标注(章节路径、文档标题)和父子块结构——用小块检索、返回其所属大块——以兼顾定位精度与解释完整性。

向量搜索不应解决所有搜索问题

向量搜索能在查询措辞与源文本不同时找到概念相关的材料。但企业问题常包含精确术语、产品代码、错误消息或版本号。

“解释我们的退款政策”与“续约后RF-204政策是否适用?”不同。前者可能受益于语义匹配;后者可能依赖精确标识符和特定文档版本。

混合检索结合基于关键词和向量的搜索,然后合并结果。关键词搜索可以捕获“续约”和精确标识符等关键术语,而向量搜索可以容忍措辞差异。混合搜索的价值在于结合互补优势,而不是假设一种检索方法对所有查询都同样有效。

微软的混合搜索概述解释了文本和向量搜索如何协同工作。正确的检索策略取决于数据和用户提出的问题——技术支持系统可能需要精确错误代码匹配,政策助手可能更依赖语义相似性,但仍需精确的政策标识符和版本约束。

混合检索(Hybrid Search) 通常并行执行 BM25 等稀疏关键词检索与稠密向量检索,再用倒数排名融合(RRF)或加权分数归一化合并两路结果。BM25 基于词频与逆文档频率,对精确术语、产品编号、错误码极为敏感,且天然带有词项重要性权重;向量检索则弥补同义改写和长尾表述。融合的关键难点在于两路分数不可直接比较,需要排名级融合或统一归一化。微软 Azure AI Search、Elasticsearch 等平台已内置该能力。是否启用混合检索应通过固定评估集对比验证,而非默认开启。

检索需要的不只是相似度分数

相似度分数估计检索项与查询的匹配程度,但它不能证明该项包含答案。一个段落可能与问题高度相似,却遗漏了决定结果的条件;另一个分数较低的段落可能包含决定性的例外。

这带来一系列工程问题:检索应返回多少候选?关键词和向量结果是否应合并?哪些文档是权威的?文档版本和生效日期应如何影响排名?何时应使用重排序器?当证据不完整或矛盾时怎么办?

典型方法是检索更广泛的候选集,然后使用更详细的相关性评估进行重排序。这可以改善结果顺序,但无法恢复初始检索阶段从未返回的证据。过滤也需要谨慎:移除过时或未授权的文档是必要的,但过于宽泛的过滤可能消除唯一能回答问题的段落。

对于处理私有或租户特定信息的系统,授权必须在检索过程中强制执行,而不是依赖语言模型选择忽略未授权段落。

需要多文档的问题怎么办?

有些问题无法从单个段落回答。例如:“根据当前政策,这位客户能否获得退款?”可靠答案可能需要三部分证据:当前退款政策、客户的合同续约日期、以及该产品或合同类型的适用例外。

仅检索通用政策不够,仅检索合同缺少例外也不够。这时需要多步检索:系统可能需要识别缺失的事实,检索额外文档,并在生成答案前组合证据。

但额外的检索步骤会引入自身风险:早期错误可能引导后续搜索走向错误方向;系统可能积累不相关段落,或将两个文档视为一致而实际上并非如此。

一个有用的设计原则是明确证据要求。对于依赖多个条件的问题,定义在答案被认为完整之前必须建立哪些事实。系统随后可以区分证据充分的问题和仍需更多信息的问题。

上下文窗口大了,为什么不把全部内容给模型?

更大的上下文窗口使传递更多信息成为可能,但它们并未消除对检索的需求。将整个知识库塞入提示词可能增加延迟、成本,以及模型必须处理的不相关信息量。大量输入还可能使模型更难一致地使用最重要的细节。

更多上下文不一定是更好的上下文。好的检索系统将证据缩小到对当前问题重要的材料,保留足够周围信息以正确解释证据,同时避免不相关段落。目标不是不惜一切代价最小化上下文,而是提供最小充分的可信证据集。

这种平衡取决于任务:简短的故障排除问题可能只需一个文档章节;复杂的合同问题可能需要多个条款及其交叉引用。上下文窗口是一种资源,检索是系统决定什么值得使用该资源的方式。

先测量检索,再归咎生成

流畅的答案不能证明检索有效。有说服力的评估必须检查到达模型的证据。

一个有用的起点是Recall@K:预期的相关来源是否出现在前K个检索结果中。如果一个问题的预期来源出现在前五个结果中,其来源召回率@5为1;如果未出现,则为0。在一组问题上取平均,可指示检索找到预期证据的频率。对于需要多个文档的问题,评估还应检查所有必需来源是否被检索到。

以下Python函数可计算来源召回率@K:

def retrieval_metrics_at_k(expected_sources, retrieved_sources, k=5):
    """
    expected_sources: 相关来源ID的可迭代对象
    retrieved_sources: 按检索排名排序的来源ID
    """
    expected = set(expected_sources)
    retrieved = retrieved_sources[:k]
    if not expected:
        return {
            "recall_at_k": None,
            "all_sources_found": None,
        }
    found = expected.intersection(retrieved)
    return {
        "recall_at_k": len(found) / len(expected),
        "all_sources_found": found == expected,
    }

对于单来源问题,Recall@K为0或1;对于需要多个来源的问题,它测量检索到的预期来源比例。all_sources_found字段指示是否所有预期来源都出现在前K个中。

这只是一个起点。源级评估可能遗漏文档内部的问题:正确文件被检索到,但相关章节不在返回的块中。更强的评估应跟踪相关段落、排名质量,以及最终答案是否由检索到的证据支撑。

下一步是分别评估生成:给定正确证据,模型是否产生正确答案?是否保留了条件和例外?是否引入了来源不支持的声明?分离检索和生成指标使故障更容易诊断。如果检索召回率差,调查摄入、分块、索引、查询构建和排名;如果检索强但答案仍不正确,调查上下文组装、指令、模型行为和答案验证。

重排序(Reranking) 是在初步召回之后,用交叉编码器(Cross-Encoder)等更重的模型对查询与每个候选段落联合打分,从而获得比独立向量编码更精细的相关性判断。典型流程是先召回数十到上百个候选,再由重排序器筛出前若干条送入生成。它能显著改善排名质量,但受限于召回集合:如果决定性证据根本没进入候选集,重排序无从补救。因此重排序优化的是排序指标(如 MRR、NDCG),而 Recall@K 反映的是召回上限,二者需分开度量。

检索也是生命周期问题

文档会变化。政策修订、产品演进、合同到期、旧流程过时。一个启动时运行良好的检索系统,如果索引不再反映当前源材料,可能逐渐变得不可靠。

这不仅是索引问题,而是生命周期问题。生产级RAG系统需要明确回答:如何检测变更文档?更新文档多快重新索引?删除或取代的文档如何移除?如何识别权威版本?生成的答案如何追溯到来源?索引或排名变更后如何检测检索退化?

文档版本和生效日期在企业系统中尤为重要。最新文档不总是每个问题的正确文档——历史问题可能需要特定日期生效的政策。同样,文档可能技术上最新,但不适用于特定客户、产品或地区。

检索因此需要考虑权威性、时间、范围和访问权限,而不仅仅是语义相似性。评估集也应随知识库演进。当重要文档或业务规则变化时,团队应更新测试问题,并验证先前正确的检索行为仍然成立。

实操改进顺序

当RAG系统产生不可靠答案时,更换模型不应自动成为第一反应。更有效的顺序是:

  1. 验证源材料:检查所需信息是否存在、是否最新、能否正确提取。
  2. 检查分块:确认标题、条件、例外、表格关系和相关元数据在预处理后保留。
  3. 检查检索结果:捕获代表性问题的实际返回段落,不要只依赖最终答案。
  4. 改进候选检索:测试关键词搜索、向量搜索、混合检索和适当过滤。
  5. 评估排名:检查相关段落是否出现在顶部附近,重排序是否改善其位置。
  6. 验证证据完整性:对于多文档问题,确认所有必要事实已检索到。
  7. 独立评估生成:给模型已知良好的证据,评估其答案是否准确且有支撑。
  8. 在固定评估集上测试变更:比较每次有意义更改前后的结果,避免依赖轶事性改进。
  9. 监控生命周期:跟踪文档新鲜度、索引失败、检索退化、延迟和成本。

这个顺序帮助团队将精力花在能产生可衡量差异的地方,也防止一个常见错误:试图用更昂贵的模型修复检索失败。

不是每个问题都应该产生答案

即使设计良好的检索管道有时也会找不到足够证据。系统应能认识到这一局限。

如果检索到的文档无法确定是否允许退款,正确响应可能是说明可用证据不足。如果两个权威来源冲突,系统可能需要呈现冲突,而不是默默选择一个。如果所需文档不可访问,系统不应编造其内容。

这种行为需要的不仅仅是一个说“不要幻觉”的提示词。它取决于应用如何定义证据充分性、处理冲突来源和验证答案。对于某些问题,应用可以在生成前要求特定事实存在;对于其他问题,可以返回有来源支持的答案并明确限制,或向用户询问缺失信息。

弃权不是良好检索的替代品,而是处理检索无法提供足够证据情况的必要部分。可靠系统必须知道如何回答,也必须知道何时没有足够信息负责任地回答。

真正的工作发生在答案之前

RAG常被呈现为搜索索引和语言模型之间的简单连接。这种描述掩盖了大量工程工作。最终答案的质量取决于进入系统的文档、内容表示方式、检索到的段落、证据排名和组装方式,以及结果上下文是否足以回答问题。

模型很重要,但只是更长决策链中的一个组件。当答案错误时,首先检查模型实际接收了什么:正确文档是否可用?相关段落是否保留?检索是否找到它?排名是否足够高?证据是否完整、最新且已授权?

这些问题通常比问“模型是否足够聪明”更有用。RAG系统的核心问题不是它能否生成答案,而是它是否为正确的问题、从正确的来源、检索到了正确的证据。这才是可靠RAG工程的起点。

分享:

相关推荐