Appearance
6.1.1 用户问题进入 RAG 后,第一步为什么往往不是直接检索?
先给结论:因为用户问题是面向人表达的,不是天然面向检索器表达的。它里面常常混着上下文、省略、指代、冗余描述和不稳定说法,所以进入 RAG 后,第一步往往应该先理解问题,而不是立刻原样检索。
这也是很多系统一开始“看起来能搜”,但一到真实提问就开始波动的原因。
用户提问和检索查询为什么不是一回事
用户提问的目标通常是:
- 把自己想问的事表达出来
但检索查询的目标是:
- 让系统更高概率找回正确候选
这两个目标不是完全一致的。
用户会自然说出很多对人类对话有用、但对检索不一定有帮助的内容,比如:
- 情绪和铺垫
- 代词和省略
- 上下文承接
- 很长的描述句
如果系统把这些内容原样全吃进去,检索器就容易抓不住真正核心。
用户原始提问里常见会混进什么
至少常见会混进这些层:
背景铺垫口语表达代词指代不完整术语多余约束
例如:
- “我刚才看到你们那个说明里有写这个规则,但是如果是定制商品的话是不是就不算了?”
这句话对人来说能理解,但对检索器来说,真正关键的可能只是:
- 定制商品
- 退款规则
- 是否适用
也就是说,进入检索前,系统往往要先抽出真正有用的那部分信号。
为什么直接检索会带来不稳定
如果系统不先理解问题,直接把整句拿去检索,常见问题包括:
- 关键信号被长句稀释
- 代词没有被还原
- 术语没有被补全
- 一个问题里混着多个子问题
- 用户真正想查的对象没有被明确抽出来
这会导致两类后果:
- 漏召回
- 误召回
而且这种不稳定经常非常隐蔽,因为:
- 同一个问题换一种说法,结果就可能差很多
一个更实际的最小链路
可以先把检索前链路粗略理解成:
- 用户提问进入系统
- 系统先判断问题核心是什么
- 必要时做术语补全、指代消解、子问题拆分
- 再把更适合检索的查询送入召回层
一个最小示意可以写成这样:
python
user_query = "如果是定制商品的话,这个规则还算吗?"
understood_query = "定制类商品是否适用退款规则"
results = retrieve(understood_query)这段代码想说明的问题是:
- 系统真正拿去检索的,未必是用户原话
- 中间往往先要经过一层“把问题变得更适合检索”
为什么这一步在多轮对话里更重要
在多轮对话里,这个问题会更明显。
因为用户经常会这样问:
- “那这个呢?”
- “上一条规则也适用于这个吗?”
- “如果不是企业版呢?”
这些句子单独拿去检索,通常几乎没法用。
系统必须先结合前文,恢复出更完整的查询对象,后面检索才有可能稳定。
一个常见误区
很多人会觉得:
- 用户原话最真实,所以当然最适合拿去搜
这不一定。
更稳的理解是:
- 用户原话最适合对话,不一定最适合检索
系统要做的不是篡改问题,而是把对话语言转成更适合召回的查询形式。
一句话总结
用户问题进入 RAG 后,第一步往往不是直接检索,因为用户原话服务的是交流,而检索器需要的是更清晰、更稳定的查询信号。先做问题理解,往往比直接原样搜索更稳。