从零开始的 Agent 开发:上下文,压缩和预算

0x00 前言

在多轮 tool loop 中,一种常见且有利于 Prompt Cache 的做法,是让 provider-visible history 尽量保持 append-only。已经发送过的消息、tool call 和 tool result 不再改写,只在尾部追加新内容。我曾经有一种设想,对上下文进行更细粒度的动态管理,分块处理,进行标记,长内容压缩/摘要,试图节省 Token 消耗以最终减少调用花费。但在进行实验后发现,这样做确实能够带来小规模的 Token 节省,但是从全局看,花费反而升高。

0x01 失败

在探索中,我构建了两套并行的上下文策略,一套为 Dynamic Context,即我天马行空的设想,以下简称 dc 策略罢。另一套为工程实践 Append-Only 的策略,简称ac。在验证设想的过程中,为减少花费,dc 策略是实际请求中所使用的,而 ac 策略为基于同一 trace 的确定性反事实重放。

以执行一个对项目的探索任务作为测试(没做太多控制变量的严谨测试或者 benchmark,俺又不是搞科研嘞),使用模型为 ChatGPT 5.6 Terra,推理强度为 xhigh。

模型价格数据为:

  • 普通输入:$2.50 / M
  • 缓存读取:$0.25 / M
  • 缓存写入:$3.125 / M
  • 输出:$15 / M

逐请求结果:

请求 输入 输出 DC缓存 DC命中率 AC缓存 AC命中率 DC总费用 AC总费用
4 25094 181 9728 38.77% 9728 38.77% $0.043562 $0.043562
5 31198 145 9728 31.18% 25094 80.43% $0.058282 $0.023709
6 39672 232 9728 24.52% 31198 78.64% $0.080772 $0.032465
7 44895 189 9728 21.67% 39672 88.37% $0.093185 $0.025811
8 51177 1966 9728 19.01% 44895 87.72% $0.135545 $0.056419

从请求数据可以看到,自第一个请求以后的数据差异越来越大。

Uncached input 减少:

14339641449143396=71.09%\frac{143396-41449}{143396} = 71.09\%

排除第一个共同基线请求,看后续四次 warm requests:

指标 DC AC
输入 tokens 166,942 166,942
缓存命中率 23.31% 84.38%
输入费用 $0.329803 $0.100422
总费用 $0.367783 $0.138402

Warm phase 总费用下降 62.37%,Warm phase 输入费用下降 69.55%。对比最后一次请求,单次输入费用下降 74.61%,单次总费用下降 58.38%。输出成本较高,因此总费用降幅小于输入费用降幅。

那么是为什么导致 DC 后续的缓存无法命中了呢?这跟 DC 的设计缺陷有关。只有前约 9k 左右的 Prompt 是没有被改变的,能够很好的命中缓存,但是自 9k 往下的新增 block 因为频繁变更导致根本无法命中缓存。

0x02 期望

优化的最终目标是降低总 Token 花费,而不只是单单降低 Token 的总量,或是仅降低上下文占用。

压缩成本

这里以 rur_u 表示普通输入,rcr_c 表示缓存读取,rwr_w 表示缓存写入,ror_o 表示输出。

相关比例为:

  • 普通输入 = 10 × cache read
  • cache write = 12.5 × cache read
  • output = 60 × cache read
  • output = 6 × 普通输入

对第 tt 次请求:

  • ItI_t:总输入
  • CtC_t:cached input
  • Ut=ItCtU_t=I_t-C_t:uncached input
  • WtW_t:显式 cache write
  • OtO_t:输出

请求成本:

Jt=ruUt+rcCt+rwWt+roOtJ_t=r_uU_t+r_cC_t+r_wW_t+r_oO_t

如果把普通输入 token 作为统一单位,可以写成:

Tequiv=U+0.1C+1.25W+6OT_{\text{equiv}} = U+0.1C+1.25W+6O

生成 1K output 的 compaction summary,费用等价于 6K 普通输入或 60K cached input。那么生成 10K summary 的输出费用为 $0.15,等价于读取 600K cached tokens。

所以 LLM compaction 本身非常昂贵。

在当缓存命中达到 90% 至 95% 时,以前文数据核算,相对当前,90% 缓存命中总成本下降约 67.9%,95% 缓存命中总成本下降约 73.2%。

