基础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个子查询,分别检索三个领域的对比信息。