Skip to content

6.1.1 用户问题进入 RAG 后,第一步为什么往往不是直接检索? ​

先给结论:因为用户问题是面向人表达的,不是天然面向检索器表达的。它里面常常混着上下文、省略、指代、冗余描述和不稳定说法,所以进入 RAG 后,第一步往往应该先理解问题,而不是立刻原样检索。

这也是很多系统一开始“看起来能搜”,但一到真实提问就开始波动的原因。

用户提问和检索查询为什么不是一回事 ​

用户提问的目标通常是:

  • 把自己想问的事表达出来

但检索查询的目标是:

  • 让系统更高概率找回正确候选

这两个目标不是完全一致的。

用户会自然说出很多对人类对话有用、但对检索不一定有帮助的内容,比如:

  • 情绪和铺垫
  • 代词和省略
  • 上下文承接
  • 很长的描述句

如果系统把这些内容原样全吃进去,检索器就容易抓不住真正核心。

用户原始提问里常见会混进什么 ​

至少常见会混进这些层:

  • 背景铺垫
  • 口语表达
  • 代词指代
  • 不完整术语
  • 多余约束

例如:

  • “我刚才看到你们那个说明里有写这个规则,但是如果是定制商品的话是不是就不算了?”

这句话对人来说能理解,但对检索器来说,真正关键的可能只是:

  • 定制商品
  • 退款规则
  • 是否适用

也就是说,进入检索前,系统往往要先抽出真正有用的那部分信号。

为什么直接检索会带来不稳定 ​

如果系统不先理解问题,直接把整句拿去检索,常见问题包括:

  • 关键信号被长句稀释
  • 代词没有被还原
  • 术语没有被补全
  • 一个问题里混着多个子问题
  • 用户真正想查的对象没有被明确抽出来

这会导致两类后果:

  • 漏召回
  • 误召回

而且这种不稳定经常非常隐蔽,因为:

  • 同一个问题换一种说法,结果就可能差很多

一个更实际的最小链路 ​

可以先把检索前链路粗略理解成:

  1. 用户提问进入系统
  2. 系统先判断问题核心是什么
  3. 必要时做术语补全、指代消解、子问题拆分
  4. 再把更适合检索的查询送入召回层

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

python
user_query = "如果是定制商品的话,这个规则还算吗?"

understood_query = "定制类商品是否适用退款规则"
results = retrieve(understood_query)

这段代码想说明的问题是:

  • 系统真正拿去检索的,未必是用户原话
  • 中间往往先要经过一层“把问题变得更适合检索”

为什么这一步在多轮对话里更重要 ​

在多轮对话里,这个问题会更明显。

因为用户经常会这样问:

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

这些句子单独拿去检索,通常几乎没法用。

系统必须先结合前文,恢复出更完整的查询对象,后面检索才有可能稳定。

一个常见误区 ​

很多人会觉得:

  • 用户原话最真实,所以当然最适合拿去搜

这不一定。

更稳的理解是:

  • 用户原话最适合对话,不一定最适合检索

系统要做的不是篡改问题,而是把对话语言转成更适合召回的查询形式。

一句话总结 ​

用户问题进入 RAG 后,第一步往往不是直接检索,因为用户原话服务的是交流,而检索器需要的是更清晰、更稳定的查询信号。先做问题理解,往往比直接原样搜索更稳。