跳到主内容
精选88Avi Chawla技巧与观点

Agent上下文压缩为何可能增加Token成本及优化策略

Compacting your agent's context can cut its tokens and still raise costs.

原文
推荐理由

深入解析了Agent开发中容易被忽视的成本陷阱,提供了从原理到具体工具(如LMCache)的完整工程实践指南,值得所有构建长上下文Agent的团队参考。

Compacting your agent's context can cut its tokens and still raise costs.

压缩智能体的上下文可能会减少其 token 数量,但反而会增加成本。

This sounds counterintuitive, but token count and billed amount are two different quantities in how prefix caching works.

这听起来违反直觉,但在前缀缓存的工作原理中,token 数量和计费金额是两个不同的量。

A long agent session resends its entire history on every call, appending the model's reply and the tool output to the transcript each turn.

在长会话中,每次调用都会重新发送整个历史记录,并在每一轮将模型的回复和工具输出追加到对话记录中。

This stays affordable because the leading span of each request is byte-identical to the previous one.

这之所以成本可控,是因为每个请求的前导部分与上一次请求完全相同(字节级一致)。

Providers bill that span as a cache read, which on Anthropic is 10% of base input, so a context that grows only at the tail stays cheap no matter how large it gets.

提供商将该前导部分作为缓存读取进行计费,在 Anthropic 上这仅为基础输入费用的 10%,因此无论上下文变得多大,只要仅在尾部增长,成本就保持低廉。

Compaction edits the front of the transcript rather than the tail. The harness replaces the original turns with a summary, so everything from the edit point onward stops matching what was cached.

压缩操作修改的是对话记录的头部而非尾部。编排器用摘要替换原始轮次,导致从编辑点开始的所有内容都不再匹配已缓存的内容。

Consider a session having 100K tokens of history.

假设一个会话拥有 10 万 token 的历史记录。

  • Normally, the next call reads that history from cache at a tenth of base rate, which works out to 10K tokens at full price.
  • But compact it down to a 10K summary, and there is nothing left to match, so those 10K bill as a cache write at 1.25x base input, which comes to 12.5K. The context is ten times smaller, and the call costs more.
  • 通常情况下,下一次调用会以基础费率十分之一的价格从缓存中读取该历史记录,相当于以全价计算 1 万 token。
  • 但如果将其压缩为 1 万 token 的摘要,就没有剩余内容可以匹配了,因此这 1 万 token 会按基础输入 1.25 倍的缓存写入费用计费,即 1.25 万。上下文变小了十倍,但调用成本却更高了。

To be fair, that cost is recovered over the turns that follow. But harnesses trigger compaction on a token threshold, so a long session compacts repeatedly and each event resets it.

公平地说,这笔成本会在随后的轮次中收回。但由于编排器基于 token 阈值触发压缩,长会话会反复压缩,且每次事件都会重置状态。

None of this makes compaction wrong. Context windows are finite, and there are five strategies used in practice.

这并不意味着压缩是错误的。上下文窗口是有限的,实践中有五种策略。

> Truncation drops the oldest tokens once the limit is close. It is the cheapest to implement and the only one that permanently loses early decisions.

> 截断:一旦接近限制,就丢弃最旧的 token。它实现成本最低,也是唯一会永久丢失早期决策的策略。

> Rolling summarization merges each new summary into a persistent state instead of regenerating from scratch, and still moves the cache boundary every time.

> 滚动摘要:将每个新摘要合并到持久化状态中,而不是从头重新生成,并且每次都会移动缓存边界。

> Prompt compression scores each token with a small model and drops the low-relevance ones. LLMLingua reports up to 20x compression at small accuracy loss, and LLMLingua-2 does the same scoring with a BERT-sized encoder.

> 提示压缩:使用小型模型对每个 token 进行评分并丢弃低相关性的 token。LLMLingua 报告称在精度损失很小的情况下可实现高达 20 倍的压缩率,而 LLMLingua-2 则使用 BERT 大小的编码器进行相同的评分。

> RAG-based retrieval moves the history into a vector DB and injects back only what matches the current query, so retrieval precision becomes the failure mode instead.

> 基于 RAG 的检索:将历史记录移入向量数据库,并仅注入与当前查询匹配的部分,因此检索精度成为主要的失败模式。

The first three delete text outright, and RAG moves it into a store the agent only sees again if retrieval fetches it.

前三者直接删除文本,而 RAG 将其移至存储中,除非检索获取,否则智能体再也看不到它。

> KV cache eviction runs at the serving layer and drops the entries least likely to be needed, either by attention score, as in H2O and SnapKV, or by position, as in StreamingLLM.

> KV 缓存驱逐:在服务层运行,丢弃最不可能需要的条目,要么基于注意力分数(如 H2O 和 SnapKV),要么基于位置(如 StreamingLLM)。

The full history still goes to the model, and what gets dropped is the KV tensors the GPU computed for those tokens. Since those tensors are derived from the tokens, eviction costs prefill work rather than information.

完整的上下文历史仍然会发送给模型,而被丢弃的是 GPU 为这些 token 计算出的 KV 张量。由于这些张量是从 token 派生而来的,驱逐操作消耗的是预填充(prefill)的工作量,而非信息本身。

They can always be recomputed. KV blocks that no longer fit in GPU memory can move to CPU DRAM, local NVMe, or a remote store, then load back on the next request instead of being recomputed during prefill.

它们始终可以被重新计算。不再适合放入 GPU 显存的 KV 块可以移动到 CPU DRAM、本地 NVMe 或远程存储中,然后在下一个请求时加载回来,而不是在预填充阶段重新计算。

LMCache implements this as an open-source layer for vLLM, SGLang, and Dynamo. Through CacheBlend, it reuses cached blocks at any position in the prompt rather than only the leading span.

LMCache 将其作为 vLLM、SGLang 和 Dynamo 的开源层来实现。通过 CacheBlend,它可以在提示词(prompt)的任何位置复用缓存的块,而不仅仅局限于前导部分。

Repo: https://github.com/LMCache/LMCache

仓库地址:https://github.com/LMCache/LMCache

(don't forget to star it ⭐)

(别忘了给它点个星 ⭐)

That said, everything we discussed above depends on how the prefix cache behaves across turns. I covered prompt caching from first principles in an article recently.

话虽如此,上述所有内容都取决于前缀缓存在多轮对话中的行为表现。我最近在一篇文章中从第一性原理的角度探讨了提示词缓存机制。

Read it below.

点击下方阅读。

更进一步:量化金融体系

看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力

进入量化体系 →

相似阅读

另一事件,读法相近