Recall Is Not Enough: A Reader-Context Diagnostic for Budget-Constrained Retrieval-Augmented Generation

Ananto Nayan Bala · arXiv 2607.00725 · 发表 2026-08-05
13 分钟阅读时长 4843字 4.70综合分 第 1 名08-07 Generative 日报
目录 · 8 节1它解决什么问题?2指标怎么定义3这个指标比召回率多告诉了我们什么4打包器怎么设计5结果6局限7一个 RAG 团队可以怎么用8结论与评价
相关 5新颖 4实用 5证据 5时效 5

这篇论文适合做检索增强生成(RAG)、需要在有限上下文里决定“放哪些检索结果进去”的工程师读。它的核心思想一句话:大家习惯用召回率(recall@k)评估检索,但模型读的是经过裁剪、拼接后的那段上下文;预算一紧,两者就会脱节,真正该看的是“标准答案有没有出现在模型读到的上下文里”,作者把这个指标叫 answer-in-context。在 HotpotQA 上,即使 5 篇检索结果已经包含全部标准文档,仍有 27% 的题在裁剪时把答案丢掉了,这些题的精确匹配率只有 0.11,答案保住的题是 0.50。作者据此做了一个按这个目标优化的上下文打包器,它稳定胜过常见的“按相关度截断”和 LLMLingua-2 压缩,但和一个手调的启发式规则相比,14 组对比里有 12 组打平。

它解决什么问题?

RAG 的流程是:检索器先找回一批文档,打包器(packer)再从中挑一部分、在 token 预算内拼成上下文,最后交给阅读模型(reader)生成答案。召回率是在第一步之后算的,只看标准文档有没有被检索回来;可模型读到的是第二步的结果。

当检索回来的相关内容比预算能装下的多,打包器就得取舍,召回率和模型实际看到的内容就分开了。多跳问题尤其明显,因为答案需要把几篇文档的信息串起来。举一个示意例子:问题是“电影 X 的导演出生在哪个国家?”。检索回来的 5 篇里,第 1、2 篇都在讲电影 X,第 3 篇讲导演的生平,写着“出生于法国巴黎”。召回率是满分。但如果预算只够放两段,按相关度排序的打包器会留下第 1、2 篇这对重复的内容,把真正含答案的第 3 篇挤掉,模型就答不出来了。

论文用三个多跳问答数据集(HotpotQA、MuSiQue、2WikiMultiHopQA)和两个单跳数据集来研究这个问题。实验设置非常紧:主预算只有 160 个 token,阅读模型主要是 Qwen2.5-3B,两张 T4 显卡就能跑。

指标怎么定义

作者在“打包后、真正交给模型的上下文”上算三个量,和召回率的区别是它们都在裁剪之后算:

指标怎么算示意例子里的值
answer-in-context标准答案(归一化后)是否作为连续片段出现在上下文里,是就记 1第 3 篇被挤掉,记 0
标准文档覆盖率有多少比例的标准文档至少贡献了一段内容进上下文两篇标准文档只进了一篇,记 0.5
标准 token 密度上下文里来自标准文档的 token 占多少取决于两段的长度

为什么不直接看召回率?因为对抽取式回答来说,答案不在上下文里,模型基本不可能答对;answer-in-context 是答对的必要条件,召回率不是。

对于没有原文片段可对的长篇自由回答,作者还做了一个分级版本:在上下文里取一个宽度为答案长度两倍的窗口,看窗口内能覆盖多少比例的答案 token,取最大值。答案完整出现在上下文里时,窗口能盖住全部答案 token,分数是 1,和二值版本一样;答案只部分出现时,二值版本记 0,分级版本给出覆盖比例,所以对长答案仍有区分度。

这个指标比召回率多告诉了我们什么

在 HotpotQA 上,把所有“打包策略×问题”的组合放在一起算相关性,answer-in-context 和 F1 的相关系数是 0.50,召回率只有 0.31,标准文档覆盖率 0.33。答案在上下文里时平均 F1 是 0.596,不在时只有 0.123。

在 HotpotQA 中检索已经把全部标准文档找回来的题目里,打包时保住答案和丢掉答案的两组对比。保住答案的一组 F1 是 0.61、精确匹配率是 0.50;丢掉答案的一组只有 0.20 和 0.11。中间的注释说明这类“检索满分”的题目中有 27% 在打包时丢了答案。
在 HotpotQA 中检索已经把全部标准文档找回来的题目里,打包时保住答案和丢掉答案的两组对比。保住答案的一组 F1 是 0.61、精确匹配率是 0.50;丢掉答案的一组只有 0.20 和 0.11。中间的注释说明这类“检索满分”的题目中有 27% 在打包时丢了答案。

