我正在构建一个应用来监控我在Claude Code中的token消费。几天前,查看原始数据时,我遇到了这样的情况:
cacheReadInputTokens: 4.241.579.174
inputTokens: 1.293.019
从缓存中读取的四十二亿个tokens。一百三十万个"新鲜"tokens。这是**99.97%**的缓存命中率。
我的第一反应是认为出了什么问题。没人能达到99%的缓存率。Redis不行。Cloudflare不行。你妈妈说她已经知道你要吃什么的时候也不行。
但事实证明它没有坏。就是这样工作的。而原因既优雅又反直觉。
缓存的不是文本
这里是大多数解释都不够深入的地方。当你看到"提示词缓存"时,你会想到类似Redis的东西:保存问题,保存答案,如果有人问同样的问题就返回同样的答案。
完全不是这样。
缓存的是KV张量——transformer在预填充阶段计算的Key和Value矩阵。用通俗的话说:当LLM收到你的提示词时,它首先要做的是将所有这些文本转换为内部数字表示(embeddings),然后与权重矩阵相乘,得到注意力机制生成响应所需的"键"(K)和"值"(V)。
这种计算是极其昂贵的。在一个200,000个tokens的提示词中(在Claude Code中很常见,对话历史会累积),我们谈论的是数十亿次矩阵乘法运算。这是最消耗GPU的部分,最耗时的部分,成本最高的部分。
这就是巧妙之处:在你的一条消息和下一条消息之间,99%的提示词不会改变。系统提示词是相同的。之前的对话历史是相同的。它读取的文件是相同的。唯一新的是你的最后一条消息。
为什么要重新计算你30秒前已经计算过的东西呢?
匹配机制的工作原理
仅仅缓存是不够的。你必须知道缓存什么时候有用。这里Anthropic使用了一个优雅的技巧:按前缀的累积哈希。
提示词的每个块(system、tools、消息)生成一个哈希。但不是单独的哈希:是累积哈希。第3块的哈希包括第1、2、3块的内容。如果前面任何块中的任何东西发生变化,后面所有块的哈希也会改变。
当新请求到达时,系统从标记有cache_control的点开始向后搜索,逐块比较哈希,直到找到匹配的最长前缀。所有匹配的→从缓存读取。只有新的→重新计算。
这就像一部你已经看了40遍的电影。你不需要看完整部电影就知道会发生什么。你只需要从与你记忆中不同的点开始看。
注意这个数据:系统只向后检查最多20个块。超过这个范围,它就停止搜索。这是一个实用的决定,避免花在搜索缓存上的时间超过直接计算张量的时间。
为什么Claude Code有99%的缓存命中率
现在你知道匹配是如何工作的了,99%就不再神秘了。看看Claude Code中典型会话发生的情况:
消息1(会话中的第一条):
系统提示词 (8K tokens) + 工具 (2K tokens) + 你的消息 (500 tokens)
= 10,500 tokens → 全部计算,全部写入缓存
消息2:
系统提示词 (8K) + 工具 (2K) + 消息1 (500) + 响应1 (3K) + 你的消息2 (500)
= 14,000 tokens
→ 前面的10,500个 → 缓存命中(我们之前已经计算过)
→ 新的3,500个 → 计算并添加到缓存
缓存命中率:75%
消息10:
系统提示词 + 工具 + 9条消息 + 9个响应 + 你的消息10
= ~150,000 tokens
→ 前面的~149,500个 → 缓存命中
→ 新的~500个 → 计算
缓存命中率:99.7%
看到了吗?对话历史只是增长。每条新消息都是累积总数的微小部分。缓存比率以自然对数的确定性收敛到99%。
这不是魔法。这是几何学:分子(新tokens)线性增长;分母(累积tokens)也是线性增长,但有巨大的领先优势。
这些张量存储在哪里
这里事情变得有趣了。因为缓存KV张量不像在Redis中缓存字符串。我们谈论的是GB级的数字数据,必须以微秒级的延迟提供。
Anthropic使用两级系统:
第1级:VRAM(5分钟TTL)
张量直接存在于将要服务下一个请求的GPU内存中。零拷贝,零网络延迟。缓存命中几乎是瞬时的,因为数据已经在需要的地方了。
TTL:5分钟。如果5分钟内没人发出请求,就被逐出。这是标准API使用的缓存。缓存写入价格:正常输入价格的1.25倍。
第2级:GPU节点的SSD(1小时TTL)
如果你支付扩展的缓存写入(输入价格的2倍),张量不会在5分钟后被逐出。相反,当它们因内存压力离开VRAM时,会被下载到GPU节点的本地SSD。
当缓存命中到达时,它们从SSD重新加载到VRAM。比第1级慢,但比从头重新计算张量要快得多。
这里有趣的是:没有网络参与。它不是远程Redis。不是S3。是物理连接到拥有GPU的服务器的SSD。架构设计用来最小化数据移动。
请求 → 在VRAM中? → 是 → 瞬时缓存命中
→ 否 → 在本地SSD中? → 是 → 加载到VRAM → 缓存命中(~毫秒)
→ 否 → 计算KV张量 → 缓存未命中
从2026年2月开始,隔离是按工作空间(之前是按组织)。这意味着你的开发团队的张量不会与市场团队的张量混合,即使它们在同一个Anthropic组织中。
数字
如果你正在评估这对你的用例是否重要,这里是确切的数据:
| 概念 | 值 |
|---|---|
| 缓存读取 | 输入价格的0.1倍(90%折扣) |
| 缓存写入5分钟 | 输入价格的1.25倍 |
| 缓存写入1小时 | 输入价格的2倍 |
| 延迟减少 | 长提示词中约85% |
| 最小可缓存量 | 每个检查点1,024个tokens |
使用Sonnet,输入成本为3.00美元/百万tokens。缓存读取成本为0.30美元/百万。在有200K tokens历史的Claude Code会话中,重新计算和从缓存读取的差异是每条消息0.60美元和0.06美元的差异。
将其乘以你在长会话中可能交换的数百条消息,就能理解为什么Anthropic投资构建这个:没有提示词缓存,带有巨大上下文的长对话在经济上是不可行的。
我的真实数据
回到我开头的数字。在我一个月的Claude Code使用中:
cacheReadInputTokens: 4.241.579.174 (42亿 — 从缓存读取)
cacheCreationInputTokens: 196.596.243 (1.97亿 — 写入缓存)
inputTokens: 1.293.019 (130万 — 无缓存计算)
outputTokens: 2.517.666 (250万 — 模型生成)
全局缓存命中率:95.5%。在长的单独会话中,轻松超过99%。
注意不对称性:我从缓存中读取了42亿个tokens,但模型只生成了250万个输出tokens。缓存读取与实际工作的比率是1,685:1。模型每产生一个token,就重复使用1,685个先前上下文的tokens。
这也意味着cacheReadInputTokens不是生产力的好指标。它不衡量你"使用"模型的程度。它衡量模型重新阅读了多少历史。这就像通过你在编辑器中打开同一个文件多少次来衡量你的生产力。
Anthropic没有说的事情
有些事情不是公开的:
- 用户→GPU亲和性:他们如何保证你的下一个请求落在有你缓存的同一个节点上?可能是会话的粘性路由,但他们没有确认。
- SSD类型:NVMe?CXL连接?200K tokens提示词的KV张量占用几个GB。SSD的速度很重要。
- PagedAttention:vLLM(最受欢迎的开源服务引擎)使用一种叫做PagedAttention的技术,将KV张量作为虚拟内存页面管理。Anthropic是否使用类似的东西,或者有专有的东西?不得而知。
- 集群拓扑:多少个GPU,它们如何互连,是否使用InfiniBand或以太网。没有公开信息。
总结一切的类比
将提示词缓存想象成外科医生在手术过程中的工作记忆。
外科医生(模型)必须处理患者的所有信息(提示词)来决定每个动作(输出)。没有缓存,他必须在每次切割前重新阅读完整的病史。有了缓存,他记住所有已经阅读过的内容,只需要处理新信息——最新的分析,组织对上次切割的反应。
保存的不是患者的文档(文本)。是外科医生已经从这些文档中提取的中间结论(KV张量)。他不需要重新阅读分析。他已经知道它说什么了。他只需要将新的与已知的整合。
99%的缓存命中简单地反映了,在与LLM的对话中,“我们已经知道的"数量比"需要处理的新内容"数量增长得快得多。
用通俗的话说,这就是使你能够进行200K tokens上下文的对话而不会让每条消息都花费你一个肾脏和另一半肾脏的原因。
相关: 如果你对当监控这些tokens的应用程序基于AI本身发明的数据时会发生什么感兴趣,请阅读静默失败:当你的AI发明而测试说一切都很好。如果你想看我如何管理API密钥而不让1Password每30秒要求Touch ID,授权疲劳和40行缓存。