--- title: RAG学习篇:Query Transformation 查询改写,让烂问题也能找到好答案 date: 2026-04-24 15:30:00 author: Gamehu tags: - RAG - Query Transformation - 查询改写 - 检索优化 categories: - AI ---
RAG Query Transformation 查询优化
这是之前学习 RAG 时整理的学习篇。用户问的问题往往很烂——要么太泛(「Python 教程」),要么太绕(「那个什么什么...」),Query Transformation 就是解决这个问题的:把烂问题改写成好问题,检索效果直接翻倍
## 一、为什么需要 Query Transformation ### 1.1 用户的提问有多不靠谱 做 RAG 的时候你会发现,**用户的问题质量参差不齐**: - 太宽泛:「讲讲 Python」——讲什么?基础语法?进阶特性?Web 开发?数据分析? - 太模糊:「那个东西怎么用」——哪个东西?怎么用? - 有歧义:「Java 的继承」——是说 `extends` 继承父类?还是 `implements` 实现接口?还是组合优于继承(composition over inheritance)的重构方向? - 有拼写错误:「Pythno 教程」——搜索引擎能纠错的还好,向量检索直接傻眼 - 太专业/太口语:「怎么让模型过拟合」——过拟合通常是负面词,但用户想问的是「怎么在特定领域微调」
**核心痛点**:用户的问题 ≠ 文档里的表达方式。 用户问「Python 教程」,文档里可能写的是「Python 3.9 入门指南」。字面完全不同,但语义相关。这就是 Query Transformation 要解决的问题。 ### 1.2 Query Transformation 的本质 用一句话概括:
把用户原始查询,改写成更容易在向量空间里找到相关内容的形式。
改写可以是: - 扩展(加同义词、相关概念) - 分解(把复杂问题拆成多个子问题) - 重构(换个问法,更接近文档的表达方式) - 生成(直接生成一个「理想答案」的草稿去搜——这就是 HyDE) ## 二、常见的 Query Transformation 方法 ### 2.1 方法对比总览 | 方法 | 原理 | 优点 | 缺点 | 适用场景 | |------|------|------|------|----------| | HyDE | 生成假设文档再编码 | 零样本、效果好 | 需要 LLM、有延迟 | 问答式、语义模糊 | | Query Expansion | 扩展同义词/相关词 | 简单、成本低 | 扩展质量不稳定 | 通用场景 | | Step-back Prompting | 退一步问更抽象的问题 | 能召回更相关的背景知识 | 可能召回过多无关内容 | 需要背景知识的复杂问题 | | 子查询分解 | 把复杂问题拆成多个子问题 | 适合复杂多跳问题 | 流程复杂、成本高 | 复杂推理问题 | | RAG-Fusion | 生成多个查询取并集 | 召回更全面 | 计算成本高 | 对召回率要求高的场景 |
### 2.2 HyDE(Hypothetical Document Embeddings) HyDE 是 Query Transformation 里最有意思的方法,本系列下一篇会专门深入讲,这里先把核心思路说清楚。 **核心思想**:与其纠结怎么优化问题,不如直接生成一个「理想答案」,然后用这个答案去搜。
用户问题 → LLM 生成假设文档 → 编码 → 检索真实文档
**什么时候用**: - 用户问题很短(1-3 个词),语义太泛 - 用户不知道怎么表达,需要「补全」语义 - 你试过其他方法,效果都不够好 ### 2.3 Query Expansion(查询扩展) 最传统、最轻量的方法。 **原理**:给原始查询加同义词、相关词,扩大检索范围。 **举个例子**:
原始查询:Python 教程
扩展后:Python 教程 入门 基础 学习 guide tutorial
**实现方式**: 1. 基于词典:用 WordNet、同义词词典人工维护 2. 基于模型:用 LLM 生成相关词(轻量版) **Prompt 示例**:
请为以下查询生成 3-5 个相关的搜索词,用逗号分隔:

查询:{query}

相关搜索词:
**优点**: - 实现简单,几乎零成本 - 不需要额外模型(如果用词典)或小模型(如果用 LLM 扩展) - 稳定性高 **缺点**: - 扩展质量依赖词典或模型能力 - 可能引入不相关的词(比如「Python」扩展到「蟒蛇」)
我的经验:Query Expansion 是性价比最高的第一步优化。先把这个做好,再考虑更复杂的方法。
### 2.4 Step-back Prompting(退一步提问) 这个方法来自 Google DeepMind 的论文《[Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models](https://arxiv.org/abs/2310.06117)》(Zheng et al., 2023),思路很有意思。 **核心思想**:当问题太具体时,退一步问更抽象、更通用的问题,先召回背景知识,再用背景知识辅助回答具体问题。 **举个例子**: | 原始问题 | Step-back 问题 | 召回内容 | |----------|---------------|----------| | 「Transformer 的注意力机制在医疗文本上怎么优化」 | 「Transformer 注意力机制是什么」 | 基础原理 | | 「React useEffect 依赖数组问题」 | 「React useEffect 是什么」 | useEffect 文档 | **Prompt 示例**:
你是一个问题改写助手。用户的问题是具体的,你需要生成一个更通用、更抽象的问题,用于检索背景知识。

