这篇学完你能回答什么
- 「用户 query 很口语很含糊,怎么做查询改写?」
- 「HyDE 的思路是什么?为什么用一段假答案去检索反而更准?」
- 「多数据源(向量库 / SQL / 图谱 / API)的路由怎么设计?」
从三个真实故障讲起
故障一:多轮指代。 用户先问「Pro 版支持几个并发」,接着问「那它多少钱」。你把「那它多少钱」直接拿去检索——「它」是谁?检索器不知道,捞回来一堆不相干的价格页。
故障二:表述鸿沟。 用户问「机器嗡嗡响正常吗」,文档写的是「设备运行异常噪音的判定标准」。语义有关联但不够近,向量检索排到很后面。
故障三:问错地方。 用户问「我上个月的订单金额是多少」——这个答案根本不在知识库里,它在数据库里。你的 RAG 再准也答不出来。
这三类问题都发生在检索之前。很多人优化 RAG 只盯着检索和排序,忽略了:用户的原始问题往往不是一个好的检索输入。 查询理解就是在提问和检索之间加的那道预处理。
核心概念
查询理解(Query Understanding)= 在检索前对用户问题做加工,让它更适合被检索。主要动作有四类:改写、扩展、变换、路由。
多轮对话里的指代
「它」是谁?检索器不知道,捞回一堆不相干的价格页
改成自包含、书面化的 query
结合对话历史补齐指代,输出「Pro 版的价格是多少」
用户的问法 ≠ 文档的写法
文档写的是「设备运行异常噪音的判定标准」,语义有关联但不够近
补上问法和写法之间的距离
多生成几个角度的变体分别检索,或者干脆用一段假答案去检索
原理拆解:四类技术
| 实现 | 说明 | 适用 |
|---|---|---|
| 规则 / 关键词 | 命中关键词就走某路 | 意图少且明确,最省 |
| 轻量分类器 | 小模型或 embedding 相似度分类 | 意图多、要求稳定 |
| LLM 判断 | 直接让大模型选 | 意图复杂、变化快,最贵 |
实用建议:先用规则或轻量分类器覆盖高频意图,尾部长尾再交给 LLM。不要一上来就每个 query 都让大模型判一次 —— 这是成本悄悄失控的常见来源。
子问题拆解是扩展的同类思路:「A 和 B 的保修政策有什么区别」拆成两个独立子问题分别检索,再合并作答,已经很接近 Agentic RAG 的路子(T2-9)。
1. 查询改写(Query Rewriting)——解决指代与口语化
用 LLM 把用户的原始问法改写成一个自包含、书面化的检索 query。
对话历史:Q1「Pro 版支持几个并发」 A1「……」
用户输入:「那它多少钱」
改写输出:「Pro 版的价格是多少」
多轮对话场景下,这一步几乎是必须的——没有它,第二轮往后的检索质量会断崖下跌。这是面试里能立刻体现「做过多轮 RAG」的细节。
代价:多一次 LLM 调用(延迟 + 成本)。优化手段是用小模型专门做改写,或只在检测到指代词时才触发。
2. 查询扩展(Query Expansion)——解决表述鸿沟
一个问题生成多个不同角度的变体,分别检索后合并结果(用 RRF 融合,见 T2-5):
原问题:机器嗡嗡响正常吗 ├── 设备运行噪音是否正常 ├── 异常噪音判定标准 └── 设备噪音故障排查
也叫 Multi-Query。原理很直白:多撒几张网,总有一张能捞到。 代价是检索次数翻倍,延迟上升。
同类思路还有子问题拆解:复杂问题(「A 和 B 的保修政策有什么区别」)拆成两个独立子问题分别检索,再合并作答——这已经很接近 Agentic RAG 的思路了(T2-9)。
3. HyDE——最反直觉的一招
HyDE(Hypothetical Document Embeddings,假设性文档嵌入):先让 LLM 凭空编一段"看起来像答案"的文本,然后拿这段假答案去检索,而不是拿问题去检索。
为什么反而更准?因为问题和答案在向量空间里本来就不相似。「保修期多久?」和「本产品自购买之日起提供 24 个月质保……」——一个是疑问句一个是陈述句,句式、词汇都不同。而 LLM 编的假答案,句式和词汇分布跟真答案高度接近,用它去匹配真文档,等于让"答案找答案",天然更近。
编的内容是错的没关系——我们要的不是它的事实,是它的表述形态。
适用与代价:专业领域、问答表述差异大的场景收益明显;但多一次 LLM 调用,且模型对该领域一无所知时可能编出误导性方向。属于「知道原理很加分,但不必默认开启」的技术。
4. 查询路由(Query Routing)——解决问错地方
判断这个问题该去哪查:
用户问题 ├─ 事实性知识问答 → 向量库 / 混合检索 ├─ 结构化数据(金额、订单)→ SQL 查询 ├─ 关系推理(谁和谁有关联)→ 图谱查询 ├─ 实时信息(今天股价) → Web 搜索 / API └─ 闲聊 / 无需检索 → 直接回答(省一次检索)
最后一条常被忽略却很实用:「你好」「谢谢」这类输入根本不需要检索,直接放行既省钱又快。
路由的三种实现,成本递增:
| 实现 | 说明 | 适用 |
|---|---|---|
| 规则 / 关键词 | 命中关键词就走某路 | 意图少且明确,最省 |
| 轻量分类器 | 小模型或 embedding 相似度分类 | 意图多、要求稳定 |
| LLM 判断 | 直接让大模型选 | 意图复杂、变化快,最贵 |
实用建议:先用规则或轻量分类器覆盖高频意图,尾部长尾再交给 LLM。不要一上来就每个 query 都让大模型判一次——这是成本悄悄失控的常见来源。
工程实践(截至 2026-08)
别一次性全上。 这些技术每一个都增加延迟和成本,正确顺序是按 badcase 归因决定:
成本与延迟的账:每一步都是一次额外的模型调用。一个「改写 + 扩展三路 + rerank」的重型管线,首字延迟很容易多出 1–2 秒。对话式产品要权衡;可以对高频简单 query 走轻管线,复杂 query 才走重管线。
常见坑:
- 改写把关键专有名词改没了(「SK-3200」被改成「该型号设备」),反而检索不到——改写 prompt 里要明确要求保留原文中的专有名词、型号、编号。
- 扩展生成的变体互相太像,等于白花钱。要在 prompt 里要求「从不同角度改写」。
- 路由判错的兜底:分类不确定时默认走全量检索,而不是赌一条路。
- 改写后的 query 要记得留档,排障时你需要知道模型到底拿什么去检索的。
| 观察到的 badcase | 上哪一项 | 备注 |
|---|---|---|
| 多轮问答第二轮开始变差 | 上查询改写 | 收益最确定,多轮场景几乎是必选项,先上这个 |
| 单轮但表述对不上 | 上查询扩展 / HyDE | 检索次数翻倍,延迟跟着上升 |
| 用户问了知识库里没有的东西 | 上路由 + 兜底话术 | 答案不在库里,RAG 再准也答不出来 |
| 什么问题都答得一般 | 回去看分块和检索(T2-2 / T2-5) | 不是这一层的锅,在这里加手段是白加 |
- 延迟的账
- 「改写 + 扩展三路 + rerank」这样的重型管线,首字延迟很容易多出 1–2 秒
- 分级放行
- 高频简单 query 走轻管线,复杂 query 才走重管线,别让所有请求付同一份钱
- 改写的坑
- 「SK-3200」被改成「该型号设备」就检索不到了 —— prompt 里明确要求保留专有名词、型号、编号
- 扩展的坑
- 变体互相太像等于白花钱,prompt 里要写明「从不同角度改写」
- 路由的坑
- 分类不确定时默认走全量检索,而不是赌一条路
- 留档
- 改写后的 query 要留档:排障时你需要知道模型到底拿什么去检索的
面试视角
- 先给分类指代、表述鸿沟、问错地方三类
- 每类配一个手段改写 / 扩展与 HyDE / 路由
- HyDE 讲根因问题和答案在向量空间本来就不相似
- 收在成本与迭代按 badcase 决定上哪一项,不一次性堆满
- 开口就报四个名词,说不出每一个到底治哪种病
- 讲 HyDE 只有「用假答案检索更准」,说不出为什么更准
- 不提多轮改写,也不知道第二轮往后会断崖下跌
- 路由张口就是「让大模型判」,不算每个 query 判一次的账
- 把手段当成越多越好,全程不提延迟和成本
- 先把问题分成指代、表述鸿沟、问错地方,再一一对应手段
- 点出根因:假答案和真答案的句式词汇分布接近,等于答案找答案
- 知道多轮里改写几乎是必须的,还会只在检测到指代词时触发
- 先用规则或轻量分类器覆盖高频意图,长尾才交给 LLM
- 主动算账:重型管线首字延迟多 1–2 秒,所以按 badcase 上手段
Q2-13、Q2-14;相关 Q2-19(Agentic RAG)。小结与延伸
一句话总结:用户的原话往往不是好的检索输入。改写治指代和口语,扩展和 HyDE 治表述鸿沟,路由治「问错地方」——但每一项都要花钱买延迟,所以该由 badcase 来决定上哪一项,而不是一次性堆满。
下一篇 T2-8:这些优化到底有没有用?RAG 评测与 badcase 驱动迭代。
继续深入
本篇归属第 2 章「RAG 工程化」,去做这一章的题。