一、8 种策略逐一定义 + LLM 参与度
1. 查询改写(Query Rewriting)
是什么:将用户原始查询改写为更适合检索系统匹配的形式。核心解决两类问题:
- 多轮对话中的指代消解:用户第1轮问"华为Mate60电池多大?",第2轮问"那充电速度呢?" → 改写为"华为Mate60充电速度"
- 口语化/模糊表达规范化:"怎么搞那个报错" → "Spring Boot 启动时报错 ClassNotFoundException 如何解决"
LLM 参与 :✅ 需要。指代消解和语义理解必须依赖 LLM。规则方法只能处理固定模板(如缩写展开),无法处理真正的上下文依赖。
框架实现:
- LlamaIndex:
TransformQueryEngine+ 自定义BaseQueryTransform - LangChain:自定义 LCEL Chain,将 chat history + 当前 query 传入 LLM 做改写
- LangChain 还提供
create_history_aware_retriever()------ 条件触发的查询改写:有 chat_history 才改写,没有则直接检索,精确控制 LLM 调用成本
2. 查询扩展(Query Expansion)
是什么:从原始查询出发,生成多个变体查询,提高检索召回率。变体查询覆盖不同的表达方式、视角或侧面。
示例:
原始查询:"RAG 性能优化"
扩展查询1:"RAG 检索速度提升方法"
扩展查询2:"Retrieval-Augmented Generation 延迟降低"
扩展查询3:"RAG 系统吞吐量优化策略"
LLM 参与 :⚠️ 可选,取决于具体技术路线:
| 子技术 | LLM? | 说明 |
|---|---|---|
| LLM 多查询生成 | ✅ 需要 | LLM 从不同角度生成 N 个变体查询 |
| 伪相关反馈(PRF) | ❌ 不需要 | 取首轮检索 top-k 结果的高频词加入查询,纯统计方法 |
| 静态词典扩展 | ❌ 不需要 | 预置同义词词典,查表追加 |
| RRF 融合 | ❌ 不需要 | 多检索器结果合并,纯数学算法 |
框架实现:
- LangChain:
MultiQueryRetriever(LLM 生成 3 个变体) - LlamaIndex:
QueryFusionRetriever(num_queries=3, mode="reciprocal_rerank") - Haystack:
query_expander.py(独立的查询扩展组件)
3. 同义词扩展(Synonym Expansion)
是什么:为查询中的关键术语生成同义词/近义词,用所有同义词去匹配知识库中使用不同术语的实体。
示例:
查询:"手机销量" → 同义词扩展 → "手机 智能手机 mobile phone cellphone 销量 销售量 销售额"
→ 能匹配到知识库中写"智能手机出货量"的文档
LLM 参与 :⚠️ 可选:
| 子技术 | LLM? | 说明 |
|---|---|---|
| LLM 生成同义词 | ✅ 需要 | LLM 根据上下文生成语境化同义词 |
| 静态同义词典(WordNet 等) | ❌ 不需要 | 查预置词典 |
| Embedding 近邻发现 | ❌ 不需要(用 Embedding 模型) | 在向量空间找最近邻词 |
框架实现:
- LlamaIndex GraphRAG:
LLMSynonymRetriever(synonym_expand_factor=2)--- LLM 生成同义词去匹配知识图谱实体 - 传统方法:WordNet / 领域术语表 + 自定义扩展器
4. 一个问题扩展成多个问题(Multi-Query Generation)
是什么:用 LLM 将单个查询从不同角度/视角重新表述为多个独立查询,每个查询独立检索后合并结果。
与查询扩展的区别:
- 查询扩展:可以是词语层面的(追加同义词),也可以是句子层面的
- 多查询生成:一定是完整句子层面的,每个变体是一个完整的、语义不同的查询
示例:
原始查询:"Python 异步编程最佳实践"
多查询1:"Python asyncio 常见陷阱和解决方案"
多查询2:"Python 异步编程与同步编程的性能对比"
多查询3:"Python async/await 生产环境最佳实践"
LLM 参与 :✅ 需要。生成语义不同的完整查询变体必须依赖 LLM 的语言理解和生成能力。
框架实现:
- LangChain:
MultiQueryRetriever(默认生成 3 个变体) - LlamaIndex:
QueryFusionRetriever配合 LLM 生成多查询 - Haystack:
multi_query_embedding_retriever/multi_query_text_retriever
5. 复杂问题拆解成多个子问题(Query Decomposition)
是什么:将一个需要多步推理或多信息源的复杂问题,拆分成若干可独立回答的简单子问题。
示例:
原始查询:"对比欧洲和亚洲的营收增长情况"
拆解:
子问题1:"欧洲地区营收增长数据是多少?"
子问题2:"亚洲地区营收增长数据是多少?"
子问题3:"欧洲和亚洲营收增长率的差异是多少?"
→ 每个子问题独立检索 → 合并答案
LLM 参与 :✅ 需要。理解问题的复杂结构并拆解需要 LLM 的推理能力。
框架实现:
- LlamaIndex:
SubQuestionQueryEngine--- LLM 拆解 + 分别查询不同数据源 + 合成答案 - LlamaIndex:
DecomposeQueryTransform/StepDecomposeQueryTransform--- 查询分解变换器 - LangChain:
MultiQueryRetriever不做拆解(只做变体);拆解需要自定义 Chain + LangGraph
6. 生成假设答案用假设答案查询(HyDE - Hypothetical Document Embeddings)
是什么 :让 LLM 先对用户查询生成一个假设性答案(可能不准确但包含相关术语和语义),然后用这个假设答案的 Embedding 去检索,而不是用原始查询的 Embedding。
核心思想:查询和文档在 Embedding 空间中存在"语义鸿沟"------查询是问题形式,文档是答案形式。假设答案更接近文档的表述方式,因此检索更精准。
示例:
原始查询:"什么是 Transformer 的多头注意力机制?"
LLM 生成假设答案:"多头注意力机制是 Transformer 的核心组件,它将查询、键、值
分成多个头并行计算,每个头关注不同的表示子空间,最后拼接并线性变换..."
→ 用假设答案的 Embedding 检索 → 能匹配到技术文档(因为文档也是答案形式的表述)
LLM 参与 :✅ 必须需要。生成假设文档是 LLM 的核心职责,没有非 LLM 替代方案。
论文来源:Gao et al., "Precise Zero-Shot Dense Retrieval without Real Labels" (2023, arXiv:2212.10496)
框架实现:
- LlamaIndex:
HyDEQueryTransform+TransformQueryEngine(源码位于indices/query/query_transform/base.py) - LangChain:
HyDEretriever(社区版)
7. 构建知识库时为每条消息生成多个问题(Index-time Question Generation)
是什么 :这是索引阶段(而非查询阶段)的策略。对知识库中的每个文档块,用 LLM 生成多个"用户可能会问的问题",将这些问题的 Embedding 与原始文档块关联存储。查询时用问题 Embedding 检索,而非文档 Embedding。
核心思想:解决查询-文档语义鸿沟的另一种方式------不是把查询变得像文档(HyDE),而是把文档变得像查询。
示例:
文档块:"Transformer 使用多头注意力机制,将 Q/K/V 投影到 h 个子空间并行计算..."
生成的问题:
Q1: "Transformer 的注意力机制是怎么工作的?"
Q2: "什么是多头注意力?"
Q3: "Q/K/V 在 Transformer 中如何使用?"
Q4: "为什么 Transformer 需要多头注意力?"
→ 将 Q1-Q4 的 Embedding 存入向量库,都指向同一文档块
→ 用户查询"多头注意力是什么" → 与 Q2 高度匹配 → 返回该文档块
LLM 参与 :✅ 需要。生成高质量问题必须依赖 LLM。
框架实现:
- LlamaIndex:
QuestionsAnsweredExtractor(在IngestionPipeline中使用,为每个文档块生成假设问题) - LangChain:
MultiVectorRetriever(将多个表示关联到同一文档) - 这种技术在业界也被称为 "反向索引问题生成" 或 "假设问题索引"(Hypothetical Question Indexing)
8. 查询意图识别(Query Intent Recognition)
是什么:识别用户查询的意图类型,决定后续处理路径------是走 RAG 检索、直接 LLM 生成、闲聊兜底、还是走 Text-to-SQL 等结构化查询。
示例:
"华为Mate60电池多大" → 知识查询 → RAG 检索
"你好,你是谁" → 闲聊 → LLM 直接回答
"帮我写首关于秋天的诗" → 内容生成 → LLM 直接生成
"上月销售额按地区统计" → 数据查询 → Text-to-SQL
LLM 参与 :⚠️ 可选:
| 子技术 | LLM? | 说明 |
|---|---|---|
| LLM 意图分类 | ✅ 需要 | LLM 做零样本/少样本分类 |
| 规则/关键词匹配 | ❌ 不需要 | 正则/关键词路由 |
| Embedding 分类器 | ❌ 不需要(用 Embedding 模型) | 查询 Embedding 与预定义意图 Embedding 计算相似度 |
| 轻量分类模型 | ❌ 不需要 | 微调的 BERT/分类器 |
框架实现:
- LlamaIndex:
RouterQueryEngine+PydanticSingleSelector(LLM 选择路由) - LangChain:
RunnableBranch/ LangGraph 条件边 - LangGraph:
add_conditional_edges用于基于意图的路由
二、LLM 参与度总览
| # | 策略 | LLM 必须? | 非 LLM 替代方案 |
|---|---|---|---|
| 1 | 查询改写 | ✅ 必须 | 规则方法只能处理固定模板,无法泛化 |
| 2 | 查询扩展 | ⚠️ 可选 | PRF(统计)、静态词典(查表)、RRF(数学) |
| 3 | 同义词扩展 | ⚠️ 可选 | WordNet(词典)、Embedding 近邻 |
| 4 | 多查询生成 | ✅ 必须 | 无(生成语义不同的完整查询必须 LLM) |
| 5 | 查询分解 | ✅ 必须 | 无(理解复杂结构并拆解必须 LLM) |
| 6 | HyDE | ✅ 必须 | 无(生成假设文档是 LLM 核心职责) |
| 7 | 索引阶段问题生成 | ✅ 必须 | 无(生成高质量问题必须 LLM) |
| 8 | 查询意图识别 | ⚠️ 可选 | 规则匹配、Embedding 分类器、轻量模型 |
三、策略间的包含关系
┌─────────────────────────────────────────────────────────────────┐
│ 查询转换 (Query Transformation) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 查询扩展 (Query Expansion) │ │
│ │ ┌──────────────┐ ┌──────────────────────┐ │ │
│ │ │ 同义词扩展 │ │ 多查询生成 │ │ │
│ │ │ (词语级扩展) │ │ (句子级扩展的特例) │ │ │
│ │ └──────────────┘ └──────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────┐ ┌──────────────────────────────────┐ │
│ │ 查询改写 │ │ HyDE (改写的特殊形式) │ │
│ │ (改写为更匹配的形式) │ │ (改写为"假设答案"而非"改写查询") │ │
│ └──────────────────────┘ └──────────────────────────────────┘ │
│ │
│ ┌──────────────────────┐ ┌──────────────────────────────────┐ │
│ │ 查询分解 │ │ 查询意图识别 │ │
│ │ (拆成子问题) │ │ (分类→路由) │ │
│ └──────────────────────┘ └──────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────┐
│ 索引阶段问题生成 (独立维度) │
│ 不属于查询转换,属于索引优化 │
│ 但与 HyDE 是对称的对子: │
│ HyDE = 查询→文档 (查询阶段) │
│ 问题生成 = 文档→查询 (索引阶段) │
└───────────────────────────────────────┘
具体包含关系分析:
| 关系 | 说明 |
|---|---|
| 同义词扩展 ⊂ 查询扩展 | 同义词扩展是查询扩展在词语层面的特例。查询扩展还包括句子层面的多查询生成。 |
| 多查询生成 ⊂ 查询扩展 | 多查询生成是查询扩展在句子层面的特例,强调生成语义不同的完整查询。 |
| HyDE ⊂ 查询改写(广义) | HyDE 本质是一种特殊的查询改写------不是改写成更好的查询,而是改写成"假设答案"。但学术界通常将其单独列出,因为它改变了检索的语义对象(用答案 Embedding 而非查询 Embedding)。 |
| 查询改写 vs 查询扩展 | 改写是 1→1 变换(一个查询变成一个更好的查询);扩展是 1→N 变换(一个查询变成多个变体)。这是正交关系,不互相包含。 |
| 查询分解 vs 多查询生成 | 分解是 1→N 但子问题是不同维度 的(回答完要合并推理);多查询生成是 1→N 但变体是同一意图的不同表述(回答完只需去重)。 |
| 索引阶段问题生成 vs HyDE | 这是一对对称策略:HyDE 在查询阶段把查询变成"文档"去检索;问题生成在索引阶段把文档变成"查询"去被检索。两者解决同一个问题(语义鸿沟),但作用在不同阶段。 |
| 查询意图识别 vs 其他所有 | 意图识别是元策略------它决定是否需要执行其他策略。先识别意图,再决定走哪条路径。 |
四、工程化先后顺序
完整 RAG 查询处理流水线(从用户输入到最终答案):
用户输入
│
▼
┌─────────────────────────────────────────────────────┐
│ 阶段0: 查询意图识别 (Query Intent Recognition) │ ← 最先执行,决定后续路径
│ - 闲聊?→ LLM 直接回答,跳过所有后续步骤 │
│ - 知识查询?→ 进入 RAG 流水线 │
│ - 数据查询?→ 走 Text-to-SQL │
│ - 内容生成?→ LLM 直接生成 │
└─────────────────────────────────────────────────────┘
│ (如果走 RAG 路径)
▼
┌─────────────────────────────────────────────────────┐
│ 阶段1: 查询改写 (Query Rewriting) │ ← 第二步,修正查询本身
│ - 多轮对话指代消解 │
│ - 口语化表达规范化 │
│ - 输出:一个改写后的规范查询 │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 阶段2: 复杂问题拆解 (Query Decomposition) [条件触发] │ ← 仅当问题复杂时执行
│ - 判断是否需要多步推理/多信息源 │
│ - 如果是:拆成子问题,每个子问题独立走阶段3-5 │
│ - 如果否:直接进入阶段3 │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 阶段3: 查询扩展 (Query Expansion) │ ← 检索前增强
│ 阶段3a: 同义词扩展(词语级) │
│ - LLM 生成同义词 或 静态词典查表 │
│ 阶段3b: 多查询生成(句子级) │
│ - LLM 生成 N 个变体查询 │
│ 阶段3c: HyDE(可选,与3b二选一或组合) │
│ - LLM 生成假设答案 │
│ - 用假设答案 Embedding 替代查询 Embedding │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 阶段4: 检索 (Retrieval) │
│ - 向量检索 (用原始/扩展/假设答案 Embedding) │
│ - 关键词检索 (BM25 等) │
│ - 图谱检索 (用同义词匹配实体) │
│ - RRF 融合多路检索结果 │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 阶段5: 后处理 (Post-Retrieval) │
│ - 重排序 (Reranker: Cross-Encoder / Cohere) │
│ - 去重 (多查询/多路检索结果合并) │
│ - 上下文压缩 (Context Compression) │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 阶段6: 生成 (Generation) │
│ - 将检索结果 + 查询 传入 LLM 生成答案 │
│ - 如果是子问题拆解:合并各子答案 │
└─────────────────────────────────────────────────────┘
│
▼
最终答案
═══════════════════════════════════════════════════════
独立维度(不在查询流水线中):
┌─────────────────────────────────────────────────────┐
│ 索引阶段: 问题生成 (Index-time Question Generation) │
│ - 在构建知识库时执行,不在查询时执行 │
│ - 为每个文档块生成多个假设问题 │
│ - 将问题 Embedding 与文档块关联存储 │
│ - 查询时直接用问题 Embedding 检索 │
└─────────────────────────────────────────────────────┘
顺序设计原则:
| 原则 | 说明 |
|---|---|
| 意图识别最先 | 它是路由器,决定是否需要后续步骤。如果闲聊直接跳过,省 LLM 调用 |
| 改写在扩展之前 | 先修正查询本身(指代消解),再在正确的查询上做扩展。否则扩展的是错误查询 |
| 分解在扩展之前 | 先拆成子问题,再对每个子问题做扩展。否则一个复杂查询的扩展会混乱 |
| HyDE 与多查询二选一或组合 | 两者都解决语义鸿沟,组合使用收益递减但成本翻倍 |
| 问题生成独立于查询阶段 | 它是离线索引阶段的工作,不影响查询延迟 |
五、工业界通用策略
当前工业界(2024-2025)的分层实践:
┌─────────────────────────────────────────────────────────┐
│ 第一层:标配(几乎所有生产 RAG 系统都在用) │
│ │
│ 1. 查询改写(多轮对话场景必须) │
│ - 指代消解是聊天机器人的最低要求 │
│ - LangChain / LlamaIndex 均有成熟实现 │
│ - LangChain 的 create_history_aware_retriever() │
│ 条件触发:有 chat_history 才改写,没有则直接检索 │
│ │
│ 2. RRF 多路检索融合 │
│ - 向量检索 + BM25 关键词检索 → RRF 融合 │
│ - 不需要额外 LLM 调用,纯算法,性价比极高 │
│ │
│ 3. Reranker 重排序 │
│ - Cross-Encoder 模型对检索结果重排 │
│ - bge-reranker / Cohere Rerank / Jina Reranker │
│ │
│ 4. 基础查询意图识别 │
│ - 至少区分"闲聊" vs "知识查询" │
│ - 规则或轻量模型即可,不一定需要 LLM │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ 第二层:进阶(中大型 RAG 系统广泛采用) │
│ │
│ 5. 多查询生成 (Multi-Query) │
│ - LangChain MultiQueryRetriever 是事实标准 │
│ - 用 1 次 LLM 调用换 3-5 倍召回率提升 │
│ - 成本可控(1次 LLM 调用),ROI 高 │
│ │
│ 6. 查询分解 (Sub-Question) │
│ - 复杂分析型查询场景必备 │
│ - 金融/医疗/法律等垂直领域广泛使用 │
│ │
│ 7. 索引阶段问题生成 │
│ - 被验证为最高 ROI 的策略之一 │
│ - 离线成本(不影响查询延迟),在线收益巨大 │
│ - Databricks、Notion、Glean 等公司公开采用 │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ 第三层:前沿(头部 AI 公司/研究型系统在探索) │
│ │
│ 8. HyDE │
│ - 学术界验证有效,但工业界采用谨慎 │
│ - 问题:假设答案可能引入噪声/幻觉 │
│ - 适合:查询与文档表述差异大的场景 │
│ │
│ 9. FLARE (主动检索) │
│ - LLM 生成过程中判断是否需要补充检索 │
│ - 延迟较高,适合对质量要求极高的场景 │
│ │
│ 10. 多步迭代精炼 (Multi-Step Refinement) │
│ - LlamaIndex MultiStepQueryEngine │
│ - 适合复杂推理链场景 │
│ │
│ 11. 混合策略组合 │
│ - 意图识别 → 分解 → 改写 → 扩展 → HyDE → 检索 │
│ - 全链路优化,但延迟和成本是主要挑战 │
└─────────────────────────────────────────────────────────┘
工业界典型架构(以 LangChain/LlamaIndex 生态为例):
用户查询
│
├─→ [意图识别] 规则/Embedding 分类器(轻量,无 LLM)
│ ├─ 闲聊 → LLM 直接回答
│ └─ 知识查询 → 继续
│
├─→ [查询改写] LLM 指代消解(1次 LLM 调用)
│
├─→ [多查询生成] LLM 生成 3 个变体(1次 LLM 调用)
│ ├─ 变体1 → 向量检索
│ ├─ 变体2 → BM25 检索
│ └─ 变体3 → 向量检索
│
├─→ [RRF 融合] 纯数学合并(0次 LLM 调用)
│
├─→ [Reranker] Cross-Encoder 重排(0次 LLM 调用)
│
└─→ [生成] LLM 生成最终答案(1次 LLM 调用)
总计:3次 LLM 调用(改写1 + 多查询1 + 生成1)
这是工业界最常见的"性价比最优"配置
关键工程决策点:
| 决策点 | 选项 | 推荐 |
|---|---|---|
| 意图识别用 LLM 还是规则? | LLM 分类 vs 规则/Embedding | 规则/Embedding(延迟低,0 LLM 调用) |
| 改写和多查询是否都做? | 都做 vs 只做一个 | 都做(改写修正查询,多查询增加召回,解决不同问题) |
| HyDE 是否启用? | 启用 vs 不启用 | 看场景(查询-文档表述差异大时启用;差异小时多查询已足够) |
| 查询分解何时触发? | 总是 vs 条件触发 | 条件触发(简单查询不需要分解,用规则判断复杂度) |
| 索引阶段问题生成是否做? | 做 vs 不做 | 做(离线成本可控,在线收益巨大,ROI 最高之一) |
| 同义词用 LLM 还是词典? | LLM vs 词典 | 混合(通用词典做基础,LLM 做领域术语补充) |
六、补充:源码级验证与增量信息
工业界参考仓库确认
| 仓库 | Stars | 分类方式 |
|---|---|---|
| NirDiamant/RAG_Techniques | 29,391 | 社区最权威的 RAG 技术目录,42+ 可运行 notebook |
| athina-ai/rag-cookbooks | 2,572 | 高级 + Agentic RAG 技术表 |
| deepset-ai/haystack | 26,435 | 生产级 AI 编排框架,有独立的 query_expander 组件 |
RAG_Techniques 仓库自身的分类体系印证了上述分层:
Foundational 🌱 → 对应"标配"
Query Enhancement 🔍 → 对应查询改写/扩展/HyDE/多查询
Context Enrichment 📚 → 对应后处理阶段
Advanced Retrieval 🚀 → 对应"进阶"
Iterative Techniques 🔁 → 对应"前沿"(反馈循环/自适应/Self-RAG/CRAG)
Advanced Architecture 🏗️ → 对应"前沿"(GraphRAG/RAPTOR/Agentic RAG)
新增策略:Step-Back Prompting(后退提示)
RAG_Techniques 的 query_transformations.py 实现了三种查询转换策略,其中有一个上面未单独列出的:
python
class RAGQueryProcessor:
# 1. Query Rewriting - 重写为更具体/详细的查询
# 2. Step-Back Prompting - 生成更宽泛/抽象的查询(后退一步看大局)
# 3. Sub-Query Decomposition - 拆成2-4个子查询
Step-Back Prompting 是 Google Research (2023) 提出的技术:当用户问"某大学2024年CS专业录取分数线"时,生成一个后退查询"某大学历年各专业录取分数线趋势",用宽泛查询补充上下文。
- LLM 参与:✅ 需要
- 与查询改写的关系 :是查询转换的子类型,但方向相反------改写是更具体 ,Step-Back 是更宽泛
框架实现细节补充
LangChain 额外发现:
| 类 | 用途 | 文件 |
|---|---|---|
RePhraseQueryRetriever |
LLM 去除查询中的无关信息后重新表述 | retrievers/re_phraser.py |
create_history_aware_retriever() |
条件触发的查询改写------有 chat_history 才改写,没有则直接检索 | chains/history_aware_retriever.py |
DocumentCompressorPipeline |
可链式组合多个后处理器(如先过滤→再重排) | document_compressors/base.py |
LlamaIndex 额外发现:
| 类 | 用途 | 文件 |
|---|---|---|
DecomposeQueryTransform |
查询分解(基础版) | query_transform/base.py |
StepDecomposeQueryTransform |
多步分解(迭代版) | query_transform/base.py |
FeedbackQueryTransformation |
基于评估反馈的查询再生成 | query_transform/feedback_transform.py |
QuestionsAnsweredExtractor |
索引阶段问题生成的正式实现 | extractors/ (IngestionPipeline) |
Haystack 框架也有独立的查询扩展组件:
| 组件 | 文件 |
|---|---|
query_expander |
haystack/components/transformers/query_expander.py |
multi_query_embedding_retriever |
多查询+Embedding检索 |
multi_query_text_retriever |
多查询+文本检索 |
包含关系的源码级确认
LlamaIndex 的 BaseQueryTransform 类层次结构直接证明了包含关系:
python
# 源码证据:indices/query/query_transform/base.py
class BaseQueryTransform(PromptMixin, DispatcherSpanMixin):
"""Base class for query transform."""
class HyDEQueryTransform(BaseQueryTransform): # HyDE 是子类
class DecomposeQueryTransform(BaseQueryTransform): # 查询分解是子类
class StepDecomposeQueryTransform(BaseQueryTransform): # 多步分解是子类
class IdentityQueryTransform(BaseQueryTransform): # 恒等变换是子类(no-op)
# 源码证据:query_transform/feedback_transform.py
class FeedbackQueryTransformation(BaseQueryTransform): # 反馈变换是子类
LangChain 的 BaseDocumentCompressor 类层次结构证明了后处理的包含关系:
python
# 源码证据:document_compressors/__init__.py
__all__ = [
"CohereRerank", # Reranking 子类
"CrossEncoderReranker", # Reranking 子类
"EmbeddingsFilter", # 过滤子类
"FlashrankRerank", # Reranking 子类
"LLMChainExtractor", # 压缩子类
"LLMChainFilter", # 过滤子类
"LLMListwiseRerank", # Reranking 子类
"DocumentCompressorPipeline", # 管道(可链式组合以上所有)
]
工业界"标配配置"的源码级确认
LangChain 的 create_history_aware_retriever() 的条件触发逻辑印证了"查询改写是标配":
python
# 源码:chains/history_aware_retriever.py
def create_history_aware_retriever(llm, retriever, prompt):
retrieve_documents = RunnableBranch(
(lambda x: not x.get("chat_history", False),
(lambda x: x["input"]) | retriever), # 无历史 → 直接检索(省 LLM 调用)
prompt | llm | StrOutputParser() | retriever, # 有历史 → LLM 改写后检索
)
这证明工业界的标配做法是:有对话历史才改写,没有则跳过------精确控制 LLM 调用成本。
七、总结速查表
| 策略 | 阶段 | LLM | 1→1/1→N | 解决的核心问题 | 工业界采用度 |
|---|---|---|---|---|---|
| 查询改写 | 查询 | ✅ | 1→1 | 指代消解/口语规范化 | ⭐⭐⭐⭐⭐ 标配 |
| 查询扩展 | 查询 | ⚠️ | 1→N | 召回率不足 | ⭐⭐⭐⭐ 广泛 |
| 同义词扩展 | 查询 | ⚠️ | 1→N(词) | 术语不匹配 | ⭐⭐⭐ 常见 |
| 多查询生成 | 查询 | ✅ | 1→N(句) | 召回率/视角覆盖 | ⭐⭐⭐⭐⭐ 标配 |
| 查询分解 | 查询 | ✅ | 1→N(子) | 复杂推理 | ⭐⭐⭐⭐ 进阶 |
| HyDE | 查询 | ✅ | 1→1(答案) | 查询-文档语义鸿沟 | ⭐⭐⭐ 前沿 |
| 索引问题生成 | 索引 | ✅ | 1→N(问) | 查询-文档语义鸿沟 | ⭐⭐⭐⭐ 进阶 |
| 意图识别 | 查询 | ⚠️ | 1→1(路由) | 路径选择 | ⭐⭐⭐⭐⭐ 标配 |
附:关键论文与参考
| 论文/来源 | 技术覆盖 | 关键发现 |
|---|---|---|
| "Query Rewriting in Retrieval-Augmented Generation" (Microsoft, 2023) | 查询改写 | LLM 改写比原始查询提升 15-25% 召回率 |
| "HyDE: Precise Zero-Shot Dense Retrieval without Real Labels" (Gao et al., 2023, arXiv:2212.10496) | HyDE | 假设文档 Embedding 优于查询 Embedding |
| "Multi-Query Retrieval" (LangChain docs) | 查询扩展 | 多查询+RRF 提升召回率且不损失精度 |
| "FLARE: Forward-Looking Active Retrieval" (Jiang et al., 2023) | FLARE | 主动检索优于固定检索-生成 |
| "Query2doc: Query Expansion with LLMs" (Wang et al., 2023) | 查询扩展 | LLM 扩展优于静态词典扩展 |
| "RAG vs Fine-tuning" (Meta, 2024) | 通用 RAG | 查询优化是 RAG 最高 ROI 的改进 |
| LlamaIndex Documentation (docs.llamaindex.ai) | 全部技术 | QueryFusionRetriever, SubQuestionQueryEngine, HyDEQueryTransform 等 |
| LangChain Documentation (python.langchain.com) | 多查询, HyDE | MultiQueryRetriever, EnsembleRetriever 等 |
| NirDiamant/RAG_Techniques (GitHub, 29K stars) | 全部技术 | 42+ 可运行 notebook,社区最权威 RAG 技术目录 |