将 RAG 上下文精简为回答所需的必要内容
Pruning RAG context down to what the answer actually needs

原始链接: https://www.kapa.ai/blog/how-we-prune-rag-context

Kapa 通过在检索与生成阶段之间引入基于大语言模型(LLM)的“剪枝器”(pruner),优化了其 RAG(检索增强生成)工作流。 传统的 RAG 依赖检索器向大模型提供大量文档片段,并假设生成器会自动过滤噪声。然而,由于生成器的 Token 成本高昂,忽视这些噪声会导致极高的费用。Kapa 的解决方案是使用一个小型、低成本的大模型,在检索到的片段进入昂贵的生成器之前,先评估它们与用户问题的相关性。 通过采用五级相关性评分机制,剪枝器能够有效地识别并剔除无关信息,在保持 96% 召回率的同时减少了约 68% 的上下文内容。在扣除剪枝器本身的运行成本后,这一过程使总查询成本降低了约 34%。尽管此方法增加了不到一秒的延迟,但显著提升了效率,对于上下文管理至关重要的复杂智能体而言尤为有效。目前,该剪枝器已成为 Kapa 产品智能体 SDK(Product Agent SDK)的默认配置,为拥有庞大知识库的 AI 助手提供了一种更精简、更具成本效益的实现方式。

这次 Hacker News 的讨论围绕 kapa.ai 最近关于 RAG(检索增强生成)语境“修剪”的文章展开。 讨论涵盖了几个核心主题: * **术语之争:** 用户们就“RAG”这一术语的准确性进行了辩论。一些人认为这对于语义搜索、编排和智能体工具使用等复杂过程来说是一个过于简单的标签;另一些人则将其视为用检索到的信息来增强大模型输出的统称。 * **RAG 的现实情况:** 经验丰富的从业者指出,“RAG”常被用作基础文档检索系统的营销术语。他们认为,现实世界的成功更多地依赖于严谨的数据工程、索引和质量测试,而非“神奇”的搜索算法。 * **修剪问题:** 讨论强调了基于相关性进行修剪(剔除相似度评分较低的数据块)的风险。批评者警告称,这可能会删除获得完整答案所必需的关键性、细微或“稀有”信息。支持者则认为,先进的多步骤相关性模型可以降低这种风险。 * **不断演变的语境:** 许多人指出,尽管更大的上下文窗口允许输入更多数据,但“塞入式上下文”(context stuffing)会导致模型难以处理噪声,因此为了兼顾成本和准确性,高效的检索和修剪依然非常必要。
相关文章

原文

Kapa builds AI assistants that answer complex questions over large product knowledge bases. Think technical documentation, API references, PDFs, forums, support threads. Developers use our retrieval API to give their agents context about their product, and the same retrieval layer powers our end-to-end assistants.

For all the debate in 2026 about whether agents still need RAG, in our domain nothing comes close when knowledge bases get large and complex. Our retrieval comes in several forms, some agentic, some single-pass, but they all share the same shape: a retriever, which finds the chunks of documentation relevant to a question, and a generator, the LLM that writes the answer from them.

The short version of this post: we added a third step between the two. A small, cheap LLM reads the question and all the retrieved chunks together, and throws out the chunks the answer will not need before the expensive model ever sees them. It drops about 68% of the context, keeps about 96% of recall, and cuts the cost of a query by a third, net of its own cost. This post explains how we got there.

Ignored chunks still cost money

A retriever is a funnel. Embedding and keyword search cut a knowledge base of hundreds of thousands of chunks down to a few hundred candidates, a reranker orders them, and the top 15 or so reach the generator, the largest and most expensive model in the chain. Even then, most of what the generator reads is not needed for the question. That is deliberate: retrievers aim for maximum recall and trust the generator to ignore the noise.

But the generator is billed for every chunk it ignores. In our assistants, retrieved chunks are about two-thirds of the cost of a query, more than the answer, the conversation history, and the system prompt combined. Every chunk fewer cuts the query cost by about 4%. And in an agent, every tool call pours its output into the same context, so the context grows quickly; a tighter retrieval result buys room for everything else the agent has to hold and leaves less context to rot.

The catch is recall. Drop a chunk the answer needed and you traded a few cents for a wrong answer. A pruner is exactly as good as that tradeoff: compression gained per point of recall lost.

The obvious fix does not work

We already rerank before returning the top K, so we are sometimes asked to just expose the rerank scores and let callers cut on them: keep everything above 0.7, drop the rest. It fails for two reasons, and the second shaped everything we built.

First, a rerank score is an ordering, not a measurement. It says chunk A beats chunk B on this query, nothing more. The scores are not calibrated across queries, Cohere too says as much, so no fixed cutoff works. The only cutoff a ranking supports is positional, top-N, and that drops the last chunk whether it is noise or the answer.

Second, and this survives even perfect calibration: relevance is not a property of a single chunk. The rerankers in most pipelines are pointwise cross-encoders. They score each query-chunk pair alone, never alongside the other chunks it was retrieved with. Here is an anonymized production example:

The second chunk never mentions audit logs, so it scores as noise, yet it is half the answer, and no pointwise score can see that, because the chunk is only relevant next to the first one. Chunks also split multi-part questions between them, each useless alone. The real question is never whether a chunk is relevant by itself, but whether it belongs to a set that together answers the question. 

A clever fix that fails the same way

Before giving up on the reranker we tried anchor documents (Sinhababu et al.): make the reranker's scale absolute by planting synthetic chunks of known relevance into the ranking, one written per level from Essential to Unrelated, then drop every real chunk that ranks below the anchor of the lowest level you want to keep. One extra LLM call on top of a rerank you already run, and genuinely elegant.

It did not work, for the same underlying reason. Anchors fix calibration, but they cannot fix the scores, and the reranker kept placing partially and indirectly relevant chunks below plainly irrelevant ones. To keep them, the anchor has to sit so low that hardly anything gets pruned.

That failure was the useful result: whatever prunes has to see the question and all the chunks at once, because the thing being judged is the set.

So we let an LLM grade the chunks

What we shipped is one listwise LLM call between the reranker and the generator. It gets the question and all the chunks, and grades every chunk against a five-level scale written into its prompt:

LLM Score

Level

Meaning

5

ESSENTIAL

The answer cannot be produced without this chunk, whether it answers directly or is a definition or prerequisite another chunk depends on.

4

CONTRIBUTING

Does not answer on its own, but supplies something a complete answer needs in combination with other chunks.

3

SUPPORTING

On topic and plausibly useful, but the answer is likely complete without it.

2

TANGENTIAL

Same domain or shared terminology, no concrete contribution.

1

UNRELATED

No meaningful connection.

Chunks at or above a threshold survive. The design answers both failures from earlier. Because each level is defined in words, a 4 means the same thing on every query, so a fixed cutoff finally works. And because the model sees the question and all the chunks together, it can judge the set, so partial and indirect relevance finally have somewhere to land.

Three knobs matter:

  • The model: the pruner is paid for out of what it saves, so flagship models are ruled out by construction; the small fast tiers all judged similarly, so we picked the fastest and cheapest at low reasoning effort. 

  • The threshold: the main dial between compression and recall. 

  • keep-top-k: the top few reranked chunks pass regardless of grade, protecting the strongest chunks from a grading mistake.

We also ran two simpler designs to keep ourselves honest. Budget-select: keep the top few, let the LLM add at most N more; predictable size, but once the budget is spent every further chunk is dropped no matter how relevant. And the simplest possible pruner: just ask the LLM which chunks to keep, no scale. If a scheme cannot beat asking directly, it is not worth building.

The results

We measured recall on a labeled set of real questions where we know exactly which chunks the answer needs, then verified compression, cost, and latency by replaying every configuration over a random month of production conversations, on the exact chunks each query actually sent to the generator.

Every point is one configuration, plotted by the two things that matter. Compression, on the x-axis, is the share of retrieved chunks the pruner throws away. Recall preserved, on the y-axis, is the share of questions that still have every chunk their answer needs after pruning: at 100% no question lost a chunk it needed, at 90% one in ten did. Up and to the right is better. The lines connect each strategy's best configurations, and the dashed grey line is the baseline any pruner has to beat: naive top-N truncation, just returning fewer chunks from the reranker.

Everything beats it, by a lot. Hold recall at 98%: truncation can drop one chunk, about 7% compression. Every LLM strategy reaches 30% or more, and relevance scoring drops close to half the chunks. The scoring line also dominates the other two at every compression level, so the only decision left was where on it to sit.

We picked a point near the aggressive end: about 96% recall preserved, about 68% of chunks dropped. One question in twenty-five loses a chunk it needed; in exchange, two-thirds of the context is gone, and the per-query bill falls by about 34%, net of the pruner's own cost.

What it costs in latency

The pruner runs between retrieval and generation, in the critical path, so its model call is added to every query, and its speed decides what that costs. Across the production set, the configuration we picked ran in about 0.7 seconds per query. Heavier settings climb fast, so a small model at low reasoning effort is what keeps the addition under a second.

The generation barely speeds up in return: fewer chunks mean fewer input tokens for the generator, so it starts responding a little sooner, but only a fraction of a second, nowhere near enough to cancel out the pruner's own call.

So pruning buys its compression at the cost of a small, fixed amount of latency, well under a second on the configuration we ship. On a latency-sensitive single-shot path that is a real cost to weigh. Inside an agent, which already makes several model calls per turn, one more lean call is marginal.

Where we turned it on

We rolled it out first where retrieval is one tool among many: customers building agents on top of our retrieval. An agent carries dozens of tools, every call pours output into the same context, and a documentation search that returns two-thirds less buys room for everything else. The lost recall is also less dangerous there: an agent that notices something missing can search again.

Pruning is on by default in our Product Agent SDK's knowledge base search, and optional in the retrieval API and MCP servers.

联系我们 contact @ memedata.com