RAG 中为什么要做查询改写?Multi-Query 和 HyDE 分别适合什么场景?
简化版
用户问题常过短、含代词、与文档表达不一致,查询改写会补全上下文、扩展同义表达或拆解子问题来提高召回。Multi-Query 生成多个不同角度的查询、分别召回再融合;HyDE 先让模型生成一段假想答案文档,再用它的向量检索真实文档,适合「查询与文档表述差距大」的零样本语义检索。铁律——改写文本不能当事实来源,要保留原查询一路兜底。
详细版
常见查询优化:
- 对话改写:把「它支持多久?」改成含历史实体的独立问题;
- 同义扩展:补缩写、术语、可能的文档用词;
- Multi-Query:生成多个语义角度查询,分别召回后去重融合;
- 问题分解:把多跳问题拆成可检索子问题;
- HyDE:生成假想相关文档,用它的 Embedding 作检索向量。
改写目标是提高召回,不是越长越好。LLM 可能引入错误实体或偏离意图,所以要保留原查询一路召回 + RRF + 重排 + 评估控风险。
完整版教学
一、原始查询为什么不适合直接检索
真实用户会说「这个怎么收费」「上一条里的接口支持吗」——充满省略、指代、口语;知识库却用正式术语。Embedding 能处理部分同义,但不能可靠恢复缺失实体;BM25 更依赖字面词。
用户:"它支持多久?"("它"指上一轮说的"XX 电池")
直接检索 → "它支持多久" 语义空洞,召回一堆无关内容
对话改写 → "XX 电池的续航支持多久?" → 召回准确
查询改写先把用户意图转成适合检索的独立表达,同时保留时间/产品/版本/权限等约束。多轮对话里的指代补全怎么做,见「多轮对话里用户问“那它呢”,RAG 检索前怎么做指代消解?」。
二、Multi-Query 如何提高召回
同一问题有多种表达,Multi-Query 让模型生成若干互补查询(如从定义、原因、操作步骤三个角度),各自召回再去重融合,降低「单一表述未命中」的风险:
原问题:"怎么解决登录失败"
→ 生成:① 登录失败的常见原因
② 登录报错的排查步骤
③ 账号无法登录怎么办
→ 三路各召回 → RRF 融合去重
代价:检索次数、延迟、噪声增加。若生成的查询只是换几个同义词,信息增益很小;若偏离原意,会引入错误候选。
三、扩展时哪些信息必须原样保留
Multi-Query 和同义扩展最大的风险是改丢约束。产品号、姓名、日期、否定词、地域和权限条件都是硬约束:把「不是 Windows 的安装问题」扩展成「Windows 安装问题」,召回的就是相反的证据。稳妥的做法是扩展前先抽出这些关键信息,要求原样保留,或者干脆以结构化条件交给检索器,只让模型改写语义部分:
{
"semantic_query": "登录失败如何处理",
"must_terms": ["ZX-1049"],
"must_not": ["Windows"],
"filters": {"product": "mobile", "valid_at": "2026-09-18"}
}
另一个风险是语义漂移:模型可能把「苹果账户」扩成水果种植。控制手段有三个:扩展条数限制在 2~4 条,并要求「互补但等价」;扩展结果和原查询的相似度、实体是否一致过一遍检查,偏得太远就丢掉;原查询单独作为一路召回,最终重排只按原始问题打分。对编号、型号这类高风险的精确查询,可以完全不做生成式扩展,只用别名词典和拼写纠正。
四、HyDE 的工作原理(反直觉但巧妙)
HyDE = Hypothetical Document Embeddings。它不直接嵌入短查询,而是先让 LLM 写一段「可能的相关文档」,再嵌入这段假想文档去检索:
查询:"量子纠缠的应用"(很短,和文档语言形式差距大)
HyDE:先让 LLM 写一段"关于量子纠缠应用的文档"(假想,可能有错)
→ 嵌入这段假想文档 → 它的语言形式更接近真实文档 → 检索到真实证据
关键理解:假想文档可能含错误事实,但它的”语言形式和相关模式”更接近真实文档。HyDE 靠稠密编码器的表示瓶颈,从假想内容附近检索真实证据——不是把假想内容当答案。
五、HyDE 的适用边界
| 适合 | 谨慎使用 |
|---|---|
| 查询非常短、缺与文档相似的表达 | 精确编号/日期/实体查询 |
| 没有相关性标注、难训练专用 Retriever | 生成模型容易改错关键约束 |
| 概念性、描述性问题 | 延迟预算严格 |
对「查询错误码 E1047」这种,HyDE 反而可能把关键约束改错——精确查询用 BM25 更稳。
六、问题分解适合多跳查询
"A 产品负责人所在部门今年有哪些项目?"
→ 单轮向量查询往往难以同时召回"负责人→部门→项目"三跳各自的证据
→ 分解:① A 的负责人是谁 → ② 此人在哪个部门 → ③ 该部门今年项目
每步用上一步提取的实体做下一跳
分解错误会逐步传播,所以要保存每步证据,允许证据不足时回退或改写(详见多跳专题)。
HyDE 生成的是检索用中间表示,不是可引用事实;它可以改善语义邻近,也可能把错误假设带入召回,必须与原查询和真实证据共同验收。
七、常见误区与追问
- 误区:查询改写越长越好。 目标是提高召回,改写太长/偏离意图反而引入错误候选。
- 误区:改写后就不要原查询了。 多查询扩展和 HyDE 都要保留原查询一路召回兜底,防模型改错;指代消解是例外,「那超期了呢」这类原句本身没有信息量,保留它只会引入噪声。
- 误区:HyDE 把假想文档当答案。 假想文档只用于检索定位真实证据,答案必须基于真实文档。
- 误区:HyDE 适合所有查询。 精确编号/日期/实体查询容易被改错,用 BM25 更稳。
- 追问:Multi-Query 怎么提召回? 生成多个互补角度查询分别召回再融合,降低单一表述未命中风险,代价是延迟和噪声。
- 追问:HyDE 为什么有效? 假想文档的语言形式比短查询更接近真实文档,从它附近检索真实证据。
- 追问:多跳为什么常要问题分解? 单轮检索难同时召回各跳证据,可拆成有依赖的子问题逐步检索。
- 追问:查询改写怎么控风险? 保留原查询、限制生成数量和可改写实体、RRF 融合、重排、记录改写便于排障、用真实问题评估。
八、加强记忆
查询改写记「优化『怎么找』,不改『事实来源』」:对话改写把话说完整、Multi-Query 换角度找(多查询融合)、问题分解分步找(多跳)、HyDE 先写”理想资料画像”再找真资料。核心认知钉死:改写目标是提召回不是越长越好、必须保留原查询兜底、HyDE 的假想文档只用于检索定位不当答案、精确编号查询别用 HyDE(易改错约束用 BM25)。LLM 会引入错误实体,所以要 RRF + 重排 + 评估控风险,最终答案永远基于知识库真实证据。
项目实战落地
项目里怎么做的
《AI Agentic RAG高级企业知识库平台》实现了三种改写方式,在检索策略里通过 rewrite_type 选择其一:
- 多查询扩展。 用
QUERY_REWRITE模板让模型把问题改写成若干条说法不同、意思相同的问题,预置策略扩展 3 条,上限 5 条;返回列表的第一条永远是原问题。每条查询在向量和 BM25 两路上各召回一份榜单,最后统一做 RRF 融合。 - 指代消解。 把最近几轮对话拼成「用户:…… / 助手:……」交给模型,补全当前这句话;没有历史时直接返回原句,不白调一次模型。
- HyDE。 用
HYDE_ANSWER模板让模型「用企业文档的书面语气写一段可能的答案,不需要保证内容正确,控制在 150 字以内」,再把原问题拼在假答案前面一起拿去检索。
模型返回空内容时,三种方式都退回原问题,不让检索拿空字符串去跑。
为什么这样取舍
- 原问题始终保留。 改写是为了增加命中机会,不是替换用户的表达,万一模型改写跑偏,原问题这一路还在。
- HyDE 把原问题拼在假答案前面。 假答案带来文档腔的用词,原问题保留用户的真实意图,两者合在一起检索更稳。
面试官还会追问
- 三种改写方式为什么在策略里只能选一种,不能叠加着开?
- 开了查询改写之后,召回和精度各提升了多少、每次问答多花了多少时间?这笔账怎么算?
学完《AI Agentic RAG高级企业知识库平台》,上面这些追问你都会迎刃而解。