# AI Agent从0到1开发学习:【如何润色用户的Query?目的是什么?】
在RAG(检索增强生成)系统中,用户输入的Query质量直接决定了最终回答的上限。然而现实是——用户不会总是给出精准的问题。这一篇,我们来聊聊Query Rewrite这件事:为什么需要它?有哪些主流方法?各自适合什么场景?
简要回答
Query Rewrite(查询重写),顾名思义,就是在用户原始查询进入检索模块之前,对其进行改写、扩展或抽象,使其更利于下游的语义检索和答案生成。它的核心目的有两个:
- 消除歧义,补全上下文:用户的提问往往是简短的、模糊的、带指代关系的,直接拿去检索效果很差;
- 弥合"问"与"答"之间的语义鸿沟:用户问的是问题,文档库里存的是陈述,两者的表达方式天然不同,重写可以让Query在语义空间上更靠近目标文档。

详细解析
为什么需要 Query Rewrite?
在讲方法之前,先搞清楚"为什么"这件事。很多初学者会问:用户输入了什么,我就拿什么去检索,不行吗?
还真不太行。原因主要有三点:
第一,用户提问天然是"懒"的。 多轮对话中,用户经常会说"它怎么样"“还有呢”“能再详细点吗"这类话,这里面充满了代词和省略。比如一个用户先问了"Transformer的注意力机制是什么原理”,然后追问"它和RNN比有什么优势"——这个"它"指代什么?如果不做上下文补全,检索系统根本不知道该搜什么。
第二,Query和Document之间存在语义不对称。 用户在提问时,用的是"疑问式"表达(“怎么做X?”“X为什么有效?”),而文档库里存储的知识通常是"陈述式"表达(“X的做法是……”“X有效的原因是……”)。这种表达方式的差异会导致向量检索时,Query的Embedding和目标Document的Embedding在向量空间中的距离偏大,从而检索不到相关内容。
第三,复杂问题难以一次检索到位。 有些问题涉及多个方面,比如"对比BERT和GPT在预训练方式、模型架构和下游任务表现上的异同"——一个Query试图覆盖多个维度,检索时很可能顾此失彼。单一检索要么只能命中其中某一个维度的文档,要么每个维度都只搜到浅层内容,很难做到全面覆盖。
举一个更直白的例子:用户在客服场景下问"退货怎么操作",这个Query简短到检索系统可能返回一堆无关的"购买操作"“换货操作"文档。但如果改写成"如何申请商品退货及退货流程步骤”,检索的精准度就会明显提升。
正是因为这些原因,Query Rewrite成了RAG系统中不可或缺的一环。它就像是给用户的"粗糙问题"做了一次"精加工",让下游的检索和生成模块能更好地完成自己的工作。

方法一:直接改写(Query Rewrite)
这是最直观的方法:把用户的原始Query丢给LLM,让它重新写一版更完整、更清晰的问题。
基本思路
核心Prompt大致是:
你是一个查询改写助手。请根据对话历史,将用户当前的问题改写为一个独立、完整、无歧义的查询。
对话历史:{history}
用户当前问题:{query}
改写后的查询:
LLM根据上下文,把省略的信息补回来,把模糊的指代消解掉,输出一个"自洽"的新Query。举个例子:用户在多轮对话中先问了"Python怎么读取CSV文件",接着追问"它支持哪些参数",经过改写后,输出"Python的csv模块/pandas的read_csv函数支持哪些参数"——信息量丰富得多,检索命中率自然也更高。
适用场景
- 多轮对话中的指代消解和上下文补全,这是最经典的应用场景;
- 用户输入明显过短或含糊,需要"展开"才能检索到相关内容的情况;
- 单轮场景下,对Query做适度的措辞优化。
优点与局限
优点:实现简单,一个Prompt就能搞定;效果立竿见影,尤其在多轮对话场景下,改写后的Query质量提升非常明显。
局限:改写质量高度依赖LLM的能力;如果上下文很长,LLM可能"过度解读"或"偏离原意";改写后的Query可能丢失用户原始意图中的某些细微之处。此外,这种方法本质上仍然是在"问题空间"内做改写,没有跳出"用户怎么问"的思维框架,对于语义鸿沟问题只能部分缓解。
方法二:HyDE(Hypothetical Document Embedding)
HyDE的思路非常有意思——与其改写问题,不如先让LLM"编"一个答案,然后用这个假答案去做检索。

