✍️ Query Rewrite:弥合提问与文档的鸿沟
用户口语化、文档书面化,向量相似度天然偏低。四种改写方法各治一种「鸿沟」。
为什么需要 Query Rewrite
🗣️ 天然的表达鸿沟
用户问「这东西坏了咋整」,文档写的是「产品故障排查与维修指南」。
即便语义相关,口语和书面语在向量空间里的坐标差距不小,相似度可能低到召回不了正确文档。
🎯 核心目的
弥补用户提问方式和知识库文档表述之间的语义鸿沟。
用户问题往往口语化、模糊、带缩写、有指代;文档是正式书面语。
鸿沟有不同形态,需要不同方法对付。
方法一:直接改写
✍️ 直接改写
把口语化、模糊的问题改写成更精准、更书面化的检索表述。
消除口语化和知识库表述之间的向量距离。
「上次说的那个退款的事,流程是啥」→「申请商品退款的完整操作流程是什么」
⚖️ 优缺点
优点:简单直接,多轮对话中效果明显(能补全指代「那个」「上次」)。
局限:问题和文档是不同文体(疑问句 vs 陈述句),改写无法消除文体差异。
方法二:HyDE
🧪 假设答案做向量
HyDE(Hypothetical Document Embeddings):先让 LLM 根据问题生成一段「假设答案」,再用这段答案的向量去检索。
假设答案不需要准确,只需要「风格像文档」就够了。
💡 为什么有效
在向量空间里,答案到答案的距离比问题到答案的距离近得多。
假设答案的作用不是回答问题,而是扮演文档的角色。
问题「退款政策是什么」和文档「申请售后退款须知」距离远;假设答案「用户可在购买后 14 天内申请退款…」和文档距离近。
方法三、四:Step-back 与多 Query
🪜 ③ Step-back Prompting
把具体问题「后退一步」,提升到更抽象的层次,先检索背景知识,再结合背景回答。
像做数学题先想「这道题用的是哪种定理」。
「Qdrant 的 HNSW ef 参数设多少合适」→「HNSW 索引的参数调优原则是什么」
🔀 ④ 多 Query 扩展
把原始问题改写成 3-5 个不同角度的版本,分别检索,然后合并去重。
只要有一个改写版本和文档表述对上,就能召回正确内容。
代价:多次 LLM 调用。适合答案涉及多个维度的复杂问题。
四种方法怎么选
| 方法 | 解决的核心问题 | 额外开销 | 适合场景 |
|---|---|---|---|
| 直接改写 | 口语化、指代不清、上下文丢失 | 1 次 LLM | 多轮对话场景 |
| HyDE | 问题和文档文体风格差异大 | 1 次 LLM | 专业知识库、文体差异明显 |
| Step-back | 具体问题需要背景知识辅助 | 1 次 LLM | 技术文档、需原理支撑 |
| 多 Query 扩展 | 单一角度覆盖不全 | N 次 LLM | 答案涉及多维度复杂问题 |
口语化 → 直接改写
补全指代、口语转书面,最简单直接。
文体差异 → HyDE
假设答案扮演文档角色,缩短向量距离。
问题太具体 → Step-back
抽象一层,先检索背景原理。
角度单一 → 多 Query
多个改写版本分别检索再合并去重。
Query Rewrite 是为了弥合用户提问和文档表述之间的语义鸿沟——用户口语化、文档书面化,向量相似度天然偏低。四种方法各治一种鸿沟:口语化→直接改写、文体差异→HyDE(假设答案做向量)、问题太具体→Step-back、角度单一→多 Query 扩展。关键是把「为什么要做」和「每种方法解决什么」讲清楚。
核心目的是弥补用户提问方式和知识库文档表述之间的语义鸿沟。用户问「这东西坏了咋整」,文档写的是「产品故障排查与维修指南」,虽然语义相关,但口语和书面语在向量空间里坐标差距不小,相似度可能低到召回不了正确文档。所以要先改写,把口语化、模糊、带缩写的问题转成和文档表述更接近的书面语。
我主要用四种。一是直接改写,把口语化问题转成精准书面表述,适合多轮对话,能补全指代。二是 HyDE,先生成一个假设答案,用答案的向量去检索,因为答案到答案的距离比问题到答案近,假设答案只是扮演文档角色。三是 Step-back Prompting,把具体问题抽象一层,先检索背景原理。四是多 Query 扩展,生成几个不同角度的版本分别检索再合并去重,适合复杂问题但要多几次 LLM 调用。
HyDE 全称是假设文档嵌入,核心思路是:先让 LLM 根据用户问题生成一段假设性的答案,然后用这段答案的向量去检索文档。关键洞察是,在向量空间里答案到答案的距离比问题到答案的距离近得多。所以假设答案不需要准确,只需要风格像文档就够了,它的作用不是回答问题,而是扮演文档的角色,让检索命中的概率更大。