最近在做一个人事政策问答的RAG系统,用的BGE-M3做embedding,chunk切的是200字+50字overlap。现在遇到的问题是:用户问“年假和病假能连着休吗”,检索回来的几个片段分别讲年假规则、病假规则、请假流程,单独看都对,但LLM回答时只会引用单个片段,经常漏掉关键约束(比如病假超过10天要医院证明)。试过调top_k从3改到8,结果更乱,回答开始自说自话。也试过在prompt里强制“结合所有片段”,但效果不稳定。是不是我该换个切分策略,或者用重排序模型先过滤一遍?还是说这种多条件组合问题压根不适合用RAG硬做?求有经验的前辈指点下方向。
RAG系统里检索结果太碎,怎么让LLM把多段信息整合好?
全部回复
共 7 条试试把病假证明这类约束条件单独抽出来做成规则映射,比硬让模型拼碎片靠谱得多。
top_k加大确实容易让模型抓不住重点,我一般会加个rerank模型卡一道,只留最相关的三四段。多条件组合的问题,感觉关键还是chunk切的时候别把年假病假这种关联规则拆太散,可以试试按条款或小节切。另外prompt里与其说“结合所有片段”,不如直接让它逐条核对每个条件再下结论。这种问题RAG能做,但指望一次检索就完美挺难的,不行就加个query改写把子问题拆开。
你这个情况我去年做HR知识库时也踩过,基本一模一样。top_k调大反而更乱,是因为召回里混进了大量语义相近但条件不同的片段,模型看到矛盾信息就开始自己编了。我觉得核心问题不在切分,而在于你缺一层“条件聚合”的预处理。BGE-M3检索出来的片段是按语义相似度排的,它根本不管“年假”和“病假”之间的逻辑关系,所以模型只能挑一个最像的来答。你可以试试在检索后加个轻量重排,但重排也解决不了跨片段推理的问题。真正管用的做法是给这类多条件问题单独建一条路径:先用query分类判断是不是组合型问题,如果是,就分别召回年假和病假两个子查询的结果,再拼成结构化上下文喂给LLM,明确告诉它“这是两个独立规则,需要合并判断”。另外prompt里别写“结合所有片段”,改成“逐条列出每个片段的约束,再判断是否冲突”,模型会老实很多。这种多条件组合确实不适合纯靠RAG硬做,加个规则引擎或者小分类器兜底会稳得多。
先加重排序把相关片段压到最前,再在prompt里让模型逐条列出约束,不然它真容易漏。
你这个情况我之前也踩过,本质上是检索粒度跟问题粒度对不上。用户问的是组合约束,但你的chunk是按段落切的,每个片段只覆盖一个子话题,LLM拿到手就是三块拼图,它不知道要拼。top_k调大只会引入更多噪音,反而稀释了关键约束的权重,所以回答开始飘。
重排序模型值得试,但别指望它解决所有问题,它只能帮你把最相关的片段排前面,解决不了“跨片段推理”这件事。真正有用的是换个思路:在检索之后加一层“多片段聚合”的处理,比如让LLM先对每个片段做一次信息抽取,把年假天数、病假证明门槛、连休限制这些结构化字段提出来,再基于抽取结果生成回答。这样比直接让LLM看原文片段要稳得多。
切分策略上,200字对政策类文档可能偏碎,可以考虑按条款或按小节切,保证一个chunk内至少是一个完整的规则单元。另外你可以在chunk的metadata里加上条款编号或章节路径,检索时把同章节的片段一起带出来,减少信息割裂。
还有个容易被忽略的点:这种多条件组合问题,其实可以在query侧做一下改写或分解,比如把“年假和病假能连着休吗”拆成“年假规则+病假规则+连休限制”三个子查询分别检索,再合并结果喂给LLM,比单query硬检索召回率高不少。
先加重排再喂给模型,碎片段太多它确实抓不住重点,我这边top_k压到5反而稳。
试试用重排序模型先筛一遍,再让LLM按条件逐条对照,多跳问题别硬塞给单次检索。