这道题问的是检索结果不对目标答案的原因和优化方向,其实本质是问检索和生成之间的对齐问题。我们做[[RAG]]时经常会遇到:明明数据库里有正确答案,但检索模块就是没把它捞上来,或者捞上来了但排序太低,导致生成器没看到。那原因可以从数据、检索、查询三个层面拆,优化也对应着来。
先说数据层面。很多人上来就调模型,但我会先检查文档质量和[[Chunk]]策略。举个例子,客服退款场景下,用户问‘退款多久到账’,文档里可能写的是‘退款处理时效为1-3个工作日’,但如果你把这句话和‘退款条件’、‘退款流程’切到一个块里,或者块太小把‘1-3个工作日’截断了,那检索时语义就不够。所以数据预处理是前提,分块策略直接影响召回天花板。如果文档本身质量差,比如过时、矛盾,那后面怎么调都白搭。
再来说检索策略。最常见的问题是单一向量检索的召回瓶颈。用户口语化表达‘我的钱什么时候退回来’和文档正式说法‘退款到账时间’在语义空间里可能离得远。我的做法是**[[混合检索]]**,把[[BM25]]关键词召回和向量召回结合起来,结果做加权融合。你可以这么理解:向量负责语义相似,关键词负责精确匹配,比如订单号、错误码这种就得靠关键词。但混合检索也有坑,如果权重调不好,比如关键词权重太高,反而会召回一堆噪音。上线时我会先离线跑一批bad case,看哪些是向量没召回、哪些是关键词没召回,再调比例。
再进一步,检索出来Top-K可能还是不准,这时候要加[[Rerank]]。用轻量级的[[Cross-Encoder]]对候选结果精排,它比[[双塔]]模型精度高,能纠正向量排序的偏差。比如用户问‘苹果有什么新品’,向量可能把水果苹果的文档排前面,但Cross-Encoder能根据上下文判断用户要的是电子产品。不过重排有延迟成本,所以我会把它放在最后几位的候选集上,而不是全量。
查询侧优化也很关键。用户问题往往短、模糊,我会用LLM做查询改写,比如把‘退款多久’扩展成‘退款处理时效是几个工作日’。还有个技巧叫HyDE,先生成一个假设文档再检索,能拉近查询和文档的语义距离。但这里有个风险:如果LLM改写错了,比如把‘苹果’错误扩展成‘水果’,反而会引入噪音。所以我会加置信度过滤,改写后和原查询做相似度对比,分太低就弃用。
另外多说一句,检索正确但生成错的情况也很常见,这其实涉及[[Faithfulness]]问题,比如生成了文档里没有的细节。这时候优化方向就变成提示工程或微调了。
所以整体上,我更倾向把RAG系统看成检索和生成的协作,优化时要先诊断是哪个环节的问题。如果检索没召回,先看数据分块和混合检索;如果召回但排序低,加重排;如果检索正确但生成错,才去动生成器。盲目堆技术容易事倍功半,关键是基于bad case做迭代。