吴师兄学大模型公众号文章

面试官问:“RAG重排漏证据怎么办?”我:“换个更强的重排模型。”他:“候选名单没它,换谁来排?”

吴师兄学大模型

公众号 · 11 篇文章

用户问:“夜间打车报销要先审批吗?”知识库里明明有一句“夜间打车报销必须先取得主管审批”,RAG 最后给出的答案却没有这条要求。

看到这种结果,很多人会先怀疑 Reranker:是不是模型太小,相关性判断不准,换个更强的重排模型就好了?这个方向并非完全错误,但它跳过了两个更早的问题:正确段落有没有进入候选名单?进入以后,关键句有没有真的出现在模型输入里?

RAG 的检索链路通常先从知识库找出一批候选,再让 Reranker 对问题和候选逐对打分,最后保留少量内容交给生成模型。Reranker 擅长在已经拿到的材料里重新排序,却不能替前面的召回补回一条根本没交给它的段落。

下面用一份合成的报销资料,把候选缺失、输入截断和排序错误分开。名单、问题与证据位置都是人工设定的,只用来说明排查方法,不假装是真实公司的制度或线上事故。

Reranker 为什么找不回未入场的 D?


假设粗召回按相关性给出六个片段,顺序固定为 A、B、C、D、E、F:

片段
内容概要
是否含本题证据
A
通用出差申请
否
B
市内交通资料
否
C
发票与凭证
否
D
夜间出行审批
是,关键句在尾部
E
餐费资料
否
F
跨城交通附件
只与跨城问题有关

系统配置 TopN=3,意味着只有 A、B、C 会进入重排。Reranker 无论怎样调整这三条的顺序,都不可能选出 D。它能改变的是候选之间的相对位置,不能凭空创造一条没有入场的候选。

这也是为什么“知识库里有答案”和“这次请求召回了答案”是两件事。文档已经入库,只能说明材料存在;过滤条件、切块方式、召回模型以及 TopN 都可能让目标片段停在候选集之外。

对于标准的重排步骤,最终保留的 TopK 应当来自输入的 TopN。如果系统在重排阶段又调用搜索补充新资料,那是另一项召回能力,需要单独记录新候选从哪里来,不能把它混成 Reranker 自己找到了证据。

开发者拿着目标D站在候选入口外,评审台上只有A、B、C

开发者拿着目标D站在候选入口外,评审台上只有A、B、C

遇到“正确证据没进最终答案”,第一步不是看重排分数,而是拿着目标证据的标识往前查:它是否完成入库,是否通过元数据过滤,在粗召回中排第几,最后有没有进入本次 TopN。D 没入场时,应修召回、过滤或候选数量;直接换重排模型,解决不了入口缺失。

D 入场了,模型实际看到了什么?


把 TopN 从 3 扩大到 4,D 终于进入候选名单。此时日志里能看到 D 的片段 ID、来源页码和完整原文,看起来条件已经满足。但 Reranker 实际打分的并不一定是日志里那份完整原文,而是经过输入模板拼接和长度处理后的文本。

为了单独观察这个差别,我们给“问题 + 分隔符 + 候选正文”设置一个人工字符预算。问题和分隔符占 17 个字符,总预算为 64,于是正文只剩 47 个字符。D 的原文有 103 个字符,真正回答问题的句子位于 [87,103),正好被裁在窗口外。

此时系统同时拥有两种看似矛盾的记录:候选日志显示 D 已命中,实际成对输入却只保留了 D 开头的资料归档说明。Reranker 看不到“必须先取得主管审批”,自然无法依据这句话给 D 打分。把这种结果直接归因为模型不理解审批规定,会修错层。

开发者核对D文件,尾部审批句落在人工输入窗口外

开发者核对D文件,尾部审批句落在人工输入窗口外

保持 A、B、C、D 和原文完全不变,只把人工预算扩大到 256,D 的成对输入变为 120 个字符,审批句才完整进入可见范围。这个变化只证明模型有机会看到关键句,还没有证明它一定会把 D 排到第一。

三种状态放在一起,断点就很清楚:

状态:TopN=3

D 是否在候选中:否

审批句是否在实际输入中:否

当前能判断什么:先修召回入口

状态:TopN=4、预算 64

D 是否在候选中:是

审批句是否在实际输入中:否

当前能判断什么:先修输入截断

状态:TopN=4、预算 256

D 是否在候选中:是

审批句是否在实际输入中:是

当前能判断什么:才能继续评价排序

实际模型通常按 token 而不是中文字符计算长度。问题、候选、特殊标记各占多少预算,截断较长的一侧还是只截第二段,也取决于具体模型、封装和版本。因此,排查时要保存或重建真正送入模型的 tokenized 输入,而不能拿截断前的原文代替。

来源元数据也不能冒充模型输入。日志里保存了“第 4 页、夜间出行审批”,只说明系统知道片段来自哪里;这些字段没有拼入成对文本时,Reranker 就不会自动看到它们。同样,问题本身出现“审批”两个字,也不能算来源证据已经可见。

多证据问题,召回率究竟在数什么?


前面的问题只需要一条规定:夜间打车是否需要审批。把这条规定标成一个证据单元,D 进入候选且关键句可见,才算这一项材料到位。

再把问题改成:“跨城夜间打车的审批和附件要求是什么?”答案同时依赖两条规定:D 中的主管审批,以及 F 中的“跨城夜间打车还需附行程说明”。这时分母是两个证据单元。

