最近在搭一个针对公司内部文档的RAG问答,用的bge-m3做embedding,向量库用的milvus。文档是各种技术方案和会议纪要,我按固定长度500字切的,重叠50字。现在问题是用户问一个具体问题,比如“某某项目上次评审定了什么结论”,检索出来的top5里经常只有1条是相关的,其他全是碰巧含有相同关键词但内容无关的片段。我用的是余弦相似度,也试过调低score阈值,但要么召回太少,要么噪声更多。想问问大家,这种混合类型的文档是不是不应该用固定窗口切?还是说需要在召回后加一层重排?有没有比较成熟的实践思路?谢谢。
RAG检索老召回一堆无关chunk,是不是我切分方式有问题?
全部回复
共 46 条固定500字切确实容易把会议纪要里结论和上下文切散,问项目评审这种问题尤其吃亏。可以试试按标题或段落切,再在chunk前面拼一句来源和章节摘要,召回质量会好不少。重排也值得加,bge-reranker这类模型对top20精排一下,噪声能压下去很多。另外milvus里可以试试混合检索,关键词加向量一起召回,纯靠embedding对内部缩写和项目名挺吃亏的。
固定500字切确实容易把技术方案和会议纪要切碎,语义边界全丢了。我们之前也踩过这坑,后来改成按标题层级+段落切,效果好了不少。不过光靠切分不够,召回后加个rerank模型(比如bge-reranker)过滤一下,top5里噪声能压下去一大半。你们文档里会议纪要那种口语化的内容,是不是单独走一套prompt做摘要再入库会更稳?
固定500字切分对这种混合文档确实容易出问题,技术方案和会议纪要的信息密度差太多了,前者一段可能就讲一个完整设计,后者一句话可能就是一条结论,硬按字数切很容易把关键结论和上下文割开。你这个场景我建议先别急着上重排,而是换成按语义或结构切,比如按标题层级、段落、发言人来分,尽量让每个chunk自带一个完整语义单元,再控制长度范围而不是死磕500。另外bge-m3本身支持多粒度,你可以试试给每个chunk补一句简短摘要或标题再embedding,召回质量会明显不一样。top5里只有1条相关,其实也说明纯向量召回在这种情况下不够,加一层rerank是值得的,bge-reranker或者cohere的都可以,先粗召回20条再精排到5条,噪声会降不少。还有个细节是score阈值别单独调,配合rerank分数一起看,不然确实容易两头不讨好。如果文档里项目名、版本号这类实体很多,也可以考虑混合检索,向量加BM25,对“某某项目评审结论”这种问法会更稳。
固定长度切就是容易这样,试试按标题或段落切,再加个rerank模型效果会好很多。
固定500字切确实容易把会议纪要里“结论”和上下文割开,检索时单靠embedding很难抓住语义重点。建议试试按文档结构切,比如技术方案按标题层级、纪要按议题分段,再配合bge-m3的多粒度表示。重排这步挺关键的,bge-reranker或者cohere rerank加一层,top5里混进来的噪声能压下去不少。你这场景其实更适合混合检索,关键词召回兜底加向量语义,光调阈值确实两头不讨好。
固定500字切确实容易把技术方案和会议纪要切碎,语义边界全丢了。你可以试试按文档结构切,比如按标题层级或者段落切,会议纪要就按发言人或议题分块,效果会好很多。另外bge-m3本身支持稀疏+稠密混合检索,你可以在milvus里同时用这两种向量召回再融合,比单靠余弦相似度强不少。重排那层也建议加上,bge-reranker跑一遍top20,噪声能压下去一大半。