Skip to content

6.2.3 多轮对话场景下,RAG 为什么要先做问题重写? ​

先给结论:因为多轮对话里的用户输入经常不是完整问题,而是依赖前文的短句、省略句和代词句。如果不先重写成独立可检索的问题,后面的召回很容易直接失真。

这也是为什么多轮 RAG 的第一步,常常不是直接检索,而是:

  • 先恢复当前轮真正想查的完整问题

多轮对话里最常见的问题是什么 ​

多轮对话的用户经常不会每次都把问题说全。

他们更常这样问:

  • “那这个也能退吗?”
  • “企业版呢?”
  • “如果不是这个型号呢?”
  • “上一条规则还适用吗?”

这些句子在对话里完全自然,但如果单独拿去搜,通常都不够完整。

系统必须先回答一个问题:

  • “这个句子真正指的是哪一个完整查询?”

为什么多轮输入不能直接原样检索 ​

因为它经常缺至少一类关键信息:

  • 主体对象
  • 比较对象
  • 条件边界
  • 上下文指向

例如:

  • “企业版呢?”

系统如果不结合前文,根本不知道:

  • 企业版的什么
  • 和谁比较
  • 正在讨论哪个主题

这时直接检索,不稳定几乎是必然的。

多轮重写到底在做什么 ​

多轮场景下的 Query Rewrite,最核心做的是:

  • 把依赖上下文的短句,恢复成一条独立、完整、可检索的问题

一个最小示意可以写成这样:

python
history = [
    "个人版支持七天无理由退货吗?",
    "个人版普通商品支持。"
]

user_query = "那企业版呢?"
rewritten_query = "企业版普通商品是否支持七天无理由退货"

这段代码想说明的是:

  • 当前轮输入本身不足以检索
  • 必须结合历史,把问题补完整

为什么这一步会直接影响召回质量 ​

因为重写前和重写后,系统送入检索器的往往不是同一个问题。

如果不重写,系统可能:

  • 抓不到真正主题
  • 误把代词当噪声
  • 把上下文里不重要的词抓进来

而重写后,系统更有机会明确:

  • 当前检索目标是什么
  • 哪些约束还要继续保留
  • 当前这一轮到底要查哪类知识

多轮重写做不好会出现什么问题 ​

最常见的几种问题是:

  1. 当前轮问题被理解错对象
  2. 上一轮无关内容被错误继承
  3. 当前轮真正关键的边界没被保留
  4. 检索结果看起来相关,但其实答的是上一轮问题

这些问题的共同点是:

  • 检索器不一定坏
  • 是系统送进去的问题就已经错了

什么情况下尤其要先做重写 ​

下面这些情况,尤其不建议跳过重写:

  1. 当前轮有大量代词,如“这个”“那个”“这里”
  2. 当前轮很短,明显依赖前文
  3. 当前轮在比较两个对象
  4. 当前轮延续的是上一轮的条件判断

这些场景如果不先恢复完整查询,后面系统就只能靠猜。

一个常见误区 ​

很多人会觉得:

  • 只要把整个对话历史一起丢给检索器,就等于完成了多轮理解

这通常不够稳。

因为“历史都带上”不等于“当前问题被正确恢复”。

系统如果没有明确重写出当前轮问题,很容易出现:

  • 历史越多,噪声越多
  • 当前轮焦点反而更模糊

一句话总结 ​

多轮对话场景下,RAG 往往要先做问题重写,因为当前轮输入经常不是完整查询,而是依赖前文的短句和省略句。先把问题恢复成独立可检索形式,后面的召回才更有机会稳定。