当 TopN=4 时,候选里只有 D,没有 F。若按文档命中来汇报,可能会说“报销制度已经召回”;若按问题实际需要的证据来算,只找回了两条中的一条。两种口径回答的不是同一个问题。

证据单元应该跟任务要求对应。同一条规定因重叠切块出现在两个片段里,只算一项证据;两个不同规定即使来自同一份文档,也不能因为文档 ID 相同就合并成一项。这样计算,才能知道最后答案缺的是哪条事实,而不是只知道某份文件来过。

候选覆盖还要与可见覆盖分开。D 已在 TopN 中,但审批句被截掉时,候选覆盖可以记为命中,实际可见证据仍是缺失。二者一起记录,才能区分“没有召回片段”和“召回了片段却没把关键内容交给模型”。

开发者拉开同一D文件的阅读窗口,保留关键句与原文位置,但没有模型评分

开发者拉开同一D文件的阅读窗口,保留关键句与原文位置,但没有模型评分

最终保留数量 TopK 也会形成新的上限。跨城问题需要 D 和 F 两条证据,而两条证据分别落在两个片段里;如果 TopK=1,即使它们都进入候选且完整可见,最后也只能保留其中一个。若一个片段本来就同时包含两条规定,结论又会不同,所以不能把“两条事实”机械理解成“必须保留两个片段”。

必要证据全部进入上下文,也仍不等于答案必然正确。生成模型还要理解条件、组合信息并形成回答。候选覆盖、输入可见、最终保留和回答正确,是四个相邻但不同的检查点。

TopN 扩大有什么代价,收益从哪儿看?


既然 D 在第 4 位、F 在第 6 位,直接把 TopN 调大似乎就能解决问题。但候选数量越大,Reranker 需要处理的问题与候选对也越多。一次请求有 N 条候选,就要形成 N 个成对输入;两个问题分别测试 N=3、4、6 时,对应 6、8、12 条输入。

在这份固定名单中,N 从 3 增加到 4,审批问题从 0/1 变成 1/1,跨城问题从 0/2 变成 1/2;N 增加到 5,只多出餐费片段 E,覆盖没有提升;增加到 6,F 才进入,跨城问题达到 2/2。

这个过程说明,调大 N 的收益不能只看数字变大,而要看新增候选补回了哪些必要证据。第 5 条候选只增加重排工作量,没有帮助这两道问题;第 6 条才补齐附件要求。

成对输入数量只是最容易核对的成本。真实部署还要看 token 长度分布、批大小、设备利用、排队时间和吞吐。十条很短的候选与十条接近长度上限的候选,开销不会相同。批处理可能提高整体吞吐,也可能为了凑批增加等待,不能把“支持 batch”直接翻译成单次请求更快。

选择 N 时,可以在验证集上扫描几个候选值,同时记录两类结果:必要证据覆盖增加了多少,以及实际计算、延迟和资源增加了多少。参数选定后,再用未参与调参的问题报告结果,避免在同一批题上反复调到好看。

如何沿 ID 找到证据消失的位置?


重排失败若只保存最终分数,后面很难判断该修哪一层。更实用的做法是给候选保留稳定 ID,把这些信息串起来:粗召回位置、文档来源、截断前原文、实际成对输入、重排分数、重排后名次和最终是否保留。

继续看 D。如果粗召回列表中没有 D,问题发生在入库、过滤或召回;列表里有 D,实际输入没有审批句,问题发生在切块、拼接模板或长度处理;D 的关键句完整可见,分数仍低,才进入模型适配和训练数据的讨论;D 已经排到前面,最终上下文却没有它,还要检查阈值、去重和上下文预算。

第一次缺失的位置
优先检查什么
粗召回前
入库、切块、元数据与过滤条件
TopN
之外
召回质量与候选数量
成对输入中
拼接模板、token 预算与截断策略
重排结果中
模型分数、输入顺序与 ID 对齐
最终上下文中
阈值、去重、TopK 与上下文预算

批量打分时还要核对分数与候选 ID 是否对齐。输入顺序变了,输出分数却按旧顺序贴回去,也会制造“模型排错”的假象。保存一串脱离身份的分数不够,输入 ID 序列和输出 ID 序列需要能互相对应。

开发者与同事分别核对候选入场和实际输入,之后才进入重排比较

开发者与同事分别核对候选入场和实际输入,之后才进入重排比较

这套定位方式的价值,在于每种现象都有对应修复层。它不会把所有失败都推给 Reranker,也不会因为召回到了某份文档,就提前宣布证据已经齐全。

面试里,把上限和验证讲完整


回答“RAG 重排漏证据怎么办”,可以这样组织:

我不会先换模型,而会先沿检索链路确认目标证据第一次在哪里消失。Reranker 只能对传入的 TopN 候选排序,所以先检查目标片段是否入库、是否通过过滤并进入候选。候选命中后,再核对真正送入模型的成对输入,确认关键句没有被切分或长度预算截掉。

对于需要多条事实的问题,我会按问题定义证据单元,分别记录候选覆盖、实际可见覆盖和最终 TopK 保留情况。调大 TopN 时,同时比较新增证据与成对输入、token 和延迟成本,而不是只看召回数字。

只有目标证据在固定候选中完整可见、候选 ID 与分数对应正确,却仍然排名靠后时,我才会在同一输入条件下比较 Reranker 模型。这样换模型是在解决排序能力,而不是替前面缺失的证据背锅。

前往微信阅读全文

内容来自公众号,可前往微信查看原文。

查看作者的更多文章 →订阅更新、RSS 与阅读指南 →