面试官你好,这道题问的是[[RAG]]效果不好怎么排查,我觉得它本质上是在问:你怎么把一个端到端的黑盒问题拆成模块级问题,然后找到那个最薄弱的环节。我的思路是分层定位、逐层验证,核心就一句话,先隔离变量,再对症下药。
具体来说,我会先问一个问题:如果我把一个完美文档直接塞给生成模型,它能不能给出好答案?这就是所谓的黄金文档实验。我找几个bad case,人工写一份理想文档,然后强制让生成模型基于它输出。如果结果明显变好,那问题大概率在检索侧;如果还是不行,那生成模型本身就有问题。这一步能快速划分责任边界,避免盲目调参。
假设黄金文档实验告诉我们检索有问题,那我会看几个关键指标。首先是 Recall@K,比如K取5或10,看正确答案是不是在前几个结果里。如果召回率低于70%,那检索模块基本要重做。另一个是排序质量,可以用MRR或者NDCG,但说实话,线上我更多依赖人工抽检,拿一批真实用户query,自己判断理想文档应该是什么,再对比实际检索结果,这样最直观。常见失败场景比如用户问“退款多久到账”,结果检索出来一堆退货政策,那肯定是[[embedding]]和query理解之间的对齐出了问题。我还会看query和top1结果的向量相似度,如果低于0.6,说明语义空间没对齐,可能需要优化query改写或者换embedding模型。
如果检索没问题,那就看生成侧。核心指标是 [[Faithfulness]],也就是生成内容是否忠实于检索文档。我会用NLI模型或者人工标注,看有没有胡编乱造的内容。另一个是答案相关性,就是答没答到点子上。比如用户问“这个订单为什么异常”,模型却开始解释异常订单的定义,那就是相关性差。这里有个坑:生成模型在长上下文场景下容易丢失信息,特别是文档中间部分。我会做个消融实验,逐步截断输入文档,看性能怎么变化,如果截到一半效果反而变好,说明模型对长上下文理解有瓶颈,那可能需要改进prompt或者用 [[Sliding Window]] 策略。
最容易被忽视的是协同环节的问题。有时候检索结果明明很相关,生成模型却选择性失明,或者多份文档信息冲突时生成混乱。比如客服场景,用户问“这两个优惠能同时用吗”,检索出来两份政策文档,一份说满减可用,一份说不可用,模型可能就胡编一个答案。这种问题我会看注意力可视化,或者做个文档去重实验,把冗余信息去掉看效果是否提升。还有一个常见问题是位置偏见,把相关文档放在第一位和不放在第一位,输出可能完全不同。
说到这,我顺便提一个我比较关注的方向:动态检索。就是生成过程中根据已生成的token实时调整检索策略,而不是一次检索完。这在多跳推理场景下特别有用,比如用户问“张三在A公司的职位是什么,他后来跳槽去了哪”,一次检索很难覆盖完整信息链。当然这也有代价,就是延迟会明显增加。
所以整体上,我会把RAG问题排查看成三步:先用黄金文档锁定责任方,再用指标和人工分析细化根因,最后针对性优化。如果检索和生成单独测都好但合起来差,那就去优化协同,比如改进prompt让模型更关注文档、加文档压缩、或者用动态检索。最怕的就是不看数据,上来就调embedding或者换模型。