AI

Agent 成本中的 Prefix Cache:从缓存命中率理解有效价格

Agent 会重复提交不断增长的上下文。模型选型需要同时考虑输入标价、缓存价格、命中率、请求形态和任务级总成本。

核心结论

在 Agent 场景中,只看模型价格表里的普通输入单价,容易误判真实成本。多轮 Agent 会在每次调用时反复提交 system prompt、工具定义和对话历史,其中大量 token 属于重复前缀。

如果 provider 能持续命中这些前缀的缓存,重复 token 会按 cached input 计费,同时减少 prefill 计算;如果命中率很低,每轮都要重新处理不断增长的上下文。

因此,Agent 的模型选型更应该关注:

有效输入价格
= 未缓存输入占比 × 普通输入单价
+ 缓存输入占比 × 缓存输入单价

当缓存命中率用输入 token 占比表示时,可以近似写成:

effective_input_price
= (1 - hit_rate) × uncached_input_price
+ hit_rate × cached_input_price

这比 headline input price 更接近长任务中的真实输入成本。

为什么 Agent 对 Prefix Cache 敏感

一次普通问答可能只调用模型一次,而 Agent 通常需要反复调用模型:

固定 system prompt
+ 固定 tools schema
+ 先前消息与工具调用
+ 本轮新增内容

随着轮次增加,历史上下文越来越长,但每轮真正新增的内容可能只占一小部分。没有缓存时,累计输入量会快速增长;有稳定 Prefix Cache 时,旧前缀可以被复用,主要为新增部分支付普通输入成本。

因此,Agent 成本不仅取决于上下文有多长,还取决于其中有多少内容能够作为稳定前缀被重复利用。

Prefix Cache 优化的是什么

LLM 推理可以粗略分为两个阶段:

  1. Prefill:处理完整输入,为输入 token 计算中间状态并建立 KV cache。
  2. Decode:逐 token 生成输出,重复读取历史 token 的 KV cache。

Prefix Cache 复用多个请求之间相同前缀的预计算状态,主要减少重复 prefill。它和单次请求 decode 阶段使用的 KV cache 概念不同,但底层通常会复用或保存前缀对应的 KV 状态。

Decode KV cache:
避免同一次生成过程中反复计算历史 token。

Prefix Cache:
避免不同请求之间反复计算相同输入前缀。

这也意味着 Prefix Cache 不只是计费优惠。命中缓存还可能降低 TTFT,因为服务端不必重新完成整段前缀的 prefill。

Cache Hit Rate 不是模型的固有能力

文章使用 OpenRouter 模型页的 Effective Pricing 数据比较不同模型和 provider。这里观察到的缓存命中率,不应直接解释为某个模型“天然更会缓存”。

它更接近下面这些因素共同形成的运行结果:

  • 用户是否主要用该 endpoint 运行 Agent 或长对话。
  • 请求中是否存在足够长且稳定的共同前缀。
  • provider 是否支持 Prefix Cache,以及缓存价格如何设置。
  • 缓存池大小、TTL 和淘汰策略。
  • 请求是否能被稳定路由到持有对应缓存的实例。
  • OpenRouter 所观察到的流量结构。

因此,比较缓存命中率时,分析单位应该是:

模型 × provider endpoint × 请求流量形态

而不只是模型名称。

同一个开源模型由不同 provider 部署,真实有效价格可能明显不同。Provider 的推理系统是模型成本的一部分。

高命中率也不能单独代表低成本

单次请求的缓存命中率可以近似理解为:

cached_input_tokens / total_input_tokens

例如一个请求有 100,000 个输入 token,其中 85,000 个按缓存输入计费,命中率就是 85%。

但百分比不能脱离绝对 token 数量理解:

100K 输入 × 90% 命中

未必比:

10K 输入 × 50% 命中

更便宜。完整判断至少需要同时考虑:

  • 总输入 token。
  • 未缓存输入单价。
  • 缓存输入单价。
  • 缓存命中率。
  • 输出 token 与输出单价。
  • Agent 完成任务所需的调用轮次。

最终应该比较的是任务级成本,而不是某一次请求的命中率。

小模型不一定让 Agent 长任务更便宜

