返回学习地图
llmPhase C · 第 20

3.3 RAG高级

混合检索/重排序/查询分解:让RAG从能用变好用

5 个章节·按类别展开/折叠
知识

基础RAG的局限性

基础RAG(简单向量检索)有很多问题。

问题1:语义鸿沟。用户问“怎么让模型跑得快一点?”,文档里写的是“优化推理速度的方法包括:量化、剪枝、蒸馏...”。向量检索可能找不到这篇文档,因为“跑得快”和“推理速度”的向量距离较远。

问题2:多跳问题。用户问“张三的老板的老婆是谁?需要检索:张三→老板→老板的老婆。单次检索只能找到“张三”相关的文档,找不到“老板的老婆”。

问题3:粒度不匹配。用户问一个具体的技术细节,但检索到的是整章内容。模型被大量无关信息淹没,无法找到关键答案。

问题4:幻觉与遗漏。检索到的文档不够全面,模型基于有限信息回答,可能产生幻觉。或者关键文档被遗漏,导致回答不完整。

问题5:缺乏上下文。检索到的文档片段缺少上下文。例如:检索到“该方法提高了20%的效率”,但不知道“该方法”是什么。

解决方案:高级RAG技术。

知识

混合检索:向量+关键词+知识图谱

混合检索(Hybrid Search)结合多种检索方式,取长补短。

1. 向量检索(Dense Retrieval):用Embedding找语义相似的文档。擅长:语义理解、同义词、近义词。弱点:对特定关键词(如产品型号、ID、代码)不敏感。

2. 关键词检索(Sparse Retrieval / BM25):传统搜索引擎技术。统计词频和文档频率。擅长:精确匹配、特定术语、产品型号。弱点:不理解语义。

3. 知识图谱检索:把文档中的实体和关系构建成图谱。擅长:多跳查询、关系推理。例如:张三→works_for→公司A→CEO→李四→spouse→王五。

混合检索的融合:

向量检索结果:文档A(0.9), 文档B(0.8), 文档C(0.7)
关键词检索结果:文档B(0.95), 文档D(0.9), 文档A(0.6)
知识图谱结果:文档E(1.0), 文档B(0.8)

融合(Reciprocal Rank Fusion):
RRF分数 = Σ 1/(k + rank_i)
其中k=60(常数),rank_i是文档在第i个检索结果中的排名

文档A:1/(60+1) + 1/(60+3) = 0.0164 + 0.0159 = 0.0323
文档B:1/(60+2) + 1/(60+1) + 1/(60+2) = 0.0161 + 0.0164 + 0.0161 = 0.0486 ← 最高
文档C:1/(60+3) = 0.0159
文档D:1/(60+2) = 0.0161
文档E:1/(60+1) = 0.0164

最终排序:B > E > A > D > C

参数表:

参数含义典型值太大/太小
向量权重向量检索结果的重要性0.5~0.7太高→忽略关键词;太低→语义丢失
关键词权重关键词检索结果的重要性0.3~0.5太高→忽略语义;太低→精确匹配丢失
RRF常数k排名惩罚系数60太大→排名差异小;太小→高排名垄断
知识

重排序与查询分解:精准定位答案

重排序(Re-Ranking):第一次检索(召回)找到100篇相关文档,第二次用更强的模型对这些文档精确排序,选出最相关的5篇。就像考试:先海选100人,再面试选出5人。

重排序模型:

  • Cross-Encoder:把查询和文档拼接,输入BERT,输出相关性分数。准确但慢(每对查询-文档需要一次前向传播)。
  • ColBERT:对每个token计算相似度,然后聚合。比Cross-Encoder快,但比Bi-Encoder慢。
  • LLM重排序:用GPT-4等强模型判断文档是否相关。最准确但最贵。

查询分解(Query Decomposition):把复杂查询拆成简单子查询。例如:“张三的老板的老婆是谁?” → 子查询1:“张三的老板是谁?” → 子查询2:“[老板名字]的老婆是谁?”

查询分解步骤:

原始查询:公司A在2020年的营收和2023年的利润分别是多少?

分解:
子查询1:公司A 2020年营收
子查询2:公司A 2023年利润

分别检索:
结果1:公司A 2020年营收为10亿元(来源:2020年报)
结果2:公司A 2023年利润为2亿元(来源:2023年Q3财报)

