html
flowchart TD
subgraph A [1. 预处理]
direction LR
U[用户提问] --> QW[查询改写]
end
QW --> HR[2. 混合检索]
subgraph B [混合检索与重排]
direction TB
HR --> VEC[向量检索<br>(语义)]
HR --> BM25[关键词检索<br>(BM25)]
VEC --> FUS[结果融合<br>(RRF算法)]
BM25 --> FUS
FUS --> RR[重排序<br>(专用模型)]
end
RR --> C[3. 构建提示]
subgraph D [4. 生成]
C --> LLM[大语言模型]
LLM --> OUT[最终答案]
end
subgraph E[元数据过滤]
MD[元数据过滤] -.-> HR
end
核心阶段一:离线索引(知识库准备)
复杂RAG的索引阶段需要比基础RAG考虑得更周全。
-
文档加载与智能分块
-
加载 :使用
Unstructured、LlamaIndex等工具解析PDF、Word等格式。 -
分块 :采用语义分块 ,而非固定大小切分。例如,先按段落切,再用模型判断句子边界,或使用滑动窗口技术,让每个块包含一部分上一块的内容,保证上下文连贯。
-
-
向量化与多重索引
-
向量化 :使用高性能嵌入模型(如
BAAI/bge-large-en-v1.5、voyage-2)。 -
多重索引 :同时构建语义索引 (稠密向量)和关键词索引(如BM25的稀疏向量),为混合检索做准备。
-
-
元数据提取与存储
- 提取文档的元数据(如
source、timestamp、author)并存入数据库,用于检索时的预过滤。
- 提取文档的元数据(如
核心阶段二:在线查询(复杂RAG流程)
这是系统运行时,处理用户每一步请求的详细过程。
步骤 1:查询改写 (Query Rewriting)
用户的问题往往含糊、缺少上下文或不够专业,直接检索效果不佳。
-
方法:
-
假设性文档嵌入 (HyDE):让LLM先根据用户问题生成一个"假设的理想答案片段",然后用这个片段去检索。因为答案比问题更接近真实文档的语言风格。
-
多查询重写 (Multi-Query):让LLM从一个原始问题改写生成多个不同角度或表述的查询,同时进行检索,避免遗漏。
-
Step-back Prompting:先让LLM提出一个更宏观、抽象的背景问题,用它的答案作为上下文辅助检索原问题。
-
查询拆分:将复杂的多跳问题(如"比较A和B的异同")拆分成几个独立的子问题,分别检索再汇总。
-
步骤 2:混合检索 (Hybrid Retrieval)
单独依赖向量检索或关键词检索都有缺陷。混合检索将两者结合。
-
并行检索:
-
向量检索:用改写后的查询向量在向量数据库中检索,找到语义最相似的Top-K个文档块(例如K=20)。
-
关键词检索:用相同的查询进行BM25检索,找到关键词匹配度最高的Top-K个文档块(K=20)。
-
-
元数据预过滤:在检索前,根据用户问题或场景(如"只看去年发布的文档")过滤元数据,缩小搜索范围。
步骤 3:结果融合 (Result Fusion)
如何将来自两种不同检索器的结果合并成一个统一的列表?
-
常用算法:倒数排名融合 (RRF,Reciprocal Rank Fusion)
-
计算每个文档块在新列表中的分数:
Score = sum( 1 / (Rank_in_each_list + k) ) -
Rank是该块在单个检索器结果中的排名,k是常数(通常取60)。 -
优点:无需标准化分数,能有效压制单一检索器的异常高分结果,表现稳定。
-
步骤 4:重排序 (Re-ranking)
RRF融合后的列表,前几个结果可能依然不够精准。需要用一个更强大的模型进行精排。
-
方法 :使用交叉编码器 (Cross-Encoder) 重排模型。
-
输入 :将
(查询, 每个文档块)成对输入到专用的重排模型中。 -
原理:与向量检索的"双编码器"不同,交叉编码器会让查询和文档块在模型内部进行深度交互,更精确地评估相关性。缺点是计算成本高。
-
常用模型 :
BAAI/bge-reranker-v2-m3、Cohere或Voyage的重排API。
-
-
操作:将RRF融合后的Top-N个(如N=30)文档块送入重排模型,根据输出的相关性分数重新排序,最后只取分数最高的几个(如3-5个)作为最终上下文。
步骤 5:上下文压缩 (Context Compression)
检索到的文档块可能包含大量无关信息,会干扰LLM。
-
方法:
-
LLM筛选:让一个较小的LLM逐块判断并提取最相关的句子。
-
重新打包:将压缩后的信息按相关性或原始顺序重新组织。
-
步骤 6:构建提示与生成 (Prompt & Generation)
-
构建提示:使用一个结构清晰的模板,明确告知LLM忽略无关信息,并在信息不足时拒绝回答。
-
生成:将提示发送给LLM(如GPT-4o、Claude 3.5 Sonnet、Llama 3),得到最终答案。
-
增强功能:
-
引用溯源 :让LLM在答案中标注信息来源(如
[1]、[2])。 -
对话历史:在聊天场景中,将之前的对话内容也作为上下文的一部分输入LLM。
-
关键区别总结
| 步骤 | 基础RAG | 复杂RAG |
|---|---|---|
| 查询处理 | 直接使用原始查询 | 查询改写(HyDE、多查询、拆分等) |
| 检索方式 | 单一向量检索 | 混合检索(向量 + 关键词/BM25) |
| 结果处理 | 直接取向量检索的Top-K | RRF融合 + 重排序模型 + 上下文压缩 |
| 检索精度 | 中低 | 高 |
| 计算开销 | 低 | 高 (多次LLM调用、重排模型) |
| 适用场景 | 原型、简单问答 | 生产环境、高要求、复杂知识库 |
总结与建议
一个复杂的RAG系统通过引入查询改写、混合检索、重排序 等一系列模块,大幅提升了最终效果,但这需要你在检索质量、响应延迟和系统成本之间做权衡。
-
对于文档质量高、查询意图明确的场景,基础RAG可能已足够。
-
对于文档多样、查询复杂、要求高精度的生产环境,值得投入资源构建上述复杂RAG流程。