最近在用 LangChain + Chroma 搭一个内部文档问答,embedding 用的 bge-m3,检索 top5 里肉眼能看到正确答案就在第 2 条。但把 context 拼进 prompt 后,模型(qwen2.5-7b)要么答成另一段的内容,要么直接说“文档中未提及”。已经试过调 chunk size 和 prompt 模板,效果都不稳定。想问下这种情况一般怎么排查?是 rerank 的问题还是 prompt 里 context 顺序有影响?有没有人遇到过类似情况?
RAG 检索出来的内容明明是对的,为什么 LLM 还是答非所问?
全部回复
共 4 条这种情况太常见了,top5里明明有正确答案但模型就是不用,我遇到过好几次。有个容易忽略的点是context拼接的方式,如果你只是简单把5条chunk用换行拼起来,模型很容易被第一条带偏,尤其是第一条看起来也相关但实际不对的时候。bge-m3的检索质量其实还行,但它的相似度分数分布可能很平,导致真正对的那条在语义空间里没拉开差距,模型自己也不会去"挑"。可以试试把最相关的chunk放到context的最前面和最后面各一次,中间放其他的,很多模型对首尾位置更敏感。另外qwen2.5-7b这个尺寸本身指令跟随就偏弱,你prompt里如果没明确说"只根据以下内容回答,如果内容中有相关信息请优先使用",它可能会自己脑补或者过度保守。还有个小技巧是先把检索到的chunk做个轻量rerank,用bge-reranker或者简单的cross-encoder,top5重排后往往能把真正对的那条顶到第一。最后检查一下你的chunk里是不是混了标题或者页眉页脚这种噪声,有时候答案在但被无关文本稀释了,模型就判断成"未提及"。建议先做个消融实验,只放第2条chunk进prompt看模型能不能答对,如果能,那就是context组织的问题而不是检索的问题。
试试把context压短点,7b模型对长上下文容易分心,顺序放关键段最前。
我遇到过类似情况,后来发现是 prompt 里 context 塞太多,模型注意力被稀释了。qwen2.5-7b 这种小模型对噪声挺敏感的,top5 里只要有两三条不相关的,它就容易跑偏。你可以试试先只喂 top2 或者加个 rerank 把分数卡一下,另外 context 顺序把最相关的放最前面也有帮助。
qwen2.5-7b这个尺寸确实容易犯这毛病,context一长就开始注意力涣散,尤其你top5里还混着几段无关内容的时候。建议先别急着上rerank,把top5砍到top2试试,很多时候噪声少了模型反而能抓住重点。另外bge-m3的相似度分数可以看看,第2条如果分数跟第1条差挺多,那大概率是排序把真正相关的挤下去了。我这边加了个简单的重排(哪怕就用cross-encoder小模型)之后,7b的命中率明显稳了不少。