最近在做一个内部知识库的RAG问答,用的bge-large-zh,chunk大小设的400字带50字重叠,faiss做向量检索。问题就是用户问“报销流程需要几步”这种时候,经常召回一些完全不相关的内容,甚至把别的部门的制度也捞出来了。我试过调top_k从5降到2,还是不行,召回来的片段明明跟问题关键词重合度不高,但向量相似度却很高。
RAG系统检索结果总是不准,是chunk切太细还是embedding模型选错了?
全部回复
共 25 条你这情况八成不是chunk的问题,400字带重叠其实挺合理的。bge-large-zh对“报销流程”和“报销制度”这种语义相近但意图不同的query区分度确实一般,容易把制度类文本排前面。建议你加个关键词过滤或者BM25混合检索,光靠向量召回在内部知识库场景下很容易翻车。另外可以试试换个指令微调过的embedding,比如bge-m3或者gte系列,对中文业务query的区分会好一些。
400字切太细了,报销流程这种问题往往跨好几个段落,切碎了上下文就断了,模型只能靠零散关键词硬匹配。试试先按标题或段落切,每块800到1000字,重叠留个100字左右。另外bge-large-zh对长query其实还行,但你得看看是不是没加指令前缀,有些版本检索时要带“为这个句子生成表示用于检索”这类提示,不加效果差挺多。还有个坑是faiss默认内积,bge得归一化后用余弦,不然相似度会虚高。
400字chunk对报销流程这种步骤性内容可能偏大了,容易把不同部门的信息混在一起。你说的关键词重合低但相似度高,很可能是bge对制度类文本的语义区分度不够,试试换个领域微调过的模型或者加个rerank。另外faiss本身只是向量召回,缺少关键词过滤,可以考虑hybrid检索把BM25加进来。我之前也遇到过类似问题,最后发现是chunk里混了太多无关上下文,按标题层级切效果会好很多。
你这个问题大概率不是chunk的锅,400字带重叠做制度类文档其实挺合适的。bge-large-zh对长query和短query的语义匹配本来就有点偏,关键词重合低但向量相似度高,说明模型把“部门制度”这类语境当成主要信号了,反而忽略了“报销流程”这个核心意图。可以试试在检索前加一层query改写,把“报销流程需要几步”拆成更具体的子问题再分别召回,或者用bge-reranker对top20做精排,光靠向量相似度确实容易把语义相近但业务无关的内容捞进来。
这个问题其实挺典型的,我前段时间也踩过类似的坑。bge-large-zh本身没问题,但你描述的现象更像是embedding把“报销”“制度”“部门”这类词拉到了一个语义空间里,导致跨部门的制度片段都被吸过来了。400字chunk对中文来说偏大了,一个chunk里可能混了好几个语义段落,embedding只能给一个向量,自然就糊了。你可以试试把chunk降到150-200字,重叠保留30字左右,同时加上metadata过滤,比如部门字段,检索时先按部门筛再算相似度。另外faiss的IndexFlatL2对归一化向量不太友好,换成cosine或者IP会更稳。关键词重合度低但相似度高,说明模型抓的是主题氛围而不是具体意图,可以加一个BM25做混合检索,把关键词信号补回来。还有个小技巧,把用户问题先用LLM改写成更具体的查询再embedding,召回质量会明显不一样。