最近在用 LangChain + Chroma 搭一个内部文档问答,embedding 用的 bge-m3,检索 top5 里肉眼能看到正确答案就在第 2 条。但把 context 拼进 prompt 后,模型(qwen2.5-7b)要么答成另一段的内容,要么直接说“文档中未提及”。已经试过调 chunk size 和 prompt 模板,效果都不稳定。想问下这种情况一般怎么排查?是 rerank 的问题还是 prompt 里 context 顺序有影响?有没有人遇到过类似情况?
RAG 检索出来的内容明明是对的,为什么 LLM 还是答非所问?
全部回复
共 6 条这种情况太常见了,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的命中率明显稳了不少。
我之前也遇到过类似问题,后来换了方案。
这个情况我遇到过,大概率不是检索的问题,而是 context 拼进去之后模型注意力被稀释了。top5 里正确答案在第2条,但如果其他4条里有语义相近但结论不同的段落,7b 这种小模型很容易被带偏,尤其是 chunk 之间有重叠内容的时候。你可以先把 top5 缩到 top2 或者 top3 试试,看答案稳定性有没有变化,如果明显好转那基本就是 context 噪声的问题。另外 qwen2.5-7b 对长 context 中间位置的敏感度确实一般,有个土办法是把最相关的那条放到 context 最前面或者最后面,别夹在中间。还有个容易被忽略的点是 prompt 里有没有明确要求“只根据以下内容回答,不要引入外部知识”,小模型有时候会自己脑补然后跟 context 打架。rerank 的话 bge-reranker 加一层确实能提纯,但你现在的现象更像是模型没抓住重点而不是排序错了。建议先做个消融:只喂第2条 chunk 看它能不能答对,能答对就说明是 context 干扰,答不对那就是 prompt 或者模型本身的问题了。