kapa.ai最近公开了一组具体数字:他们在RAG流水线里塞进一个专门负责"扔东西"的小模型,一次查询平均丢弃68%的检索内容,召回率只掉4个百分点,单次查询成本净省约三分之一。这不是把生成模型换便宜,也不是少检索几条,而是在检索器和生成器之间,新插了一道"读了但未必要用"的过滤层。

多数人对RAG的直觉是context越多越安全,省钱的功夫习惯花在换模型或砍检索数量上。kapa这次算的账不一样——真正被浪费的,是那些被认真检索回来、却从没被生成模型真正用上的内容。

检索到的,不等于被用到的

标准流程是:embedding加关键词检索从几十万chunk里筛出几百个候选,reranker排序,取Top15左右交给最贵的生成模型。默认逻辑是让检索器追求高召回,把过滤噪声的责任丢给生成器兜底。

问题是生成器按token计费。kapa给出的数字很直白:检索回来的chunk本身,占一次查询成本的三分之二——比答案、对话历史、系统提示词加起来还多。每少一个chunk,查询成本降4%左右。agent场景里问题更重,每次工具调用的输出都塞进同一个上下文窗口,context会越滚越大,留给别的东西的空间越来越少。

kapa.ai 剪枝前后的账单变化 68% 检索chunk被丢弃 96% 召回率保留 1/3 单次查询成本净降

代价也很直接:剪掉一个答案真正需要的chunk,省下的几分钱换来的是一个错误答案。任何剪枝方案的好坏,就看一件事——每压缩一分,召回掉多少。

直接卡阈值,行不通

最直觉的做法是复用已经在跑的reranker:分数超过某个阈值就留,低于就扔。kapa试过,失败在两点上。

第一,rerank分数是排序信号,不是绝对测量。它只能说"这条比那条更相关",不能跨query比较——Cohere自己的文档也这么写。固定阈值唯一能立住脚的规则是"取前N个",可前N个照样会把答案需要的最后一个chunk一起扔掉。

第二点更致命,校准分数也救不了。多数reranker是pointwise cross-encoder,给每条chunk单独打分,不参照它旁边的其他chunk。kapa举了一个真实例子:两条chunk里,第二条只字未提"审计日志",单独看像噪声,可它和第一条拼在一起才是完整答案的另一半。relevance从来不是单个chunk的属性,它是有没有属于"能凑齐答案的那个组合"。

更聪明的办法,依然没赢

kapa后来试了一个更巧妙的方案:往候选集里塞几条"锚点"chunk,每条对应一个已知的相关度等级,靠锚点把reranker的打分刻度校准成绝对值,再按最低要保留的等级去截断——思路来自一篇公开论文(arXiv 2604.09492)。

方案没能解决问题。锚点能修刻度,修不了打分逻辑本身:reranker依然会把那些部分相关、间接相关的chunk排在明显不相关的chunk下面。想留住它们,锚点只能设得极低,结果几乎什么都剪不掉。

这次失败反而给出一个有用的结论——凡是要做判断的东西,必须同时看到问题和全部候选chunk,因为要判断的对象从来不是单条chunk,是整个候选集合。

让另一个LLM来判"集合关系"

kapa最后上线的方案,是在reranker和生成器之间插一次listwise打分:一个小模型同时读问题和全部候选chunk,按五级量表(从"缺了就答不出"到"毫无关联")给每条chunk评分,固定阈值以上的留下。

新插入的第三步:LLM打分 检索器 数十万chunk 筛出候选 Reranker 排序取 Top 15 LLM打分 五级量表 判去留 (新增) 生成器 只读 幸存chunk

这个设计同时解决了前面两次失败的根子。等级用文字定义,同一个分数在不同query里含义一致,固定阈值才终于站得住;模型同时看到问题和全部chunk,判断的是"这条属不属于能凑齐答案的组合",部分相关、间接相关的chunk才有地方落。

模型选型也很务实——打分模型的花销必须从省下的钱里出,旗舰模型直接出局,kapa选的是小尺寸、低推理强度的快模型。剩下两个可调旋钮:阈值是压缩和召回之间的主拨盘,keep-top-k让排名最靠前的几条chunk无论打分如何都强制保留,防止判断失误。

kapa还测了两个更简单的对照方案。一个是留几条固定的,再让LLM最多加N条,预算可控但用完就只能硬扔;另一个不设量表、直接问LLM留哪些。这两个都没打赢listwise打分——如果一个方案连"直接问LLM"都赢不了,就不值得单独做。

判断一个chunk该不该留,本质是判断它属不属于那个能凑齐答案的集合。
同等召回(98%)下的压缩率对比 固定阈值截断 ~7% 简单LLM策略 ≥30% listwise打分 接近50% kapa实际上线配置压缩68%,召回96%(非同一基准点)

在同样保住98%召回的前提下,固定阈值截断只能压掉一成不到,几种简单LLM策略能到三成以上,而listwise打分能逼近一半。kapa自己上线的配置更激进,压缩到68%,召回率还留在96%左右,代价是延迟多了不到一秒——单轮场景这个延迟要认真权衡,但在本来就要跑好几次模型调用的agent场景里,这一次调用只是边际增量。

这事的分寸在哪

这套方法论最值得记住的地方,不是又省了一笔钱,是它把reranker的局限钉死了:pointwise打分不是校准不好,是评分单元本身选错了。这对所有拿cross-encoder做重排的团队都是一个具体提醒——想再往下剪,靠调阈值调不动,得换个能看到集合关系的判断者。

  • 风险.kapa公开的68%/96%/降三分之一这组数字,评测集规模、基线设定、是否覆盖多轮agent场景都没有完整披露,目前也没有第三方复现或交叉验证,能不能迁移到别的知识库、别的领域(比如法律、医疗文档需要重写五级量表的定义),还看不清。

这套架构本身不难复制:检索器和生成器之间插一层listwise打分,谁都能试。真正的门槛在于把"多留一分召回"和"多省一分钱"这条曲线画准——这是每个团队自己知识库的脾气,借不来。