当缓存到达 95% 后,输出成本已经占:

0.040695/0.11030836.9%0.040695/0.110308\approx36.9\%

也就是说,缓存足够高以后,继续优化输入的边际收益会下降,输出长度会成为新的主要成本。

盈亏条件

考虑保留缓存历史与压缩的 break-even:

定义:

  • HH:准备压缩的、已经缓存的历史
  • SS:压缩后的 summary
  • LL:由于前缀被改写,后面一起失效的 collateral suffix
  • NN:未来使用该上下文的请求总数,包含压缩后的第一次冷请求
  • GG:生成 summary 的模型成本

不压缩时:

未来 NN 次继续读取缓存:

Jkeep=N(H+L)rcJ_{\text{keep}}=N(H+L)r_c

压缩时:

第一次请求冷启动,后续 N1N-1 次缓存读取:

Jcompact=G+(S+L)ru+(N1)(S+L)rcJ_{\text{compact}} = G+(S+L)r_u+(N-1)(S+L)r_c

压缩有利需要:

Jcompact<JkeepJ_{\text{compact}}<J_{\text{keep}}

整理后:

N>G+(S+L)(rurc)(HS)rcN> \frac{ G+(S+L)(r_u-r_c) }{ (H-S)r_c }

含义:

  • GG:生成摘要的直接费用
  • (S+L)(rurc)(S+L)(r_u-r_c):冷启动和连带缓存失效代价
  • (HS)rc(H-S)r_c:每次未来请求真正节省的 cache read 成本

如果暂时忽略 summary 生成成本和 collateral:

G=0,L=0,N=1G=0,\quad L=0,\quad N=1

压缩有利需要:

Sru<HrcSr_u<Hr_c

因为:

rc/ru=0.1r_c/r_u=0.1

所以:

S<0.1HS<0.1H

也就是说,如果会重置缓存,压缩后必须小于原长度的 10%,即一次压掉 90% 以上,才能在下一次请求立即回本。

如果压缩发生在上下文中间,那么被修改位置之后即便内容不变,也无法继续命中 prefix cache。

设受影响后缀为 LL

普通冷启动的额外代价:

Pcollateral=L(rurc)P_{\text{collateral}} = L(r_u-r_c)

对于 51K → 10K 的场景,并连带让后面 20K 失效的话,大约需要34 次未来复用才回本;如果还使用显式 cache write,则约需要 37 次。

因此,越靠前修改历史,经济代价越大。

数学期望

考虑有终止概率时的期望:

假设每轮后终止概率为 qq,未来请求数量为几何分布。

如果允许未来请求数为 0:

EN=1qqEN=\frac{1-q}{q}

设压缩回本需要 TT 次未来复用,则经济上值得压缩需要:

1qq>T\frac{1-q}{q}>T

等价于:

q<1T+1q<\frac1{T+1}

例如 51K 压到 10K,需要约 30 次复用:

q<1313.23%q<\frac1{31}\approx3.23\%

只有当每一轮结束任务的概率低于约 3.2%,即预计任务还会持续约 30 轮时,才值得单纯为了费用执行这次 LLM compaction,而日常中的普通 turn 通常不满足,只在长线任务执行,上下文将满时才有意义。

根本目标是费用,真正的优化目标应该为:

minπ  Eπ ⁣[t=1Nπ(ruUt+rcCt+rwWt+roOt)+k=1KπGcompact,k+λqLquality+Lretry+Loverflow]\boxed{ \min_{\pi}\; \mathbb{E}_{\pi}\!\left[ \sum_{t=1}^{N_{\pi}} \left( r_u U_t + r_c C_t + r_w W_t + r_o O_t \right) + \sum_{k=1}^{K_{\pi}} G_{\mathrm{compact},k} + \lambda_q L_{\mathrm{quality}} + L_{\mathrm{retry}} + L_{\mathrm{overflow}} \right] }

而最小化 raw context 并非一个好的选择。

0x03 总结

大家都这么干一定有道理

有时候的天马行空并不能经得起实践的检验。


从零开始的 Agent 开发:上下文,压缩和预算
https://www.letr7.com/2026/07/15/letcode-3/
作者
letr
发布于
2026年7月15日
更新于
2026年7月19日
许可协议