Appearance
6.2.3 多轮对话场景下,RAG 为什么要先做问题重写?
先给结论:因为多轮对话里的用户输入经常不是完整问题,而是依赖前文的短句、省略句和代词句。如果不先重写成独立可检索的问题,后面的召回很容易直接失真。
这也是为什么多轮 RAG 的第一步,常常不是直接检索,而是:
- 先恢复当前轮真正想查的完整问题
多轮对话里最常见的问题是什么
多轮对话的用户经常不会每次都把问题说全。
他们更常这样问:
- “那这个也能退吗?”
- “企业版呢?”
- “如果不是这个型号呢?”
- “上一条规则还适用吗?”
这些句子在对话里完全自然,但如果单独拿去搜,通常都不够完整。
系统必须先回答一个问题:
- “这个句子真正指的是哪一个完整查询?”
为什么多轮输入不能直接原样检索
因为它经常缺至少一类关键信息:
- 主体对象
- 比较对象
- 条件边界
- 上下文指向
例如:
- “企业版呢?”
系统如果不结合前文,根本不知道:
- 企业版的什么
- 和谁比较
- 正在讨论哪个主题
这时直接检索,不稳定几乎是必然的。
多轮重写到底在做什么
多轮场景下的 Query Rewrite,最核心做的是:
- 把依赖上下文的短句,恢复成一条独立、完整、可检索的问题
一个最小示意可以写成这样:
python
history = [
"个人版支持七天无理由退货吗?",
"个人版普通商品支持。"
]
user_query = "那企业版呢?"
rewritten_query = "企业版普通商品是否支持七天无理由退货"这段代码想说明的是:
- 当前轮输入本身不足以检索
- 必须结合历史,把问题补完整
为什么这一步会直接影响召回质量
因为重写前和重写后,系统送入检索器的往往不是同一个问题。
如果不重写,系统可能:
- 抓不到真正主题
- 误把代词当噪声
- 把上下文里不重要的词抓进来
而重写后,系统更有机会明确:
- 当前检索目标是什么
- 哪些约束还要继续保留
- 当前这一轮到底要查哪类知识
多轮重写做不好会出现什么问题
最常见的几种问题是:
- 当前轮问题被理解错对象
- 上一轮无关内容被错误继承
- 当前轮真正关键的边界没被保留
- 检索结果看起来相关,但其实答的是上一轮问题
这些问题的共同点是:
- 检索器不一定坏
- 是系统送进去的问题就已经错了
什么情况下尤其要先做重写
下面这些情况,尤其不建议跳过重写:
- 当前轮有大量代词,如“这个”“那个”“这里”
- 当前轮很短,明显依赖前文
- 当前轮在比较两个对象
- 当前轮延续的是上一轮的条件判断
这些场景如果不先恢复完整查询,后面系统就只能靠猜。
一个常见误区
很多人会觉得:
- 只要把整个对话历史一起丢给检索器,就等于完成了多轮理解
这通常不够稳。
因为“历史都带上”不等于“当前问题被正确恢复”。
系统如果没有明确重写出当前轮问题,很容易出现:
- 历史越多,噪声越多
- 当前轮焦点反而更模糊
一句话总结
多轮对话场景下,RAG 往往要先做问题重写,因为当前轮输入经常不是完整查询,而是依赖前文的短句和省略句。先把问题恢复成独立可检索形式,后面的召回才更有机会稳定。