Query 改写
Query 改写就是在用户提问后、系统去数据库检索前,先由模型把用户模糊、口语化、带有指代的原始问题,改写成一个清晰、完整、对检索系统非常友好的新问题。从而大幅提升检索的准确性和召回率。
为什么要进行query改写?
在 RAG 系统中,模型虽然有"记忆",能理解上下文,但底层的检索系统(如向量数据库)是"失忆"的,它拿到的只是一个孤立的查询字符串。
例如,用户先问"iPhone 16 Pro 的退货政策是什么",再问"那它的保修期呢"。如果直接用"那它的保修期呢"去检索,系统无法理解"它"指的是什么,召回的结果很可能不相关。
Query 改写就是为了解决这个问题,在检索前把"那它的保修期呢"改写成"iPhone 16 Pro 的保修期呢",确保检索的精准命中。
除了指代消解,Query 改写主要还能解决以下问题:
-
口语化表达:用户说"东西坏了咋整?",文档里写的是"产品故障维修流程"。改写可以消除这种"语义鸿沟"。
-
上下文省略:用户在多轮对话中省略了产品名等信息,改写可以自动补全。
-
多意图混合:用户一句话里问了两个不相关的问题(如"退货流程是什么,运费谁承担?"),改写可以将其拆分为两个独立的查询,确保每个问题都能找到最相关的答案。
Query 改写的五大核心策略
Query 改写主要有五种策略,它们可以组合使用,以应对各种复杂的用户提问。
1. 指代消解
这是多轮对话中最常用、最关键的策略。它的任务是识别并替换用户 query 中的代词(如"它"、"这个"、"上面说的"),将其指向具体的实体。
| 用户 query | 改写结果 |
|---|---|
| 那它的保修期呢? | iPhone 16 Pro 的保修期呢? |
| 上面说的退货条件再详细说说 | iPhone 16 Pro 拆封后退货条件的详细说明 |
2. 上下文补全
在多轮对话中,用户会自然地省略一些信息,认为对方应该知道。但检索系统不知道。上下文补全就是将这些省略的关键信息补充完整。
| 用户 query | 补全后的 query |
|---|---|
| 还有别的颜色吗? | iPhone 16 Pro 还有别的颜色吗? |
| 价格呢? | iPhone 16 Pro 的价格是多少? |
3. 口语化转正式(Colloquial to Formal)
用户提问时使用的往往是口语化的表达,而知识库中的文档通常是正式、专业的写法。这种改写可以消除两者之间的语义鸿沟,尤其对基于关键词匹配的检索(如 BM25)帮助很大。
| 用户 query | 改写结果 |
|---|---|
| 东西坏了咋整? | 产品故障后的维修和报修流程 |
| 快递咋还没到? | 订单发货后物流状态查询 |
4. 多意图拆分
当用户的一个 query 包含了多个独立的意图时,需要将其拆分为多个子查询。这样可以确保每个问题都得到精准的回答,而不是被"平均分配"或"混合"在一起。
| 用户 query | 拆分后的 query |
|---|---|
| 退货流程是什么,运费谁承担? | 1. 退货流程是什么 2. 退货运费由谁承担? |
不是所有长 query 都需要拆。"iPhone 16 Pro 的价格和颜色"虽然问了两个方面,但通常在同一个产品介绍 chunk 里就能找到,不需要拆成两次检索。拆分的判断标准是:两个意图是否可能分布在不同的 chunk 里。
多意图拆分的实现复杂度比前面几种策略高,而且拆分后每个子查询都要走一遍检索流程,成本翻倍。在实际项目中,如果业务场景下多意图问题不多,可以先不实现这个策略。
5. 关键词扩展
为原始 query 添加同义词、近义词或相关术语。这主要对基于关键词匹配的检索(如 BM25)有显著提升,能有效提高召回率。
| 用户 query | 扩展后的 query |
|---|---|
| 七天无理由退货 | 七天无理由退货 退换货政策 无条件退款 退货期限 |
使用频率
实际项目中,指代消解和上下文补全是必做的(不做的话多轮对话检索基本不可用)。口语化转正式建议做(投入产出比高)。多意图拆分和关键词扩展根据业务需要决定。
如何用大模型实现 Query 改写?
最高效的方式是通过设计一个清晰的 Prompt(提示词),让大模型自动完成改写。您可以用一个基础版的 Prompt 解决绝大多数问题。
基础版 Prompt 示例
你是一个查询改写助手。根据对话历史和用户的最新问题,将问题改写为一个独立的、完整的检索查询。 要求: 1. 如果最新问题中包含代词(它、这个、那个等)或省略了关键信息,请结合对话历史补全。 2. 如果问题已经足够完整清晰,请原样输出,不要画蛇添足。 3. 只输出改写后的查询,不要输出任何解释、前缀或多余内容。 4. 改写后的查询应该是一个独立的句子,不依赖对话历史也能理解。 对话历史:{history} 用户最新问题:{query} 改写后的查询:
进阶版 Prompt(支持 JSON 输出)
如果您需要支持多意图拆分,可以使用这个更复杂的 Prompt,并要求模型输出 JSON 格式,方便程序解析。
你是一个查询改写助手。根据对话历史和用户的最新问题,将问题改写为适合检索的查询。 要求: 1. 补全代词和省略的上下文信息。 2. 将口语化表达转化为更正式、更适合检索的表达。 3. 如果问题包含多个独立意图,拆分为多个子查询。 4. 如果问题已经完整清晰且只有一个意图,只输出一个查询。 5. 以 JSON 格式输出,格式为:{"queries": ["查询1", "查询2"]} 6. 不要输出 JSON 以外的任何内容。 对话历史: {history} 用户最新问题: {query}