用户问题:{query}

请生成一个更通用的背景问题:
**什么时候用**: - 问题很具体,需要背景知识才能理解 - 用户问的是某个领域的专业问题,但知识库里有更基础的解释 **注意事项**: - Step-back 可能会召回太多无关内容 - 建议配合 Reranker 使用,先召回更多,再精确排序 ### 2.5 子查询分解(Sub-query Decomposition) 适合那种「一步问完但其实包含多个问题」的复杂查询。 **举个例子**:
原始问题:「怎么在 Kubernetes 上部署一个带数据库的 Web 应用,还要配置 SSL」

子查询 1:Kubernetes 部署 Web 应用
子查询 2:Kubernetes 部署数据库
子查询 3:Kubernetes 配置 SSL 证书
**实现方式**: 1. 用 LLM 分析问题包含哪些子问题 2. 对每个子问题分别检索 3. 合并所有检索结果作为上下文 **Prompt 示例**:
请将以下复杂问题分解成 2-4 个更简单的子问题。每个子问题应该独立可回答。

原始问题:{query}

子问题:
1.
2.
3.
**优点**: - 每个子问题更精准,检索质量更高 - 适合复杂的多跳推理问题 **缺点**: - 需要多次检索,成本翻倍 - 合并策略需要设计(简单拼接还是智能合并)
什么时候用:当用户问题明显包含多个子任务时(「怎么实现 A 同时还要 B 和 C」),分解后效果更好。
### 2.6 RAG-Fusion RAG-Fusion 由 Zackary Rackauckas 在 2024 年提出([arXiv:2402.03367](https://arxiv.org/abs/2402.03367)),核心融合算法 RRF(Reciprocal Rank Fusion)则来自 Cormack 等人 2009 年的 SIGIR 论文。思路是:一个查询不够,我生成多个查询。 **流程**:
原始查询 → LLM 生成 5 个相关查询 → 分别检索 → 用 RRF 融合结果 → Top-K 返回
**Prompt 示例**:
请根据以下查询,生成 5 个不同角度但相关的查询。每个查询应该能检索到相关的补充信息。

原始查询:{query}

相关查询:
1.
2.
3.
4.
5.
**RRF 融合公式**:
RRF 分数 = Σ 1 / (k + rank_i)
简单说就是:一个文档在多个查询的结果里排名越高,最终分数越高。 **优点**: - 召回更全面,不容易漏掉相关内容 - 多个角度覆盖,减少 query 表述差异的影响 **缺点**: - 需要多次检索,成本高 - 需要调 RRF 的参数 k ## 三、方法选择决策树 这么多方法,怎么选?
### 决策流程:
用户问题质量如何?
├── 问题清晰、具体 → 直接用原始查询
│
├── 问题太泛/太短 → Query Expansion 或 HyDE
│   ├── 延迟敏感 → Query Expansion
│   └── 追求效果 → HyDE
│
├── 问题太复杂/多条件 → 子查询分解
│
├── 需要背景知识 → Step-back Prompting
│
└── 召回率不够 → RAG-Fusion(多查询生成)
### 我的建议:渐进式优化 不要一上来就搞最复杂的方法。建议这个顺序: | 阶段 | 方法 | 预期收益 | 成本 | |------|------|---------|------| | 第一阶段 | 原始查询 + 好的 Embedding 模型 | 60% | 低 | | 第二阶段 | + Query Expansion | 70% | 很低 | | 第三阶段 | + Reranker(Cross-Encoder) | 80% | 中 | | 第四阶段 | + HyDE / Step-back / RAG-Fusion | 85-90% | 高 |
关键洞察:80% 的收益来自前三个阶段。HyDE 这类高级方法是为了最后那 10% 的提升,但成本和复杂度会显著增加。先跑基线,再决定是否需要。
## 四、生产落地的实战经验 ### 4.1 延迟优化 Query Transformation 最大的问题是增加了延迟: - Query Expansion:几毫秒(如果用词典)到几百毫秒(如果用 LLM) - HyDE:几百毫秒到几秒(取决于 LLM) - RAG-Fusion:查询数 × 单次检索时间 **优化策略**: 1. 分层缓存 - 高频查询的改写结果缓存 - 低频查询走原始查询 2. 并行执行 - RAG-Fusion 的多个查询并行检索 - 子查询分解的多个查询并行处理 3. 降级策略 - LLM 超时或失败时,回退到原始查询 - 设置改写质量的阈值,质量不够就回退 4. 小模型替代 - HyDE 的假设文档生成不需要大模型,用 GPT-3.5 级别的小模型替代 GPT-4,延迟可以降低 3-5 倍,效果损失在可接受范围内 ### 4.2 改写质量评估 怎么知道改写有没有变好? 离线评估: - 准备一批测试查询和期望的相关文档 - 对比改写前后的 Recall@K、Precision@K、MRR 在线评估: - A/B 测试:一部分用户走改写,一部分走原始 - 观察下游指标:回答的点击率、满意度、任务完成率
避坑提醒:Query Transformation 可能导致「改写后召回的文档更相关,但 LLM 生成的答案反而更差」的情况。一定要评估端到端的效果,不要只看检索指标。
### 4.3 常见坑 | 坑 | 表现 | 解决 | |----|------|------| | 改写过度 | 原始查询很清晰,改写后反而引入无关词 | 设置改写置信度阈值 | | 改写跑偏 | 改写后的查询偏离了用户真实意图 | 用原始查询兜底 | | 多语言问题 | 用户用中文问,改写成英文后检索不到中文文档 | 按语言分别处理或混合检索 | | 领域适配 | 通用改写策略在专业领域效果差 | 用领域特定词典或微调 | ## 五、Prompt 工程技巧 ### 5.1 通用原则 1. 明确输出格式:告诉模型你要什么格式的输出 2. 加示例(few-shot):给 1-2 个例子,模型学得更快 3. 约束条件:限制输出的长度、风格、范围 ### 5.2 示例:带 few-shot 的 Query Expansion Prompt
你是一个查询扩展助手。请为用户的查询生成 3-5 个相关的搜索词,帮助检索更多相关内容。

