跳转到主内容
博客
Token 业务的暗线:决定成本的不是吞吐,是 KV cache 命中

Token 业务的暗线:决定成本的不是吞吐,是 KV cache 命中

大家算 token 成本,习惯盯 TTFT、TPOT、吞吐速率。真正让账单差出 10 倍的是 KV cache 有没有命中。模型、服务端、用户三层都得对得上。

关嘉伟关嘉伟5 分钟阅读
分享:

最近研究 token 这个行业越多,我越觉得有一根弦被普遍低估了。

过去一年大家算推理性能,主要盯三个数:绝对吞吐、TTFT、TPOT。一个请求进来能并到几路,首 token 出来多快,每个 output token 多快。这套话术今天很主流。

但坐下来真做 serving,你会发现真正决定 token 成本的不是吞吐速度,是 KV cache 有没有命中。

一、10 倍的鸿沟,被刻进了定价表

最近几家模型 API 都在降价。打开价目表一看,input 这一列很久之前就被拆成了两栏:cache hit 和 cache miss。

差多少?

Anthropic 的 cache read 是 base input 价格的 0.1 倍,便宜 10 倍。DeepSeek V4 Flash 的 cache hit 是 0.0028 美元/百万 token,cache miss 0.14 美元/百万 token,差 50 倍。Anthropic 这边写一份 cache 还得付 1.25 倍(5 分钟版)或 2 倍(1 小时版)。DeepSeek 今年 4 月 26 号又把所有模型的 cache hit 价格再砍掉 10 倍。

落到机器层面,差的是计算资源。命中 cache 等于跳过 prefill,机器只做 decode 那一小段。不命中就是从头算一遍,占机器时间、占算力,差出来不是几个百分点,是数倍到 10 倍这个量级。

有意思的地方在这:cache hit/miss 被拆开计价之后,价格里有一部分用户能通过设计去争取,另一部分完全由供应商决定。两边一拆,"哪家 API 便宜"在 token 维度上就不再可比了,得看实际命中率。

二、用户侧最大的坑:模型路由

来说说用户侧能怎么把这事搞砸。

这两年大家蛮迷信"模型路由",复杂任务给强模型、简单任务给弱模型,看起来很省。

我的看法是:在一个 session 里中途换模型,多数时候是亏的。

最直接的例子是 Claude Code。你已经积到 300K 上下文,中间觉得这一步用 Opus 太贵,切到 Sonnet。Claude Code 现在会弹一个提示,明确告诉你:切换后前面的 cache 全部失效,下一步必须冷启重算一次。以前是不提醒的,被骂多了才加上。

为什么会失效?每个模型的 KV 表征不一样,cache 不能跨模型复用。Opus 的 cache 和 Sonnet 的 cache 是两个东西,session 没换、cache key 没动,底下重算的成本一文不省。

算一笔账。当前 Opus 4.7 是 5/5/25 每百万 token,Sonnet 4.6 是 3/3/15。Sonnet 比 Opus 便宜 40% 左右,不是过去 5 倍那么夸张了。你前面那 300K input 要从 cache 命中(0.1 倍价格)变成冷算(1 倍价格),单次 input 成本翻 10 倍。模型本身省下来 40%。两头一抵,整体反而贵了 5 倍以上。

而且 agent 这种业务里,token 几乎都是 input 重、output 轻。prefill 一般每秒几千 token,decode 几十到一百多 token,差两个数量级。钱基本花在 input 上。模型路由毁掉的恰好是 input 这边的省钱机制。

所以现在主流 agent 设计都围绕"上下文稳定"在做。模型不能轻易换,工具结构不能动,CLAUDE.md 这种核心 prompt 半路也不能改。一动,命中率从 90% 掉到 5% 是真发生的事。

三、Claude Code 的解法:spawn 子 agent

那任务里如果真有一部分更适合便宜模型,怎么办?

Claude Code 的解法是 spawn 子 agent。

