Agent中RAG检索增强:5种Query Enhancement方法详解与实现
Agent中RAG检索增强:5种Query Enhancement方法详解与实现
在RAG系统中,用户提问的质量直接影响检索效果。本文详解5种查询增强方法:HyDE、Query Rewriting、Multi-Query、Step-back Prompting和Query Expansion,
一、为什么需要查询增强?
在实际的RAG系统中,我们经常遇到这样的痛点:
| 痛点 | 症状 | 影响 |
|---|---|---|
| 检索召回率低 | 只用用户原问题检索 | 漏掉相关文档 |
| 用户表达口语化 | “咋整RAG” 搜不到文档 | 术语不匹配 |
| 问题太短/太模糊 | 缺少上下文信息 | 检索范围过大 |
| 单一策略 | 只有一种检索方式 | 无法适应不同场景 |
查询增强(Query Enhancement)的核心思想是:不要直接用用户原问题检索,而是先对问题进行改写、扩展或拆分,再用增强后的问题检索。
二、5种增强方法对比
| 方法 | 原理 | 适用场景 | LLM成本 |
|---|---|---|---|
| HyDE | LLM生成假设答案,用答案检索 | 概念性问题、需要背景知识 | 1次调用 |
| Query Rewriting | 改写成更清晰专业的形式 | 口语化、太短的问题 | 1次调用 |
| Multi-Query | 拆成3-5个不同角度问题 | 模糊问题、追求高召回 | 1次调用 |
| Step-back | 先问抽象大问题获取背景 | 有具体细节但缺背景 | 1次调用 |
| Expansion | 补充同义词/相关关键词 | 缺少专业术语 | 1次调用 |
下面逐一详解每种方法的原理和实现。
三、HyDE:假设文档嵌入
3.1 原理
HyDE(Hypothetical Document Embeddings)的核心思想是:让LLM生成一个假设答案,然后用这个假设答案去检索。
为什么这样做有效?因为文档库中的内容是"专业表达",而用户问题往往是"口语化表达"。假设答案的表达方式更接近文档,因此检索命中率更高。
3.2 流程图
用户问: "RAG 最新进展" ↓ LLM生成假设答案 ↓ 假设答案: "RAG最新进展包括:GraphRAG用知识图谱增强...ColPali直接向量PDF..." ↓ 用假设答案做向量检索 ↓ 命中率大幅提升!3.3 Prompt模板
请针对以下问题生成一个详细的假设答案: {query} 答案应该包含专业术语和关键概念。3.4 适用场景
- 用户问的是概念性问题(如"什么是…")
- 需要背景知识才能检索
- 问题表达方式与文档差异大
3.5 缺点
- 需要1次LLM调用,增加延迟(约1-2秒)
- 如果LLM生成的内容偏离事实,可能引入噪声
四、Query Rewriting:问题改写
4.1 原理
用户的表达往往不规范、不专业。Query Rewriting就是让LLM把用户问题改写成更清晰、更专业的表达。
4.2 流程图
用户问: "咋整RAG" ↓ LLM改写 ↓ 改写后: "RAG(检索增强生成)系统的实现方案和技术架构" ↓ 用改写后的问题检索 ↓ 更精准的检索结果!4.3 Prompt模板
请将以下用户问题改写为更清晰、更专业的表达: 原问题:{query} 改写要求: 1. 保留原问题的核心意图 2. 使用更专业的术语 3. 补充必要的上下文 改写后的问题:4.4 适用场景
- 用户表达口语化(如"咋整"、“怎么搞”)
- 问题太短(少于10个字)
- 非专业用户提问专业内容
五、Multi-Query:多角度拆分
5.1 原理
一个模糊的问题,从不同角度可能有不同的理解。Multi-Query的核心思想是:把一个问题拆成3-5个不同角度的问题,分别检索,然后合并去重。
5.2 流程图
用户问: "怎么优化RAG" ↓ LLM拆分 ↓ 多角度问题: 1. "RAG检索质量如何提升" 2. "RAG召回率优化方法" 3. "RAG准确率提升技术" 4. "检索增强生成的最佳实践" ↓ 分别检索4个问题 ↓ 合并结果,去重 ↓ 大幅提高召回率!5.3 Prompt模板
请将以下问题拆分为3-5个不同角度的问题: 原问题:{query} 拆分要求: 1. 每个问题从不同角度切入 2. 使用不同的关键词和表达方式 3. 保持原问题的核心意图 拆分后的问题列表:5.4 适用场景
- 问题比较模糊,可以有多种理解
- 追求高召回率(宁可多,不可漏)
- 单一检索策略效果不佳
5.5 实现要点
// Multi-Query需要分别检索再合并asyncfnmulti_query_search(&self,queries:Vec<String>,top_k:usize)->Vec<SearchResult>{letmutall_results=Vec::new();// 分别检索forqueryinqueries{letresults=self.vector_store.search(&query,top_k).await;all_results.extend(results);}// 合并去重(按document_id)self.merge_and_dedupe(all_results)}六、Step-back Prompting:后退一步
6.1 原理
用户的问题往往太具体,缺乏必要的背景知识。Step-back Prompting的核心思想是:先问一个更抽象、更宏观的问题,获取背景知识,再回答具体问题。
6.2 流程图
用户问: "2024年3月北京气温数据" ↓ LLM生成Step-back问题 ↓ Step-back问题: "北京春季气候特点和温度规律" ↓ 先检索背景知识 ↓ 获得背景信息 ↓ 再回答具体问题6.3 Prompt模板
原问题:{query} 请生成一个更抽象、更宏观的Step-back问题: - 这个问题应该能帮助获取回答原问题所需的背景知识 - 问题应该比原问题更宽泛 Step-back问题:6.4 适用场景
- 用户问的是具体细节,但缺乏背景
- 问题包含具体时间、地点、人物
- 需要先理解宏观概念才能回答
七、Query Expansion:关键词扩展
7.1 原理
用户的问题可能缺少专业术语,导致检索不到相关文档。Query Expansion的核心思想是:用LLM补充同义词、相关关键词。
7.2 流程图
用户问: "向量检索怎么做" ↓ LLM扩展关键词 ↓ 扩展后: "向量检索 embedding 相似度 ANN Qdrant Milvus Faiss" ↓ 用扩展后的关键词检索 ↓ 补充专业术语,命中更多文档!7.3 Prompt模板
请为以下问题补充相关的专业术语和关键词: 原问题:{query} 扩展要求: 1. 添加同义词 2. 添加相关的技术术语 3. 添加可能用到的工具/库/框架名称 扩展后的查询:7.4 适用场景
- 用户表达缺少专业术语
- 文档库使用专业表达,用户使用通俗表达
- 需要覆盖更多关键词变体
八、智能策略选择
不同的问题适合不同的增强策略。我们可以根据问题特征,自动选择最合适的策略:
pubfnauto_select_strategy(query:&str)->EnhanceStrategy{letlen=query.len();lethas_time_detail=query.contains("年")||query.contains("月");letis_short=len<20;lethas_terms=query.contains("RAG")||query.contains("向量");ifhas_time_detail&&!has_terms{// 具体问题但缺背景 → Step-backEnhanceStrategy::StepBack}elseifis_short&&!has_terms{// 太短且口语化 → RewriteEnhanceStrategy::Rewrite}elseiflen>50&&!has_terms{// 长但缺术语 → ExpansionEnhanceStrategy::Expansion}elseifquery.contains("最新")||query.contains("趋势"){// 需要背景知识 → HyDEEnhanceStrategy::Hyde}else{// 默认 → MultiQuery(召回率高)EnhanceStrategy::MultiQuery}}策略选择测试用例
| 输入问题 | 自动选择策略 | 原因 |
|---|---|---|
| “咋整RAG” | Rewrite | 太短且口语化 |
| “怎么优化检索” | MultiQuery | 默认,高召回 |
| “2024年RAG进展” | HyDE | 包含"最新"关键词 |
| “3月北京天气” | StepBack | 具体时间,缺背景 |
| “向量检索” | Expansion | 缺少专业术语 |
九、性能与成本对比
| 策略 | LLM调用 | 增加延迟 | 适用频率 | 推荐场景 |
|---|---|---|---|---|
| HyDE | 1次 | 1-2秒 | 低频 | 复杂概念问题 |
| Rewrite | 1次 | 0.5秒 | 中频 | 口语化问题 |
| MultiQuery | 1次 | 1秒 | 中频 | 模糊问题 |
| StepBack | 1次 | 0.5秒 | 低频 | 具体细节问题 |
| Expansion | 1次 | 0.5秒 | 高频 | 缺术语问题 |
| None | 0次 | 0秒 | 高频 | 简单明确问题 |
建议:
- 默认使用
auto自动选择 - 对延迟敏感的场景可以设置阈值,简单问题跳过增强
- 可以缓存增强结果,相同问题不重复调用LLM
十、总结
查询增强是提升RAG检索效果的重要手段。5种方法各有侧重:
| 方法 | 核心价值 | 一句话总结 |
|---|---|---|
| HyDE | 拉近用户表达与文档表达的距离 | 用假设答案检索 |
| Rewrite | 规范化用户表达 | 口语变专业 |
| MultiQuery | 多角度覆盖 | 一个不够,来一群 |
| StepBack | 补充背景知识 | 后退一步,海阔天空 |
| Expansion | 补充专业术语 | 关键词加一加 |
在实际应用中,建议:
- 默认开启自动选择,让系统智能判断
- 提供手动选择入口,让用户根据需要切换
- 监控增强效果,持续优化策略选择逻辑
- 控制成本,对简单问题可以跳过增强
参考资料
- HyDE论文
- Multi-Query Retriever (LlamaIndex)
- Step-back Prompting (Google)
- Query Expansion (Stanford IR Book)
https://github.com/atliliw/langchainrust.git
相关项目:LangChainRust Agent - Rust实现的RAG系统