有人会质疑:这个指标会不会只是召回率换了个说法,或者几乎等于“答对了”?作者做了两层检验。

第一层是增量解释力。只用召回率去拟合 F1,能解释 8.5% 的方差;加上 answer-in-context 后升到 25.7%,多解释了 17 个百分点,说明它带来了召回率没有的信息。另两个多跳数据集上,这个增量更大,分别是 23 和 27 个百分点。answer-in-context 和召回率本身的相关系数只有 0.24 到 0.41,所以它远没到“就是召回率换个说法”的程度。

第二层是两次干预实验。在 2WikiMultiHopQA 上,作者的打包器比启发式规则多放进了标准文档(覆盖率高 0.054),但 answer-in-context 没变(-0.007),F1 也没变(-0.008,不显著)。原因是这类题的答案通常就在启发式已经排第一的那篇里,多放进来的是推理用的桥接文档。反过来,用 LLMLingua-2 按 token 粒度压缩上下文,会把答案片段切碎,answer-in-context 下降 0.243,准确率跟着下降。覆盖率变了而答案在不在没变,质量不动;答案在不在变了,质量跟着变。这说明真正起作用的是答案有没有进上下文。

打包器怎么设计

既然目标是让答案进上下文,作者把“在预算内选哪些片段”写成一个带预算约束的子模最大化问题(子模函数的特点是边际收益递减:已经选得越多,再加一段带来的增量越小)。目标函数是四项加权和:

项作用权重
相关度每段各自的相关度分数之和;单段分数由候选生成阶段给出,打包器直接当输入用1.0
问题词覆盖问题里的不同实词被覆盖了多少,已覆盖的词再出现不加分0.5
代表性选中的片段能“代表”多少候选内容,设了上限,防止近似重复刷分0.4
来源多样性每篇文档的相关度总量开平方再求和,鼓励分散到不同文档0.3

其中代表性这一项稍复杂:对每个候选片段,算它和已选片段的相似度之和,但封顶在它和全部候选的相似度总和的 0.3 倍,然后对所有候选求和。封顶意味着一个候选被“代表”到一定程度就不再加分,所以反复塞进几段近似重复的片段,不能无限刷高这一项。

求解用标准的按 token 计价的贪心:每一步在不超预算的片段里,挑“边际收益除以 token 数”最大的那段加进来。示意:片段 A 有 40 个 token、能让目标增加 0.4,每 token 0.01;片段 B 有 20 个 token、能增加 0.3,每 token 0.015,所以先选 B。最后再检查一次,如果单独一段最好的片段比整个贪心结果还好,就只返回它。

对照组有四个。朴素打包是按相关度依次拼接直到装满,这是大多数 RAG 流水线的默认做法。MMR(最大边际相关)是经典的去冗余排序。LLMLingua-2 是把同一批候选压缩到同样预算。最强的对照是作者项目里此前效果最好的“聚焦启发式”打包规则。按作者的描述,它逐段贪心地挑片段,首要标准是这一段能补上多少还没覆盖到的问题词,补得一样多时,再优先选来自还没用过的文档的那段;每加入一段后才检查预算,超出就停止并截断末尾。作者对它的定位是:它关心的两件事大致对应目标函数里“问题词覆盖”和“来源多样性”两项,但缺少代表性项、不按长度折算收益、也不在挑选时考虑预算,因此可以看作同一个目标的粗糙手工近似。为了让比较公平,打包器和启发式共用同一批候选片段和同一份单段相关度分数,比较时唯一的变量就是挑选规则。

结果

HotpotQA、预算 160、3B 阅读模型、三个随机种子的平均(论文表 3):

打包策略F1精确匹配率实际用的 token
LLMLingua-2 压缩0.3260.233129.6
朴素打包0.4000.306151.1
MMR0.4100.313151.7
聚焦启发式0.4290.331152.1
子模打包器0.4510.359145.5
每题挑最好的策略(上限参考)0.6010.487141.5

子模打包器在每个种子上都是最好的固定策略,而且用的 token 更少。它比朴素打包高 0.051 F1,比 LLMLingua-2 高 0.125 F1。压缩输得这么多,是因为逐 token 删减会切碎答案片段,即使把朴素打包的预算降到和压缩差不多的 128 个 token,F1 仍有 0.368,高于压缩的 0.326。作者逐题拆解发现,子模打包器相对启发式的收益里,81% 来自 37 道“新把答案放进上下文”的题,原因是它让全部标准文档都进上下文的题从 256 道增加到 289 道。

