RAG上下文裁剪实战:68%的检索结果可以扔掉
原文:How we taught a small LLM to throw away 68% of our RAG context | Kapa.ai | 2026.07.02
RAG系统有个"公开的秘密":检索出来的大部分内容,生成模型根本用不上。
但你还是得为每个token付费。
Kapa.ai团队找到了一个简单有效的方法:在检索和生成之间加一步裁剪,用一个小LLM判断哪些片段是"噪音",直接扔掉。
问题:检索器追求召回率,成本你来扛
一个典型的RAG管线:
用户问题 → 嵌入检索(几千候选) → 重排序(几百) → Top-15送入LLM → 生成答案
检索器的目标是不漏掉任何相关内容,所以宁可多捞一些噪音。反正LLM能自己分辨。
问题是:LLM读的每一个chunk都要花钱。
在Kapa的生产环境中,检索片段占一次查询成本的2/3——比答案、对话历史、system prompt加起来还多。每少一个chunk,查询成本降低约4%。
为什么直接用reranker分数做裁剪不行
最直觉的方案:让调用方根据reranker分数自己设阈值,低于0.7的扔掉。
失败了,两个原因:
-
reranker分数是排序,不是度量。 分数只说明"A比B相关",不跨查询校准。没有一个固定的阈值能通用。
-
相关性不是单个chunk的属性。 这是更根本的问题。一个chunk可能单独看是噪音,但和另一个chunk组合起来就是完整答案。
Kapa给了一个真实的生产案例:
第二个chunk单独看完全不相关(reranker分数很低),但它其实是答案的一半——因为它和第一个chunk组合才能回答问题。逐点评分永远看不到这种关系。
他们的方案:listwise LLM裁剪
在reranker和generator之间加一个小LLM调用。
输入:用户问题 + 所有检索到的chunk(通常15个左右) 输出:每个chunk的分数(1-5级)
| 分数 | 级别 | 含义 |
|---|---|---|
| 5 | ESSENTIAL | 没有这个chunk就无法回答 |
| 4 | IMPORTANT | 不是核心,但对回答质量有帮助 |
| 3 | RELATED | 提供了有用的背景信息 |
| 2 | TANGENTIAL | 勉强相关,不推荐使用 |
| 1 | UNRELATED | 完全无关 |
只保留分数≥3的chunk送入昂贵的生成模型。
结果
| 指标 | 数值 |
|---|---|
| 上下文减少 | 68% |
| 召回率保持 | 96% |
| 单次查询成本降低 | ~33%(扣除裁剪LLM自身的成本) |
裁剪用的是一个小模型(成本远低于生成模型),所以净效果是省钱。
关键洞察
"一个chunk是否相关"不是它自身的属性,而是它和周围chunk的关系属性。
这就是为什么逐点reranker做不了裁剪——它只看"问题-chunk"这对,看不到chunk之间的关系。而listwise LLM能看到全部chunk,能判断"这两个chunk组合起来才构成完整答案"。
实践建议
- 裁剪步骤放在reranker之后,而不是替代reranker。两者解决不同问题。
- 用小模型做裁剪,不需要大模型。判断"有没有用"比"怎么回答"简单得多。
- listwise比pointwise好——能看到chunk之间的关系,这是核心优势。
- 在Agent场景下价值更大——每次工具调用都会往context里塞内容,裁剪能为其他内容腾出空间。
本文来源:Kapa.ai Engineering Blog,2026年7月2日