最近在搭一个简单的RAG问答系统,用的是LangChain加Chroma。文档库大概有几百篇技术文档,用户问个问题,检索出来的chunk经常有十几二十个,里面很多内容其实跟问题关系不大,甚至完全无关。直接全塞给LLM,回复质量很差,有时候还会被无关信息带偏。试过调高相似度阈值,但这样又容易漏掉真正相关的信息。想问问大家,有没有什么好的方法做检索后重排序?或者有没有办法让LLM自己先过滤一遍再回答?感觉这步处理不好,整个RAG效果就卡住了。
RAG系统检索到的文档太多太杂,怎么让LLM只挑有用的?
全部回复
共 125 条我最近也在弄这个,试了一圈感觉重排序比调阈值靠谱多了,像bge-reranker那种模型效果立竿见影,不过得注意别把延迟拖太高。另外你也可以试试让LLM先对chunk做个相关性打分再决定用哪些,虽然多一步调用,但能省掉后面乱回答的麻烦。几百篇文档其实不算多,要不要考虑直接上更细粒度的元数据过滤?比如按文档标题或者章节先粗筛一轮再进向量检索,这样召回质量能稳不少。
试过用Cohere Rerank或者bge-reranker做重排序没?先粗筛top50再精排取前5,比单纯调相似度阈值靠谱很多。另外你可以在prompt里加一步,让LLM先判断每个chunk跟问题的关联度,输出“有用/没用”再决定要不要参考,这样能减少噪声干扰。不过注意别让过滤本身吃掉太多token,最好先压缩一遍再给模型。
试试先粗召回再让embedding模型rerank,比如cohere的API,能把不相关的chunk压掉不少,保住阈值下限。
可以试试给检索结果加个LLM自带的打分过滤,让模型先判断题文相关再答,LangChain里写个自定义链就行,效果比阈值稳。
我之前也卡在这一步,后来加了个cross-encoder做重排序,效果提升挺明显的。就是先粗召回个二三十条,再用rerank模型精排取top5,比单纯调阈值靠谱多了。LLM自己过滤的话可以试试让它先输出相关段落编号再回答,不过会多花token,得看你怎么权衡。
我之前也卡在这一步,后来加了cross-encoder做重排序,效果提升挺明显的,你可以试试bge-reranker这种,比单纯调阈值靠谱多了。另外检索阶段可以多召回一些,比如top50,再用rerank压到top5给LLM,这样既不容易漏也不会太杂。让LLM自己过滤也行,但得多一轮调用,成本和延迟都上去了,看你能不能接受。还有个小技巧是把chunk切小一点,粒度细了相关性判断会更准。