RAG 怎么做 Query 改写?从工程实践看检索增强生成的第一道关键关卡
1. 文章背景:为什么 Query 改写很重要
在 RAG(Retrieval-Augmented Generation,检索增强生成)系统中,很多人一开始会把重点放在向量数据库、Embedding 模型、文档切分、召回算法、重排序模型和大模型生成上,但真正落地以后会发现:用户输入的 Query 质量,往往直接决定整个 RAG 系统的上限。
一个典型的 RAG 流程通常是:
- 用户提出问题
- 系统根据问题检索知识库
- 将检索结果拼接到 Prompt 中
- 大模型基于上下文生成答案
这个流程看起来很简单,但问题在于,用户的问题并不总是适合直接拿去检索。
例如用户问:
这个怎么部署?
如果当前对话上下文中前面提到的是"LangChain + Milvus 的知识库问答系统",那么"这个"指的可能是整个 RAG 服务。但如果直接把"这个怎么部署?"送进向量数据库,检索效果通常会很差,因为这个 Query 缺少明确实体、缺少业务关键词,也没有表达出用户真正想要的信息。
再比如用户问:
报错了怎么办?
这种 Query 对人来说可能有上下文,但对检索系统来说几乎没有信息量。向量检索可能召回一堆"报错排查""常见问题""环境配置"的内容,但未必是用户真正需要的那一段。
因此,在企业级 RAG 系统中,Query 改写不是锦上添花,而是非常核心的工程模块。它的目标不是"让问题变得更好看",而是让问题变得更适合检索、更适合召回、更适合后续生成。
可以简单理解为:
Query 改写是 RAG 系统中连接"用户自然表达"和"知识库检索表达"的中间层。
一个好的 Query 改写模块,能够显著改善以下问题:
- 用户问题过短,缺少检索关键词
- 多轮对话中存在指代、省略、上下文依赖
- 用户表达口语化,和知识库文档表达不一致
- 查询意图不明确,需要拆分为多个子问题
- 单一 Query 召回不足,需要多路查询扩展
- 用户问题中包含无关信息,影响召回精度
2. 核心问题:实际开发中会遇到什么问题
在实际 RAG 开发中,Query 改写主要解决的不是语言润色问题,而是检索匹配问题。常见问题可以分为以下几类。
2.1 Query 信息不足
用户经常会问一些非常短的问题:
- 怎么配置?
- 这个参数是什么意思?
- 为什么失败?
- 有什么区别?
- 能不能优化?
这些问题如果脱离上下文,几乎无法直接检索。即使有上下文,向量检索也未必能理解"这个"指代的对象。
所以 Query 改写需要做的一件事是:补全上下文中的关键信息。
例如:
原始 Query:
text
这个怎么部署?
结合历史对话后改写为:
text
LangChain 和 Milvus 构建的 RAG 知识库问答系统如何进行生产环境部署?
这样改写后,检索系统就更容易召回"部署架构""服务启动""向量数据库配置""API 服务封装"等相关内容。
2.2 用户表达和文档表达不一致
企业知识库中的文档通常比较正式,而用户提问往往比较口语化。
用户可能问:
text
为什么模型回答总是胡说?
但文档中可能写的是:
text
大模型幻觉问题产生的原因包括检索上下文不足、Prompt 约束不明确、知识库召回不准确等。
这时如果直接检索"胡说",效果可能不稳定。Query 改写需要把用户口语表达转换成更贴近文档表达的形式:
text
RAG 系统中大模型幻觉问题的原因和解决方法是什么?
这类改写本质上是在做"语义归一化"。
2.3 多轮对话中的指代和省略
RAG 系统常常不是单轮问答,而是多轮对话。多轮场景下最常见的问题是指代。
例如:
用户第一轮问:
text
RAG 中 rerank 的作用是什么?
系统回答后,用户继续问:
text
那它会不会增加延迟?
这里的"它"指的是 rerank 模块。如果直接检索"它会不会增加延迟",召回结果很可能不稳定。正确的改写应该是:
text
RAG 系统中的 rerank 模块是否会增加检索和回答延迟?
所以多轮 Query 改写的重点是:将依赖上下文的问题改写成一个自包含问题。
2.4 查询意图复杂,需要拆分
有些用户问题包含多个意图:
text
RAG 的文档切分怎么做,Embedding 怎么选,召回效果怎么评估?
这类问题如果作为一个 Query 检索,可能会召回一些泛泛而谈的文档。更好的方式是拆分成多个子查询:
- RAG 系统中文档切分的策略和参数如何设计?
- RAG 系统中 Embedding 模型如何选择?
- RAG 系统中检索召回效果如何评估?
然后分别召回,再进行融合。
这类 Query 改写不仅是改写,而是 Query Decomposition,也就是查询分解。
2.5 Query 中存在噪声
用户输入中经常包含和检索无关的内容:
text
我现在很着急,老板下午要看演示,你赶紧告诉我 RAG 为什么查不到知识库里的内容。
真正用于检索的 Query 应该是:
text
RAG 系统无法检索到知识库内容的常见原因和排查方法。
Query 改写需要去掉情绪表达、无关背景、重复描述,只保留对检索有价值的信息。
3. 基础概念:用工程视角解释关键概念
3.1 Query 改写是什么
Query 改写指的是在 RAG 检索前,对用户输入的问题进行加工,使其更适合检索系统使用。
它可能包括:
- 补全上下文
- 消解指代
- 提炼关键词
- 转换表达方式
- 拆分复杂问题
- 扩展同义表达
- 生成多个检索 Query
- 过滤无关信息
从工程视角看,Query 改写不是一个单一能力,而是一组检索前处理策略。
3.2 Query 改写和 Prompt 改写的区别
很多人会把 Query 改写和 Prompt 优化混在一起。两者目标不同。
| 模块 | 作用位置 | 主要目标 |
|---|---|---|
| Query 改写 | 检索前 | 提升召回质量 |
| Prompt 改写 | 生成前 | 提升回答质量 |
| Rerank | 检索后 | 提升上下文排序质量 |
| Answer Rewrite | 生成后 | 提升最终表达质量 |
Query 改写服务的是检索系统,Prompt 改写服务的是生成模型。
一个常见错误是:只优化最终 Prompt,却忽略检索 Query。结果是 Prompt 写得很复杂,但召回内容不相关,大模型仍然无法回答。
RAG 系统有一个基本原则:
检索错了,生成很难对。
3.3 Query 改写的几种类型
工程中常用的 Query 改写方式主要有以下几类。
| 类型 | 说明 | 适用场景 |
|---|---|---|
| 上下文补全 | 将多轮对话中的省略信息补全 | 多轮问答 |
| 指代消解 | 将"它""这个""上面那个"等替换为明确对象 | 对话式 RAG |
| 关键词提取 | 提取核心实体、概念、参数 | 关键词检索、混合检索 |
| 同义扩展 | 生成相近表达 | 文档表达和用户表达不一致 |
| 查询分解 | 将复杂问题拆成多个子问题 | 长问题、多意图问题 |
| HyDE | 先生成假设答案,再用假设答案检索 | Query 太短或抽象 |
| 多查询生成 | 生成多个不同角度的 Query | 提升召回覆盖率 |
| 查询压缩 | 去掉噪声,只保留核心检索意图 | 用户输入冗长 |
4. 系统设计:如何搭建完整 Query 改写流程
一个比较完整的企业级 RAG Query 改写流程可以设计成以下模块:
text
用户问题
↓
对话上下文管理
↓
Query 类型判断
↓
Query 改写 / 拆分 / 扩展
↓
多路检索
↓
召回结果合并
↓
Rerank 排序
↓
上下文构造
↓
大模型生成答案
4.1 模块一:上下文管理
多轮 RAG 系统中,不能把所有历史对话都塞给改写模型。这样会带来三个问题:
- Token 成本变高
- 延迟增加
- 历史噪声影响当前问题
更合理的做法是维护一个轻量级上下文窗口,只保留对当前问题有帮助的信息。
可以保留:
- 最近 3 到 5 轮对话
- 当前正在讨论的主题
- 用户上一次确认的实体
- 已经检索到的文档标题或知识点
- 当前业务场景,例如"部署问题""报错排查""模型评估"
不建议直接保存全部历史消息作为改写输入。
4.2 模块二:Query 类型判断
并不是所有 Query 都需要复杂改写。对于简单、明确、信息充分的问题,直接检索可能效果更好。
可以将 Query 分为几类:
| Query 类型 | 示例 | 处理方式 |
|---|---|---|
| 明确单轮问题 | RAG 中 rerank 的作用是什么? | 可直接检索 |
| 指代问题 | 它有什么缺点? | 需要指代消解 |
| 省略问题 | 怎么部署? | 需要上下文补全 |
| 多意图问题 | 怎么切分文档,怎么选 embedding? | 需要查询分解 |
| 抽象问题 | 怎么优化效果? | 需要扩展或澄清 |
| 噪声问题 | 我很急,为什么知识库查不到? | 需要压缩 |
Query 类型判断可以用规则,也可以用小模型或大模型完成。实际落地中,建议先用规则兜底,再用 LLM 处理复杂情况。
4.3 模块三:Query 改写策略选择
不同场景适合不同改写策略。
如果是多轮对话,优先做上下文补全和指代消解。
如果是短 Query,优先做关键词扩展。
如果是复杂 Query,优先做查询分解。
如果是知识库文档表达和用户表达差异较大,可以做同义改写或 HyDE。
如果系统对延迟非常敏感,可以只做轻量规则改写,不调用大模型。
4.4 模块四:多路检索和结果融合
Query 改写后,不一定只生成一个 Query。很多生产系统会生成多个 Query,然后进行多路召回。
例如原始问题:
text
RAG 回答不准怎么办?
可以改写成:
text
RAG 系统回答不准确的原因有哪些?
RAG 检索召回不相关如何优化?
RAG 系统如何减少大模型幻觉?
RAG 知识库问答效果差的排查方法是什么?
然后分别检索,最后合并结果。
结果融合时要注意:
- 去重相同文档片段
- 保留不同角度的内容
- 控制上下文总长度
- 使用 rerank 模型重新排序
- 避免低质量扩展 Query 带来噪声
5. 关键实现:核心模块、技术选型和实现细节
5.1 基于规则的轻量 Query 改写
规则改写适合高频、稳定、低成本场景。例如企业内部系统经常会有固定术语:
- "权限"扩展为"权限控制、RBAC、数据访问权限"
- "报错"扩展为"异常、错误日志、排查方法"
- "部署"扩展为"服务部署、容器化部署、生产环境部署"
简单示例:
python
def rule_based_rewrite(query: str) -> str:
synonym_map = {
"报错": "报错 异常 错误日志 排查方法",
"部署": "部署 服务启动 Docker Kubernetes 生产环境",
"权限": "权限控制 RBAC 数据权限 访问控制",
"回答不准": "回答不准确 召回不相关 大模型幻觉 RAG效果优化",
}
rewritten = query
for key, value in synonym_map.items():
if key in query:
rewritten += " " + value
return rewritten
query = "RAG 回答不准怎么办"
print(rule_based_rewrite(query))
规则方案优点是:
- 成本低
- 延迟低
- 可控性强
- 便于线上排查
缺点是:
- 泛化能力有限
- 维护成本会逐渐上升
- 难以处理复杂上下文
因此规则改写适合作为基础兜底,不适合作为唯一方案。
5.2 基于 LLM 的上下文改写
LLM 适合处理多轮对话、指代消解和语义补全。一个常见 Prompt 可以这样设计:
text
你是一个 RAG 检索 Query 改写器。
你的任务是根据用户当前问题和必要的历史对话,将用户问题改写为一个适合知识库检索的独立问题。
要求:
1. 只输出改写后的 Query
2. 不要回答问题
3. 不要添加无法从上下文推断的信息
4. 保留关键实体、参数、系统名称和业务场景
5. 如果原问题已经清晰,可以保持不变
历史对话:
{chat_history}
当前问题:
{user_query}
改写后的 Query:
Python 示例:
python
def build_rewrite_prompt(chat_history: str, user_query: str) -> str:
return f"""
你是一个 RAG 检索 Query 改写器。
你的任务是根据用户当前问题和必要的历史对话,将用户问题改写为一个适合知识库检索的独立问题。
要求:
1. 只输出改写后的 Query
2. 不要回答问题
3. 不要添加无法从上下文推断的信息
4. 保留关键实体、参数、系统名称和业务场景
5. 如果原问题已经清晰,可以保持不变
历史对话:
{chat_history}
当前问题:
{user_query}
改写后的 Query:
""".strip()
需要注意,LLM 改写不是越"聪明"越好。它不能擅自补充用户没说过的信息,否则可能导致检索方向偏移。
例如用户问:
text
这个模型怎么优化?
历史上下文只提到"时序异常检测模型",LLM 不应该擅自改写成:
text
如何优化基于 Transformer 的电池电压时序异常检测模型?
除非历史上下文中确实出现过 Transformer 和电池电压。
5.3 查询分解
对于复杂问题,可以让 LLM 输出多个子查询。
Prompt 示例:
text
你是一个 RAG 查询分解器。
请将用户问题拆分为多个适合知识库检索的子问题。
要求:
1. 每个子问题必须语义完整
2. 子问题之间尽量不重复
3. 不要超过 5 个子问题
4. 只输出 JSON 数组
用户问题:
{query}
示例输出:
json
[
"RAG 系统中文档切分策略如何设计?",
"RAG 系统中 Embedding 模型如何选择?",
"RAG 系统中检索召回效果如何评估?"
]
在工程实现中,查询分解适合以下场景:
- 用户问题中有多个并列问题
- 用户要求做方案设计
- 用户要求对比多个技术
- 用户问题涉及多个系统模块
- 用户希望得到完整排查流程
但是查询分解也会增加检索次数和延迟,所以需要控制子查询数量。一般建议最多 3 到 5 个。
5.4 Multi-Query 多查询扩展
Multi-Query 的思想是:同一个问题可以从多个表达角度进行检索,避免单一 Query 表达不足。
例如:
原始 Query:
text
RAG 为什么回答不准确?
扩展 Query:
text
RAG 系统回答不准确的原因是什么?
RAG 检索结果不相关如何排查?
如何减少 RAG 系统中的大模型幻觉?
知识库问答系统效果差如何优化?
多查询扩展适合召回覆盖不足的场景,但要注意控制噪声。扩展 Query 不是越多越好。过多 Query 会带来:
- 检索成本上升
- 延迟增加
- 无关文档进入候选集
- rerank 压力变大
- 上下文拼接更复杂
工程上可以设置一个策略:
| 场景 | Query 数量建议 |
|---|---|
| 普通问答 | 1 个 |
| 短 Query | 2 到 3 个 |
| 复杂问题 | 3 到 5 个 |
| 高召回场景 | 5 个以内 |
| 实时低延迟场景 | 尽量 1 个 |
5.5 HyDE:用假设答案辅助检索
HyDE 的核心思想是:当用户 Query 太短、太抽象、缺少关键词时,可以先让 LLM 生成一个"假设性答案",再用这个假设答案去做向量检索。
例如用户问:
text
怎么提升召回?
直接检索可能太泛。可以先生成一段假设答案:
text
提升 RAG 系统召回效果通常可以从文档切分、Embedding 模型选择、Query 改写、混合检索、向量索引参数、召回数量和 rerank 等方面优化。
然后用这段文本去检索,可能更容易匹配知识库中的相关内容。
HyDE 适合:
- Query 很短
- 用户表达很抽象
- 知识库文档偏长
- 向量检索效果不稳定
但 HyDE 也有风险:
- LLM 生成的假设答案可能引入偏差
- 可能把检索方向带偏
- 成本和延迟更高
所以企业落地时,HyDE 一般不建议默认开启,而是作为特定场景的增强策略。
5.6 结构化 Query 改写
对于企业知识库,很多文档带有元数据,例如:
- 部门
- 产品线
- 文档类型
- 创建时间
- 权限级别
- 系统模块
- 版本号
- 标签
这时 Query 改写不应该只输出自然语言,还可以输出结构化检索条件。
示例:
json
{
"query": "RAG 系统中 rerank 模块如何降低延迟?",
"filters": {
"doc_type": "技术方案",
"module": "RAG",
"permission": "internal"
},
"top_k": 20
}
这种结构化改写对企业系统非常重要,因为企业知识库往往不是一个纯文本集合,而是带有权限、业务线、版本和文档类型的复杂数据系统。
6. 常见问题:实际落地中的坑和解决方案
6.1 改写后 Query 偏离用户原意
这是最常见的问题。LLM 可能会"过度理解",把用户没说的内容补进去。
解决方案:
- Prompt 中明确要求不要添加无法推断的信息
- 保留原始 Query 和改写 Query 一起检索
- 对改写结果做关键词一致性检查
- 对高风险场景增加用户确认
- 在日志中记录改写前后对比
推荐做法是:不要完全丢弃原始 Query,而是采用:
text
原始 Query + 改写 Query 双路检索
这样可以降低改写错误带来的损失。
6.2 Query 扩展太多导致噪声变大
多查询扩展确实能提升召回,但也容易召回无关内容。尤其是企业知识库很大时,扩展 Query 越多,候选文档越杂。
解决方案:
- 控制扩展 Query 数量
- 每个 Query 单独设置 top_k
- 合并后去重
- 使用 rerank 重新排序
- 对低分文档设置过滤阈值
- 监控无关文档比例
不要盲目追求召回数量。RAG 更重要的是"召回对的内容"。
6.3 多轮上下文污染
如果把太多历史对话放进改写模型,可能出现上下文污染。例如用户前面问过"Milvus",后面已经切换到"ES 混合检索",但改写模型仍然把 Milvus 带进去。
解决方案:
- 只保留最近几轮对话
- 使用当前主题检测
- 当用户明显切换主题时清空上下文
- 保留用户显式确认的信息
- 不要把系统生成的长回答全部作为上下文
6.4 改写模块增加延迟
调用 LLM 做 Query 改写会增加一次模型调用。如果系统要求低延迟,比如客服机器人、在线助手、生产监控问答,就必须控制延迟。
优化方式:
- 简单 Query 直接跳过改写
- 使用小模型做改写
- 使用规则优先,LLM 兜底
- 对高频问题缓存改写结果
- 改写和权限过滤并行处理
- 控制 Prompt 长度
工程上可以设计一个路由策略:
text
明确 Query → 直接检索
短 Query / 多轮 Query → LLM 改写
复杂 Query → 查询分解
低延迟场景 → 规则改写
6.5 改写结果不可解释
线上排查时,如果只看到最终回答,看不到 Query 改写过程,就很难判断问题出在哪里。
建议记录以下日志:
- 原始 Query
- 历史上下文摘要
- 改写后的 Query
- 拆分后的子 Query
- 每个 Query 的召回结果
- rerank 分数
- 最终进入 Prompt 的上下文
- 最终答案
这些日志对调试 RAG 系统非常关键。
7. 效果评估:如何判断 Query 改写是否有效
Query 改写不能只凭感觉判断,需要建立评估体系。
7.1 离线评估
离线评估可以构造一批测试集,每条数据包含:
- 用户原始问题
- 历史对话
- 标准答案
- 期望召回文档
- 改写后的 Query
- 实际召回结果
常用指标包括:
| 指标 | 含义 |
|---|---|
| Recall@K | 前 K 个召回结果中是否包含目标文档 |
| MRR | 目标文档排名越靠前越好 |
| NDCG | 考虑多个相关文档的排序质量 |
| Hit Rate | 是否命中至少一个相关文档 |
| Rewrite Accuracy | 改写结果是否保持原意 |
| Noise Rate | 召回结果中无关内容比例 |
其中最重要的是 Recall@K 和 MRR。因为 Query 改写的核心目标是提升检索质量。
7.2 在线评估
线上可以关注:
- 用户是否继续追问
- 用户是否点赞或点踩
- 用户是否点击引用文档
- 是否触发人工转接
- 回答是否被用户复制
- 会话是否快速结束
- 相同问题的重复提问率
这些指标不能完全代表答案质量,但可以作为线上趋势观察。
7.3 人工评估
Query 改写非常适合做人工抽样评估。可以设计几个维度:
| 维度 | 判断标准 |
|---|---|
| 语义一致性 | 是否保留用户原意 |
| 信息完整性 | 是否补全必要上下文 |
| 检索友好性 | 是否包含关键实体和概念 |
| 无幻觉 | 是否没有添加不存在的信息 |
| 简洁性 | 是否没有引入多余噪声 |
人工评估时,建议同时看"改写前召回结果"和"改写后召回结果",不要只看 Query 文本是否自然。
8. 工程优化:性能、成本、稳定性和可维护性
8.1 成本控制
Query 改写会增加模型调用成本。企业落地中不能所有请求都走大模型改写。
建议使用分层策略:
- 第一层:规则判断是否需要改写
- 第二层:简单规则改写
- 第三层:小模型改写
- 第四层:大模型复杂改写
- 第五层:查询分解或 HyDE
只有复杂问题才进入高成本链路。
8.2 延迟优化
Query 改写对延迟影响明显。可以从以下方面优化:
- 限制历史上下文长度
- 控制 LLM 输出长度
- 使用低延迟模型
- 将多 Query 检索并行执行
- 对高频 Query 使用缓存
- 对明确问题跳过改写
- 改写失败时降级为原始 Query
线上系统一定要有超时控制。比如改写超过指定时间,就直接使用原始 Query 检索,保证系统可用性。
8.3 稳定性设计
Query 改写模块必须支持降级:
text
LLM 改写失败 → 使用规则改写
规则改写失败 → 使用原始 Query
多查询失败 → 使用主 Query
HyDE 失败 → 跳过 HyDE
不要让 Query 改写成为整个 RAG 系统的单点故障。
8.4 权限控制
企业 RAG 系统中,Query 改写不能绕过权限。
例如用户问:
text
帮我查一下财务部门的薪资制度。
即使 Query 被改写得很准确,也必须在检索阶段基于用户身份做权限过滤。
权限控制应该在检索层和数据层完成,而不是依赖 Prompt 约束。Query 改写模块可以生成 filters,但不能决定用户能看什么。
推荐设计:
text
用户身份 → 权限服务 → 可访问文档范围 → 检索过滤 → rerank → 生成
8.5 可维护性
Query 改写模块上线后,要持续维护:
- 维护领域词典
- 维护同义词表
- 维护业务实体表
- 维护 Prompt 版本
- 维护测试集
- 维护日志和监控
- 定期回放失败案例
建议将 Query 改写 Prompt、规则词表、路由策略配置化,而不是写死在代码中。
9. 实践建议:给开发者的落地建议
9.1 不要一上来就做复杂方案
很多团队一开始就上 Multi-Query、HyDE、Agentic RAG,结果系统复杂度很高,效果却不稳定。
建议从最小可用方案开始:
text
原始 Query
↓
判断是否需要改写
↓
简单上下文补全
↓
原始 Query + 改写 Query 双路检索
↓
rerank
↓
生成答案
先把日志、评估、回放体系建起来,再逐步增强。
9.2 原始 Query 不要丢
无论改写结果看起来多好,都建议保留原始 Query 一起参与检索。因为改写模型可能出错,而原始 Query 是用户真实表达。
常见策略:
- 原始 Query 检索 top_k=10
- 改写 Query 检索 top_k=10
- 合并去重后 rerank
- 取最终 top_n 进入 Prompt
这样可以兼顾稳定性和召回效果。
9.3 Query 改写要面向知识库设计
不同知识库适合不同改写方式。
如果知识库是 API 文档,Query 要保留函数名、参数名、错误码。
如果知识库是企业制度,Query 要保留部门、制度名称、适用范围。
如果知识库是技术方案,Query 要保留系统名称、模块名称、架构关键词。
如果知识库是工单和故障记录,Query 要保留报错信息、日志关键词、环境信息。
不要把所有场景都用同一个 Prompt 解决。
9.4 评估要看召回结果,不只看改写文本
很多改写后的 Query 看起来很专业,但召回效果未必好。评估 Query 改写时,一定要看:
- 是否召回目标文档
- 目标文档排名是否提升
- 无关文档是否减少
- 最终答案是否更准确
- 延迟和成本是否可接受
Query 改写的价值最终体现在检索和回答质量上,而不是文本本身。
9.5 建议增加 Query 改写调试面板
在企业内部 RAG 平台中,建议提供调试页面,展示:
- 原始问题
- 历史上下文
- 改写 Query
- 子查询列表
- 每个 Query 的召回结果
- rerank 分数
- 最终上下文
- 最终回答
这能极大提升研发、算法、产品和业务人员之间的沟通效率。
10. 总结:提炼核心观点
RAG 系统的效果,不只取决于向量数据库、Embedding 模型和大模型本身,也强烈依赖用户 Query 的质量。Query 改写的本质,是把用户自然语言表达转换成更适合知识库检索的表达。
实际落地中,Query 改写主要解决以下问题:
- 用户问题过短,缺少关键词
- 多轮对话存在指代和省略
- 用户表达和文档表达不一致
- 一个问题包含多个意图
- Query 中存在大量噪声
- 单一查询召回覆盖不足
工程上不要把 Query 改写理解成简单的"润色问题",它更像是 RAG 检索链路中的智能路由和语义适配层。
一个可落地的 Query 改写系统,应该具备:
- 上下文补全能力
- 指代消解能力
- 查询分解能力
- 多查询扩展能力
- 结构化过滤能力
- 日志追踪能力
- 降级兜底能力
- 离线和在线评估能力
最推荐的实践路线是:
text
先做规则和上下文补全
再做原始 Query + 改写 Query 双路检索
然后引入 rerank
再根据失败案例增加多查询、查询分解和 HyDE
最后通过评估集和线上日志持续优化
Query 改写不是 RAG 系统中最炫的模块,但它往往是最影响效果的模块之一。尤其在企业级知识库问答、智能客服、技术文档助手、运维助手和内部知识管理系统中,Query 改写能力越强,系统越能理解用户真实意图,也越容易召回正确知识。
一句话总结:
RAG 的第一步不是检索,而是把用户的问题变成一个值得检索、能够检索、容易检索的问题。