换成另外两个 3B 模型(Falcon3-3B 和 Phi-3.5-mini),相对朴素打包的优势仍然显著(+0.029 和 +0.048),但相对启发式的优势消失了(-0.004 和 +0.002)。

阅读模型尺寸从 3B 到 32B 时,子模打包器相对两种对照的 F1 差值。红线是相对朴素打包,每个尺寸都在 0.04 以上;蓝线是相对聚焦启发式,3B 时为正,7B 时打平,14B 时显著为负,32B 时回到持平。空心菱形是 7B 的 4 比特量化对照,和全精度结果重合,说明趋势来自模型尺寸而不是量化。
阅读模型尺寸从 3B 到 32B 时,子模打包器相对两种对照的 F1 差值。红线是相对朴素打包,每个尺寸都在 0.04 以上;蓝线是相对聚焦启发式,3B 时为正,7B 时打平,14B 时显著为负,32B 时回到持平。空心菱形是 7B 的 4 比特量化对照,和全精度结果重合,说明趋势来自模型尺寸而不是量化。

模型变大后,相对启发式的优势被吸收:大模型能从启发式打包的上下文里自己找出答案,更密的标准内容不再带来准确率。预算也有类似规律,在 96、128、160、224 四个预算里,只有 160 时相对启发式的优势显著;而相对朴素打包,每个预算都显著领先。

局限

第一,相对手调启发式的优势基本站不住。作者自己统计了 14 组对比,只有 1 组显著为正、1 组显著为负,其余 12 组打平。在没有真实效果的情况下,做 14 次检验本来就会有一两次偶然显著,作者也承认这个唯一的正面结果只能算假设,而且这些“打包器在什么条件下更好”的结论是事后从同一批实验里归纳的。

第二,设置和真实部署差距很大。160 个 token 的预算只够放两三段文字,现实中的 RAG 预算通常是几千 token;相关度是词面打分,embedding 模型只用了 bge-small;跨模型家族的检验只在 3B 上做,32B 只跑了一个种子。预算放宽到 224 时,相对启发式的优势已经不显著。

第三,answer-in-context 本身是词面匹配。答案被改写成同义表达时会被判为“不在上下文”,作者也提到 27% 的丢答案题里有一小部分属于这种情况。分级版本缓解了长答案的问题,但仍是词面重叠,不衡量答案是否忠实于来源。

第四,这是单作者工作,所有结论都来自同一条实验流水线,复现时要重建它的候选片段切分和聚焦启发式基线。另外,“每题挑最好的策略”能到 0.60 F1,而最好的固定策略只有 0.45,说明不同题目适合的打包方式差别很大;但子模打包器(表里的 submod)已经在 79% 的题目上是最好或并列最好的策略;剩下那些题目上哪种方式更好,要等看到阅读模型的答题结果才知道,推理时拿不到这个信息,所以作者只把 0.60 当作提升空间的参考,而不是一个能部署的方法。

一个 RAG 团队可以怎么用

  1. 先加一个诊断:在评测里除了召回率,再记录 answer-in-context,也就是标准答案是否出现在最终交给模型的上下文里。重点看“召回满分但答案被丢”的比例,论文的 HotpotQA 设置下是 27%。
  2. 如果现在用的是按相关度截断,或者用 LLMLingua 这类压缩来塞预算,换成按片段选择的打包器很可能有稳定收益;论文里这一点在所有阅读模型和预算下都成立。
  3. 如果已经有一个手调好的“覆盖问题词、分散来源”的启发式,就不必期待子模打包器再带来明显提升。
  4. 多跳任务里先看检索:MuSiQue 上只有 18% 的题全部标准文档都被检索到,这时任何打包方式都无济于事,应该先上迭代式的多跳检索。

结论与评价

这篇论文最有价值的部分是诊断而不是方法:在预算受限的 RAG 里,召回率不等于模型看到了答案,answer-in-context 能更好地解释最终质量,而且两次干预实验支持它是中间的关键变量。

维度评价
问题重要性中高。上下文预算和检索结果之间的取舍是 RAG 工程里常被忽视的一环
方法创新性中低。子模贪心是教科书方法,新意在把目标和诊断指标挂钩
实验证据指标的有效性证据扎实;打包器相对强启发式的优势基本是打平,作者自己也如实报告
工程成本低。诊断只需字符串匹配,打包器是简单贪心
是否值得尝试诊断值得马上加;打包器在替换朴素截断或压缩时值得试
适用场景上下文预算紧、多跳问答、阅读模型较小的 RAG 系统

读完这篇,你觉得

点一下即可,无需登录;再点一次撤回。只统计匿名次数,不记录你是谁。

讨论

欢迎补充实验细节、复现经验或不同看法。需 GitHub 登录。

正在加载讨论…