最近在搭一个内部文档问答的RAG,用的bge-m3做embedding,chunk大小试了256和512,重叠设了50。问题是有时候问“报销流程”,召回的前十名里一堆是合同审批、采购付款的内容,虽然也沾边,但真正讲报销步骤的那几段反而排到很后面。我怀疑是chunk切分把完整流程截断了,语义不完整导致的。想请教下各位,对于这种操作流程类的文档,是应该按段落切还是按固定长度切?有没有必要先做一下标题层级识别再切?另外重排模型对这种情况帮助大吗?
RAG检索老召回一堆无关片段,chunk切分到底该按啥来?
全部回复
共 5 条操作流程类的文档真不太适合纯按固定长度切,你试试按语义块或者直接按段落切,bge-m3本身对长文本也有一定容忍度,256和512其实都可能把“报销流程”里的前置条件、审批节点、后续动作给拆散了。我做过类似的采购流程问答,后来改成先用规则识别文档里的标题层级(比如“一、二、三”或者“步骤1、步骤2”),把每个完整流程节点作为一个chunk,召回率提升挺明显的。重排模型对这种情况帮助确实有,但前提是检索回来的片段本身要相对完整,不然重排也只是在残缺的碎片里挑相对不残缺的,效果有限。你可以试试先做一下简单的文档结构解析,比如用正则或者LLM提取标题和段落归属,再决定每个chunk的边界,会比盲目调chunk size和overlap高效得多。另外重叠设50有点小,如果按段落切的话,段落之间如果有关联词(比如“上述步骤”),建议把上一个段落的结尾和下一个段落的开头各带上一部分,或者直接按小节切,别让流程断在半路。我之前还试过把每个标题下的内容单独作为一个chunk,然后给chunk加上标题前缀(比如“报销流程-提交申请”),这样embedding能更好区分不同流程的上下文。你那个“合同审批”和“报销流程”容易混,大概率是它们共享了相似的动词和名词结构(比如“审批”“提交”“部门”),重排模型如果训练数据里对这种细粒度区分不敏感,也可能拉不开差距,所以还是得先从切分源头解决。
操作流程类文档真别按固定长度硬切,我之前也踩过这坑,后来改成先识别标题层级,把每个步骤和它的说明尽量包在同一个块里,召回准了不少。重排模型对这种情况帮助挺大的,尤其你这种“沾边但不对”的噪声多,rerank能把真正讲流程的段落顶上去。另外重叠设50可能不够,流程文档里步骤之间经常有承上启下的句子,试试128的重叠,或者干脆按语义完整句来切。
我之前也踩过这个坑,bge-m3对长文本的语义捕捉其实挺吃结构的,固定长度切很容易把“流程步骤”拦腰截断。建议你先做标题层级识别,按章节或者步骤块切,比如“报销流程”这个二级标题下的内容作为一个chunk,比纯按字数靠谱得多。重排模型(比如bge-reranker)对这种情况帮助很大,它能把那些“沾边但不对”的段落压下去,我实测top5准确率能提30%以上。另外重叠50对流程类文档可能不够,试着把重叠提到100-150,保证步骤间的上下文连贯性,你可以先拿几个典型问题做个A/B测试看看。
强烈建议先做标题层级识别再切,流程类文档按段落切真不如按语义块切,重排模型对这类问题帮助有限。
我之前也踩过这个坑,操作流程类文档固定长度切确实容易把步骤拦腰截断。后来改成按段落切,再配合标题层级识别,效果会好很多,至少能保住“报销申请→审批→打款”这个完整链路。重排模型对这类场景帮助挺大的,尤其bge-m3的分数不太能直接反映语义相关性,加个bge-reranker能把真正讲步骤的段落顶上去。另外建议你试试在切分时把二级标题也塞进chunk里,系统能更容易判断当前内容属于哪个流程环节。