主 session 守在 Opus 这一档,命中率保得住。需要 explore、批量处理、跑某个特定子任务,调一下 Task 工具开一个新 agent。新 agent 在自己隔离的 context 里跑,可以挑更便宜的模型,自己维持自己的命中率。跑完只把摘要回传给主 session,主 session 的 cache 不污染。

这个机制成立的前提:子任务的上下文需求跟主任务差异够大。如果你的子任务恰好要把主 session 大部分内容也喂进去,等于在子 agent 里又冷启一遍,省下来的钱被 prefill 吃光。这事得挺精细地判断。

四、服务端的 KV cache 工程

服务端这边差异有多大?非常大。

最粗糙的实现是没怎么针对 cache 做设计。多用户之间不能复用,路由乱跑(本该回那台带 cache 的机器,调度去了别处),显存兜底所有 cache 容量。这种系统下,用户侧再精心也救不回来。

成熟的代表是月之暗面、清华大学与趋境科技等机构联合做的那套 Mooncake 框架,KVCache-centric 的 disaggregated 架构。prefill 和 decode 集群分开,把 GPU 节点上没用满的 CPU、DRAM、SSD 资源拿来做 KV cache 的分布式池,再用一个 KV cache 调度器决定排队和路由。论文里给的数字是模拟 525% 吞吐提升,真实负载下处理请求量增加 75% 到 115%。

反例是 Openclaw。这套开源 agent 之前被骂得比较惨,主要栽在这一层。它的 plugin 架构默认不设 promptCacheKey,过第三方 proxy 拿不到节点亲和,cache 命中率近乎 0%。你看它跑的 token 总量其实不夸张,但 input 全是 cache miss 价位,账单就离谱。我大概一个月前看过它的 trace:6 万多 input token 一次请求,0% 命中,单次 $0.12 出去——典型的服务端 cache 没做针对性设计。

五、模型层也能往这条路压

再往下一层,模型层本身可以为 KV cache 让出非常大的空间。

DeepSeek 是把这件事做得最系统的。MLA(Multi-head Latent Attention)把 KV 投影到一个 latent 向量再回弹,KV cache 体积压了 90% 以上;V3 一直延续这个机制;后来又加 Native Sparse Attention,KV cache 在长上下文里的增长几乎被压平。这样推理系统才能在百万级上下文里把 cache 池的容量做起来。

但模型一改,cache 命中的判定逻辑也会变。某些原本会被认作"前缀重叠"的输入,进了 sparse attention 之后机制不一样,能不能命中要重新对齐。所以推理系统也得跟着改一轮。这是为什么我说做推理的人现在不能只盯吞吐,得围着模型架构去重新设计 cache。

六、想测出这件事,很难

整套链路最头疼的一点:单独评估服务端没用,单独评估用户侧也没用。

服务端 cache 做得再强,用户侧像 Openclaw 那样设计,命中率依旧抬不起来。用户侧再精心,碰到一个粗糙的服务端,路由乱、容量不够、跨用户不复用,一样掉成本。

所以"哪家 API 便宜"在 token 这件事上不能单点比。同样的硬件、同样的目标,两端配合得好和两端各做各的,整体账单可以差 5 到 10 倍。

写在最后

token 定价表上 cache hit/miss 分两栏,是这整件事最重要的一根弦。它给用户透传了一个激励:你命中率做得高,你就省钱;同时也对服务端施压:cache 系统不够强,就拿不到生意。

我希望厂商把 cache 命中机制本身也透传出来。不然用户侧只知道有这件事,不知道怎么针对它做优化。能把"模型、服务端 cache、用户侧使用"这三段端到端打通的厂商,目前还不多。

边端这边现在还在比裸性能。但等应用密度上来、agent 真的跑起来,KV cache 同样会成为主线问题。从云端到边端,绕不开。


参考资料

推荐阅读

订阅博客更新

新文章发布时第一时间通知你,不会发送垃圾邮件。

仅用于博客更新通知,随时可以取消订阅。

评论

或匿名评论
0/2000