最近用LangChain搭了个RAG问答系统,本地测试时top-k命中率还行,结果一上线跑真实用户query就崩了。比如用户问“工资什么时候发”,我库里明明有《薪酬管理制度》相关条文,但检索出来的全是别的文档碎片,甚至把离职流程都带出来了。我怀疑是embedding模型对口语化表达不敏感,但换了BGE-large还是不行。现在看chunk切分也感觉有问题,按固定200字切,很多语义被截断了。想请教下大家,遇到这种线上检索效果差的情况,一般从哪些维度排查?是先调chunk大小还是换rerank策略?有没有靠谱的评估方法(比如构造golden set)能提前发现问题?求实战经验,感谢!
RAG项目上线后效果翻车,检索准确率暴跌,大佬们怎么排查的?
全部回复
共 27 条先看query改写和切分吧,口语化query建议加HyDE或同义扩展,固定200字确实容易切碎语义。
我之前也踩过类似的坑,本地测试用自己编的问题命中率挺高,一上真实流量就原形毕露。你这个“工资什么时候发”检索出离职流程,我感觉不光是embedding的问题,大概率是chunk切分把薪酬制度里的关键段落切碎了,导致向量语义偏移,反而跟离职流程里某些“工资结算”字眼更接近。固定200字切确实太粗暴了,试试按标题层级或者语义段落切,再加个overlap,效果会稳不少。另外BGE-large对口语化query其实还行,但你得确认下线上query有没有做预处理,比如去掉“什么时候”这种停用词干扰,或者用query改写扩展一下。rerank这块建议先别急着上,先把召回阶段的chunk质量修好,不然rerank也是垃圾进垃圾出。评估的话,golden set一定要建,但别只标答案,要标出哪些chunk是应该被召回的,这样能分别看召回率和准确率。我一般会抽100条真实query,人工标好相关段落,跑个recall@5和mrr,基本能提前发现大部分问题。
工资这种口语query和制度文档的表述差太远了,光换embedding模型治标不治本。我建议先搞个几十条真实query的golden set,把召回率量化出来再动手调,不然你都不知道改完到底有没有变好。chunk按200字硬切确实容易把条文拦腰砍断,试试按标题层级或者语义边界切,再叠个rerank基本能救回来一大半。
先把用户真实问法收集起来做个小golden set,不然调chunk和rerank都是瞎猜。
口语化query和文档的语义gap确实容易被忽略,你换BGE没效果可能问题不在模型本身。建议先拿几条真实badcase把检索链路拆开看:是召回阶段就没捞到正确chunk,还是捞到了但排序被挤下去。固定200字切分对制度类文档太粗暴了,试试按标题层级或语义段落切,再叠个rerank会稳不少。golden set一定要早点建,从线上日志里捞高频query人工标,比拍脑袋调参靠谱多了。
线上翻车太常见了,本地测试那点query根本代表不了真实分布,用户的口语化表达和文档里的书面语之间gap比想象中大得多。你换BGE-large没用,大概率不是模型本身的问题,而是query和文档压根不在一个语义空间里,试试加个query改写或者用HyDE先生成假答案再检索。chunk按200字硬切确实坑,薪酬制度这种条文跨段被截断后,单块既没有完整语义也没有关键词锚点,检索不崩才怪。建议先别急着上rerank,把chunk按标题层级或语义边界重新切,再在召回阶段加个BM25混合检索兜底,纯向量对“工资”“薪酬”这种词面匹配其实很弱。评估这块golden set一定要提前建,但别只标query和答案,要把相关chunk的id也标上,不然你连是召回问题还是排序问题都分不清。另外线上query日志记得埋点,把bad case捞出来聚类看看,很多时候是用户问法跟你预期完全不一样。调优顺序我自己的经验是先修切分和混合召回,再考虑rerank,最后才动embedding,不然前面漏了后面怎么排都白搭。
口语化query和制度文档的语义gap确实挺坑的,BGE对“工资啥时候发”这种问法可能真不如query改写来得直接。我一般会先看召回列表里有没有正确文档,有的话就是排序问题,加个rerank基本能救;没有的话就得回头查chunk切分和embedding了。固定200字切确实容易把条文切碎,试试按标题层级切或者加overlap。golden set一定要早点建,拿真实用户问法去测,别自己编问题,不然永远发现不了线上那种口语化偏差。