小模型通常有更低的普通输入单价和推理成本,但如果某个 provider 的 Prefix Cache 支持较弱,Agent 每轮仍要重新 prefill 大量历史上下文。

相反,一个普通输入单价更高的模型,如果缓存输入足够便宜、长期命中率足够高,可能获得更低的有效输入价格。

这形成了一个反直觉判断:

模型越小或标价越低,不等于 Agent 完成一次长任务的总成本越低。

模型选型不能只比较模型规模和公开标价,还要把 provider、缓存机制和真实请求形态纳入同一组实验。

Prompt 结构决定前缀是否稳定

Prefix Cache 依赖相同的 token 前缀。前面越早出现动态内容,后面越大一段内容越难复用。

不利于缓存的结构包括:

  • 在 system prompt 前部写入当前时间或随机值。
  • 每轮重新排序 tools schema。
  • 动态改写系统提示词。
  • 把检索结果、错误日志等易变内容放在固定内容之前。
  • 每轮重排消息或工具调用结构。

更有利于缓存的上下文顺序是:

固定层:system prompt、角色约束、tools schema
→ 半固定层:项目背景、用户偏好、长期上下文
→ 动态层:当前任务、检索结果、工具输出、临时状态

这里的目标不是为了命中率而牺牲语义正确性,而是在语义等价时保持序列稳定,把变化尽量推迟到上下文后部。

长输出与工具结果会改变后续成本

上一轮生成的长输出,在下一轮首次作为输入时,会成为新增上下文。它会增加输入 token,也会占用更多缓存空间。继续进入后续轮次后,这段内容才可能转化为可复用前缀。

工具输出也有相同问题。完整日志、文件内容、搜索结果和 reasoning trace 如果被无限追加,会同时带来:

  • 更高的绝对输入成本。
  • 更大的 prefill 与缓存压力。
  • 更容易变化的前缀结构。
  • 更快的上下文窗口消耗。

所以 Agent 的上下文治理不能只追求高命中率,还需要裁剪、摘要和结构化保存,只把下一步判断真正需要的信息放回模型上下文。

从文章数据可以得出什么

文章的数据能够支持这些判断:

  1. Agent 场景中,有效输入价格比普通输入标价更有解释力。
  2. 不同模型和 provider endpoint 的长期缓存表现可能有明显差异。
  3. 高缓存命中率可以显著改变模型之间的成本排序。
  4. Provider 的缓存与调度能力会进入 Agent 的真实成本结构。

但仅凭这些观测数据,不能直接证明:

  • 某个模型架构必然带来更高的 Prefix Cache 命中率。
  • 高命中率完全来自 provider 的缓存实现。
  • 一个 endpoint 的历史统计可以直接代表自己的业务流量。
  • 高命中率模型一定拥有最低的任务级总成本。

这些问题仍需要结合具体请求分布和受控实验验证。

工程推论:模型架构与缓存资源

Prefix Cache 需要保存可复用的中间状态,会占用 HBM 或其他高带宽内存。Provider 需要在缓存容量、并发、batch、上下文长度和模型副本之间分配有限资源。

因此,在请求形态相同的前提下,更大的缓存池、更长的 TTL 和更稳定的路由通常有利于提高长期命中率,但会产生机会成本。

DeepSeek 的 MLA 等降低 KV cache 体积的模型架构,理论上能让相同内存容纳更多缓存状态,为长期 Prefix Cache 提供更好的资源条件。但这只是合理的基础设施推论,不能仅凭 OpenRouter 的命中率数据断言 MLA 是高命中率的直接原因。

实际评估方法

评估一个模型是否适合 Agent,不应照搬平台整体统计,而应使用自己的任务分布做回放测试:

  1. 选取短问答、长对话、多工具调用和长文件任务。
  2. 保持 prompt 结构、工具顺序和路由条件可复现。
  3. 记录每轮总输入、缓存输入、输出 token、TTFT 和总延迟。
  4. 分别计算请求级成本和完成整个任务的累计成本。
  5. 对比不同模型与 provider endpoint,而不只对比模型名。

最终需要回答的不是“哪个模型缓存命中率最高”,而是:

在自己的 Agent 请求形态下,哪个模型与 provider 组合能以可接受的质量、延迟和稳定性完成任务,并拥有最低的任务级总成本?

Back to Blog

Related Posts

View All Posts »