基本思路
具体步骤如下:
- 拿到用户的Query,让LLM生成一个"假设性回答"(Hypothetical Document),这个回答与真实答案格式相似但内容可能不准确的文档,没关系;
- 对这个假设性回答做Embedding;
- 用这个Embedding去向量库中检索最相似的真实文档;
- 返回检索到的真实文档作为上下文。
这个方法的核心洞察是:虽然LLM编造的答案可能不准确,但它的"样子"——包括用词、行文结构、涉及的专业术语——和真实正确的文档非常相似。 换句话说,假答案和真答案在语义空间中的方向是接近的,只是内容细节不同。因此,用假答案的Embedding去检索,反而能找到真正相关的文档。
这背后的原理可以用一个类比来理解:假设你问一个人"北京有什么好玩的地方",他可能胡乱编了一篇游记,里面把景点名字、美食推荐、交通方式写得有模有样但全是编的。虽然内容是虚构的,但这篇游记的"行文风格"和"话题分布"跟真实的北京旅游攻略高度相似。拿这篇假游记去匹配真实攻略,反而比拿"北京有什么好玩的地方"这个问题去匹配效果好得多——因为问题和攻略的"说话方式"差太远了,但假游记和真攻略的"说话方式"很接近。
适用场景
- 用户提问比较抽象或开放,难以直接从问题本身提取有效检索词;
- 文档库内容专业性强,用户的"问题式表达"和"文档式表达"之间差距大;
- 对检索的召回率要求较高,愿意用一定的计算成本换取更好的检索效果。
优点与局限
优点:巧妙地跨越了"提问-陈述"的语义鸿沟,检索效果通常优于直接改写;不需要额外的训练,即插即用。
局限:多了一次LLM调用,延迟和成本都会增加;如果LLM对某个领域完全不了解,生成的假设文档可能偏离正确方向太远,反而会误导检索
方法三:Step-back Prompting
Step-back Prompting的哲学是:当具体问题检索不到好结果时,不妨退一步,从更高的抽象层次来看这个问题。

