最近在搭一个RAG问答系统,用的ChromaDB,embedding模型是bge-large-zh,文本切了512字符带overlap。结果跑了一批测试集,召回率(Recall@5)居然比直接用ES的BM25还低快10个点。我检查过,query和chunk都是同一个embedding模型,也试过调相似度阈值,但检索回来的片段就是不太对,感觉语义近的反而没排前面。是不是我切的粒度有问题?还是说向量数据库做RAG本身就该跟关键词混合召回?求真实经验,别复制教程。
用向量数据库存RAG的chunk,结果召回率还不如直接BM25,心态崩了
全部回复
共 27 条混合召回才是正解,BM25保底再加向量重排,单靠embedding在中文长文本上确实容易翻车。
bge-large-zh做dense召回对短query本来就不稳,试试混合召回加RRF融合,别纯靠向量。
我之前也踩过这坑,后来发现512切太大了,改256加重叠,BM25和向量各取一半结果才稳。
BGE-large在长文本上的表现其实没那么稳,512字符带overlap切出来每个chunk语义太散,向量空间里可能被稀释了,反而BM25靠关键词硬匹配能抓住核心实体。你可以试试切成256甚至128,或者干脆用句级粒度做召回再合并段落,我调过类似问题,粒度细了以后Recall@5能涨不少。另外bge-large-zh对短query和长文档的相似度计算有bias,建议你检查下是不是query编码时没加指令前缀,这个模型中文检索需要带特定prompt,不加的话效果会打折。混合召回确实是更稳的解法,但别急着上重排序,先看看单路召回的上限在哪,你可以把embedding换成bge-m3或者试试用query generation扩充一下查询再检索,很多“语义近”其实是伪相关,模型没学到你要的意图。还有个小坑,ChromaDB默认的余弦距离和ES那边的打分尺度不一样,你对比的时候最好先统一用NDCG或者Recall@K看相对排序,别被绝对分数带偏了。我现在做生产系统基本是BM25保底加向量召回取并集再rerank,纯向量在中文场景下除非领域微调过,不然真不一定打得过关键词。
512字符对bge-large-zh来说其实偏长了,这模型最佳粒度一般128-256,切太长语义会被稀释,召回自然拉胯。BM25反超不奇怪,关键词匹配在短query上本来就猛。建议你先按256带点overlap重切一版对比下,再考虑加个rerank或者RRF做混合召回,纯向量单打独斗确实容易翻车。
512字符太长了,语义被稀释,试试300以内加混合召回,纯向量本来就容易翻车。
纯向量召回对短query确实容易飘,试试bge加指令前缀,或者直接上混合检索,BM25兜底比硬调阈值管用。
纯向量召回在中文短query上翻车太常见了,bge-large-zh对长chunk的语义压缩其实挺吃亏的,512字符塞进去,关键信息容易被稀释。你试试把chunk缩到200字左右,或者用bge-m3那种支持多粒度的,召回能明显不一样。另外BM25赢向量不丢人,很多线上系统就是混合召回加rerank,单靠一路本来就容易漏。