合并回答:
公司A在2020年的营收为10亿元,2023年的利润为2亿元。

查询改写(Query Rewriting):用户问“跑得快”,系统改写为“推理速度优化”,提高检索准确率。

参数表:

参数含义典型值太大/太小
召回数量(top-k)第一次检索返回多少文档20~100太大→重排序慢;太小→遗漏相关文档
重排序数量(top-n)最终保留多少文档3~10太大→上下文太长;太小→信息不足
子查询数量分解后的子查询数2~5太多→检索开销大;太少→分解不充分
实例

例子:高级RAG完整流程

实例

场景:用户问“怎么优化模型推理速度?”

Step 1: 查询改写。

原始查询:怎么优化模型推理速度?
改写后:深度学习模型推理加速方法(量化、剪枝、蒸馏、并行、缓存)

Step 2: 混合检索。

向量检索:
  文档A: 模型量化技术(相似度0.85)
  文档B: 知识蒸馏简介(相似度0.78)
  文档C: Transformer推理优化(相似度0.72)

关键词检索:
  文档D: 推理速度优化指南(BM25分数0.92)
  文档A: 模型量化技术(BM25分数0.88)
  文档E: GPU并行计算(BM25分数0.85)

RRF融合:
  文档A: 1/(60+1) + 1/(60+1) = 0.0328 ← 最高
  文档D: 1/(60+1) = 0.0164
  文档E: 1/(60+2) = 0.0161
  文档B: 1/(60+2) = 0.0161
  文档C: 1/(60+3) = 0.0159

Step 3: 重排序。

用Cross-Encoder对Top 5文档精确排序:
  文档A: 0.95(量化→直接优化推理速度)
  文档D: 0.90(优化指南→全面但不够具体)
  文档E: 0.85(GPU并行→相关但间接)
  文档B: 0.80(蒸馏→相关但训练阶段)
  文档C: 0.75(Transformer优化→部分相关)

Step 4: 生成回答。

最终保留Top 3文档(A, D, E)输入LLM。
LLM生成回答:
优化模型推理速度的方法包括:
1. 模型量化(文档A):将FP32权重转为INT8,减少内存占用和计算量...
2. 并行计算(文档E):使用多GPU或批处理...
3. 其他优化(文档D):包括剪枝、缓存等...

效果:相比基础RAG(只检索到文档B和C),高级RAG找到了更精准的文档A和D,回答质量显著提升。

练习

练习:RAG高级

练习

Q1:基础RAG有哪些主要局限性?请列举3个。

Q2:混合检索中,向量检索和关键词检索各自擅长什么?为什么需要两者结合?

Q3:RRF融合公式中,常数k=60的作用是什么?如果k=10会怎样?

Q4:Cross-Encoder和Bi-Encoder(向量检索用的模型)有什么区别?为什么重排序用Cross-Encoder更准确?

Q5:查询分解适合什么类型的问题?如果用户问“介绍Python”,需要分解吗?

查看答案

A1:1.语义鸿沟:用户用词和文档用词不同;2.多跳问题:需要多个关联文档才能回答;3.粒度不匹配:检索到文档太粗或太细;4.幻觉与遗漏:检索不全面导致回答不完整;5.缺乏上下文:检索片段缺少上下文。

A2:向量检索擅长语义理解、同义词、近义词匹配。关键词检索擅长精确匹配、特定术语、产品型号。两者结合是因为:单独向量检索对特定术语不敏感,单独关键词检索不理解语义。互补使用可提高召回率。

A3:k=60的作用是平滑排名差异。k=10时,排名差异被过度放大,高排名的文档会垄断最终分数,低排名的文档几乎没有贡献。k=60让不同排名的文档都能有一定贡献,更平衡。

A4:Bi-Encoder分别对查询和文档编码,然后计算向量相似度。快但精度较低(因为编码时不知道对方)。Cross-Encoder把查询和文档拼接一起编码,能直接建模两者关系。慢但精度高(因为能看到完整交互)。重排序只需要对少量文档(如Top 20)做精确排序,所以用Cross-Encoder更准。

A5:查询分解适合复杂、多条件、多跳的问题。“介绍Python”是简单查询,不需要分解。但如果问“Python和Java在Web开发、数据科学、机器学习三个领域的优劣对比”,可以分解为3个子查询,分别检索三个领域的对比信息。