示例 1:
查询:Python 教程
扩展:Python 入门, Python 基础, Python 学习指南, Python 编程, Python 3.9

示例 2:
查询:Kubernetes 部署
扩展:K8s 部署, Kubernetes 安装, Kubernetes 集群搭建, Docker 容器编排

用户查询:{query}

请生成扩展词(用逗号分隔):
### 5.3 示例:子查询分解 Prompt
请将以下复杂问题分解成 2-4 个更简单的子问题。每个子问题应该独立可回答。

示例:
原始问题:「怎么在 AWS 上部署一个高可用的 Web 应用,还要配置负载均衡和自动扩缩容」
子问题:
1. AWS 上如何部署 Web 应用
2. AWS 负载均衡器(ELB)如何配置
3. AWS 自动扩缩容(Auto Scaling)如何设置
4. AWS 高可用架构设计

原始问题:{query}

子问题:
1.
2.
3.
4.
## 六、总结 Query Transformation 是 RAG 检索优化的核心手段,但不是银弹
核心观点: 1. 先跑基线,知道当前问题在哪 2. 从轻量方法(Query Expansion)开始,逐步迭代 3. 高级方法(HyDE、RAG-Fusion)是为了最后 10% 的提升,成本和复杂度会显著增加 4. 一定要评估端到端效果,不要只看检索指标 5. 改写可能跑偏,一定要有降级策略
最后送大家一句话:用户的烂问题不是你的错,但如果检索不到答案,那就是你的问题了。Query Transformation 就是来解决这个问题的。 --- ## 参考资源 **论文原文**: - **HyDE**:Gao, L., Ma, X., Lin, J., & Callan, J. (2022). [Precise Zero-Shot Dense Retrieval without Relevance Labels](https://arxiv.org/abs/2212.10496). arXiv:2212.10496. - **Step-back Prompting**:Zheng, H., Mishra, S., Chen, X., et al. (2023). [Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models](https://arxiv.org/abs/2310.06117). arXiv:2310.06117. Google DeepMind. - **RAG-Fusion**:Rackauckas, Z. (2024). [RAG-Fusion: a New Take on Retrieval-Augmented Generation](https://arxiv.org/abs/2402.03367). arXiv:2402.03367. - **RRF(基础算法)**:Cormack, G. V., Clarke, C. L. A., & Büttcher, S. (2009). [Reciprocal Rank Fusion outperforms Condorcet and Individual Rank Learning Methods](https://dl.acm.org/doi/10.1145/1571941.1572114). SIGIR 2009. **官方实现参考**: - LangChain:[Query Transformations 官方博客](https://www.langchain.com/blog/query-transformations)(含 MultiQueryRetriever 使用说明) - Haystack:[Advanced RAG: Query Expansion](https://haystack.deepset.ai/blog/query-expansion)(实现细节清晰,工程向) - RAG-Fusion GitHub 实现:[Raudaschl/rag-fusion](https://github.com/Raudaschl/rag-fusion)