基本思路
- 用一个Prompt让LLM对原始问题进行"抽象化",生成一个更宽泛的"后退问题"(Step-back Question);
- 用这个后退问题去检索,获取更广泛的背景知识;
- 将原始问题和检索到的背景知识一起交给LLM,生成最终回答。
举个例子:
- 原始问题:“为什么GPT-4比GPT-3表现更好?”
- 后退问题:“大语言模型的演进规律是什么?”
后退问题更宽泛,检索到的文档虽然不一定直接回答"为什么GPT-4更好",但很可能包含大模型演进的一般性规律,这些规律恰好能帮助LLM推导出原始问题的答案。
Tips:实际工程中,建议同时用原始问题进行一次检索,并与后退问题的检索结果合并,以兼顾具体信息和背景知识。
适用场景
- 具体问题过于细节化,文档库中缺乏直接匹配的内容;
- 需要大量背景知识才能回答的复杂推理问题;
- 领域知识问答,用户问题很具体但检索语料偏向综述性内容。
优点与局限
优点:通过抽象化扩大了检索范围,能有效解决"具体问题检索不到"的困境;检索到的背景知识能帮助LLM做更深入的推理,而不仅仅是拼凑片段。
局限:抽象的"度"不好把握——太抽象检索结果会太泛,不够抽象又和原始问题一样检索不到;后退问题的生成质量直接影响最终效果;对于本身已经很宽泛的问题,再后退一步可能就失去了焦点。实践中,后退问题的生成通常需要精心设计Prompt,并在少量样本上反复调试,才能让LLM稳定地产出合适粒度的抽象问题。
方法四:多Query扩展
前三种方法都是把一个Query变成另一个Query,而多Query扩展则是把一个Query拆成多个子Query,分头检索、合并结果。
基本思路
- 用LLM将原始Query拆解或扩展为多个视角不同的子查询;
- 对每个子查询分别执行检索;
- 对所有检索结果进行去重、合并、排序;
- 用合并后的结果作为上下文生成最终回答。
比如用户的原始问题是"对比BERT和GPT的异同",可以拆解为:
- “BERT的模型架构和训练方式”
- “GPT的模型架构和训练方式”
- “BERT和GPT的性能对比”
- “BERT和GPT的适用场景差异”
每个子查询从不同角度检索,最终汇总得到的信息远比单一Query丰富全面。
适用场景
- 用户的问题包含多个方面或维度,单一Query难以覆盖;
- 需要综合多个信息源才能回答的复杂问题;
- 对检索的全面性(召回率)要求很高的场景。
优点与局限
优点:覆盖面广,不容易遗漏关键信息;子查询之间可以互补,整体检索效果通常优于单一Query。
局限:多次检索带来较高的延迟和计算开销;结果合并和去重需要额外的策略设计,比如可以用RRF(Reciprocal Rank Fusion)算法对多路检索结果做融合排序;如果子查询之间相关性弱,可能引入噪声,反而降低最终回答的精度。此外,子查询的数量也需要控制,一般3-5个为宜,过多会导致延迟飙升且边际收益递减。
四种方法对比
| 方法 | 核心思路 | 适用场景 | 额外增加的成本 | 实现复杂度 |
|---|---|---|---|---|
| 直接改写 | LLM改写Query,补全上下文 | 多轮对话、指代消解 | 1次LLM调用 | 低 |
| HyDE | 生成假设性文档做检索 | 语义鸿沟大、开放式问题 | 1次LLM调用 | 中 |
| Step-back | 抽象化问题再检索 | 细节问题检索不到、需背景知识 | 1次LLM调用 | 中 |
| 多Query扩展 | 拆分为多个子查询 | 复杂多维度问题 | N次LLM 调用 | 高 |
在实际工程中,这四种方法并非互斥,经常组合使用。比如先对多轮对话的Query做直接改写,消除指代;再根据改写结果判断是否需要HyDE或多Query扩展。一个常见的Pipeline是:直接改写 → 判断问题复杂度 → 按需选择HyDE/Step-back/多Query扩展。选择哪种方法,取决于你的业务场景、数据特点和性能预算。
有一点需要特别提醒:Query Rewrite并不是万能的。如果文档库本身就缺乏相关内容,或者Embedding模型的质量不够好,再怎么改写Query也无济于事。Query Rewrite解决的是"好内容存在但检索不到"的问题,而不是"好内容压根不存在"的问题。在优化检索效果时,要同时关注索引质量、Embedding模型和检索策略,不要把所有期望都压在Query Rewrite上。
写在最后
Query Rewrite看起来只是RAG流程中的一个小环节,但它往往是"四两拨千斤"的关键——一个好的Query改写,可以让下游的检索和生成事半功倍,而一个糟糕的改写,则可能让整个系统的表现大打折扣。
从工程实践的角度来看,建议从直接改写入手,这是投入产出比最高的选择。当你发现改写后的Query仍然检索不到理想结果时,再根据具体问题选择HyDE、Step-back或多Query扩展。循序渐进,不要一上来就搞最复杂的方案。
希望这篇文章对你理解Query Rewrite有所帮助。如果你在实践中有其他心得,欢迎在评论区交流。
更多推荐



所有评论(0)