巧用缓存,让 Claude 用得更划算

HN AI Tools 2026-10-23T21:38:07.167964

了解 Claude 的提示缓存(prompt cache)如何工作,以及如何控制 token 用量

你可能注意到,一段很短的提示词有时会消耗掉惊人的 Claude 用量。如果你把这段提示发到一个已经闲置了一阵子的会话里,很可能就是没命中缓存。以 Opus 5.5 为例,缓存未命中的成本最高可达命中时的 40 倍。下面我们来看看究竟发生了什么,以及怎么避免。

#缓存

简单说,缓存就是存放你之前提示词处理结果的临时存储。实际机制要更复杂一些,因为存下来的是中间结果(KV 表示),但要理解怎么利用它,不需要了解这些细节。

举个例子:你发一条提示,让 Claude 开发某个功能。你的工具(比如 Claude Code)会把你的提示发给 Opus,同时附带额外上下文:系统提示、你的 AGENTS.md 内容、技能(skills)等等。

Claude 处理完整个提示,把结果存入缓存,然后回复你。

当你发第二条消息时,工具会把整个上下文再发一遍。好消息是,Claude 不会从头处理。它会复用缓存里存的结果,只处理新增的信息。新的结果又会被存进缓存,为你下一轮对话做好准备。同样,这是简化后的说法,有些细节差异,但作为心智模型够用了。

缓存带来了巨大的性能提升,但它要占存储空间,而空间是有限的。如果过了一段时间 Claude 没收到你的后续消息,它就会清掉存下的结果,把空间让给别人。

这意味着,缓存被清掉之后再发的消息,必须把整个上下文重新处理一遍。

这就是所谓的“缓存未命中”。反过来,当你的消息能复用缓存里的结果时,就叫“缓存命中”。

#缓存未命中的代价

你已经看到,每个模型都会列出每百万输入 token 和输出 token 的价格,同时还会列出“缓存读取”和“缓存写入”的价格。

比如,Opus 5.5 每百万输入 token 收费 4 美元,但缓存读取每百万只要 0.20 美元。也就是说,命中缓存便宜了 20 倍。

写入缓存还有额外成本:Opus 5.5 对 1 小时缓存写入收取正常输入价格的 2 倍。因此,命中缓存和未命中缓存的成本差距达到 40 倍。

Claude API pricing

Claude API 定价

#示例

假设你正在一个带有 30 万 token 上下文的会话中工作,然后发送一条 1k token 的新消息。会有两种情况:

在这个贴近实际的例子里,未命中缓存的成本要高 35 倍以上。

#一般情况

如果已有 token 数为 P,新 token 数为 N,两种情况的成本分别是:

两者之比为:

已有上下文 P 越大、新消息 N 越小,未命中缓存的成本就越接近命中缓存的 40 倍。

#如何避免缓存未命中

默认情况下,Claude Code 使用 1 小时缓存,也就是说,缓存在最后一次写入或读取后 1 小时过期。其他运行框架(harness)可能使用不同的缓存时长。

一种策略是持续发送消息,让缓存一直不过期。手动做法是,在缓存过期前发送类似下面这样的话:

wait, I'm still working on this

这条消息大约 10 个 token,但它可能向缓存写入超过 100 个 token,因为发送时会附带额外数据,比如上一条回复以及用户/系统标记。

所以,套用上面的公式,相比缓存未命中,这样做的成本节省接近 40 倍。上下文只有 100k token 时,就已经能带来 38.5 倍的成本节省。

注意,把第一个小时写入缓存要花 2 倍基础 token;而命中缓存后,每延长一小时只需 0.05 倍基础 token。也就是说,如果能把这个过程完全自动化,1 小时缓存成本是 2 倍,2 小时缓存是 2.05 倍,3小时缓存成本是 2.1 倍,以此类推。这里的成本不对称非常明显,完全可以加以利用。

自动化执行

Claude Code 有一个 /loop 命令,可以按计划定时发送消息。

它不是免费的,但循环大约 40 次的开销,才抵得上一次缓存未命中。

问题在于,cron 语法里没有简单办法表达「每 50 分钟一次」。最简单的替代方案是在 :00 和 :30 各跑一次,20 小时内正好 40 轮。

保住缓存的替代方案

最好的替代方案是用 /compact 命令压缩上下文。压缩会对对话做摘要,让上下文本身变小。代价是你可能丢掉一部分上下文,而这些内容之后可能恰好用得上。

压缩的成本取决于你的 harness,也就是发出压缩指令的那个工具。对 Claude Code 来说,这条指令大约 2k token。当前整个上下文都会命中缓存*,价格是基础 token 的二十分之一,而那 2k 指令 token 是新增的。这些指令也可以选择不写入缓存,但文档里没说清楚实际会怎样。

然后 Claude 输出摘要,这属于输出 token。输出 token 比输入 token 贵得多。比如 Opus 5.5,输出价格是基础输入价的 5 倍。按我的经验,摘要通常在 30k token 以内,相当于 150k 基础输入 token 的费用。这部分很容易被忽略,但往往是压缩过程中最贵的开销。

压缩后的第一条消息会把摘要写入缓存,同时写进去的还有系统提示词和工具定义。系统提示词和工具可能又是 30k token,但这很大程度上取决于你的配置。可以用 /context 查看上下文大小。

*注意

如果压缩时没有命中缓存,那绝对是最糟的情况。你要按 2 倍价格把整个上下文写入缓存,再加上压缩本身的费用、按 5 倍基础 token 价格输出的摘要,然后还要再按 2 倍价格把摘要以及系统提示词和工具写回缓存。记住:缓存过期时千万别压缩!

示例

回到那个上下文有 300k token 的会话,在缓存过期前对它做压缩:

总计 291k 基础输入 token。大约是那次 602k 缓存未命中花费的一半,但比缓存命中的 17k 贵得多。

省钱发生在后面。此后每条消息只需从缓存读取约 60k token,而不是 300k,成本约 5k 基础输入 token,而不是 17k。消息发得足够多,压缩的成本就赚回来了。

可以看到,不同策略的优劣很大程度上取决于几个变量,比如上下文大小和摘要长度。该做一次交互式对比了。

#交互式对比

下面是我们讨论过的三种场景:让缓存过期、循环发送等待消息、压缩上下文。图表展示了暂停期间以及暂停后前 10 条消息的累计基础 token 成本。

哪种策略最好,主要看上下文大小和需要循环的时长。粗略的经验是:上下文大或暂停时间长,就压缩;否则就循环。

至于什么算“大上下文”、什么算“长暂停”,两者互相牵制。但大致上,600k token 算大上下文,8 小时以上算长暂停。

如果你喜欢更细的判断流程,可以参考这套决策树:

2–4 小时这一段是灰区。在这里,主要的问题是:

下面是 Claude 提供的一张流程图:

在暂停时选择 /loop 还是 /compact 的流程图

在暂停时选择 /loop 还是 /compact 的流程图

#结论

当我意识到命中缓存和未命中缓存会带来 40 倍的使用量差异时,我以为自己靠循环策略挖到了宝藏。但把 /loop 和 /compact 放在一起对比后,我重新评估了它们各自更适用的场景。

我依然认为,在很多常见场景下 /loop 是最佳选择,比如午休时间较长,或者出门办事。

即便如此,上下文很大时,或者上下文中等而暂停时间很长时,压缩显然是更明智的选择。丢失相关上下文是倾向用 /loop 的一个理由,但随着模型越来越聪明,它们生成的摘要也会越来越好,这个问题会慢慢消失。

不过,压缩在保真度上有硬性上限。从 800k 的上下文压到 30k,压缩比超过 26 倍,肯定会丢失一些相关内容。作为参考,关于提示压缩的研究似乎都认为,10 到 20 倍压缩是甜点区,此时大部分相关信息仍然保留,而到 25 倍左右性能就会下降。那项研究压缩的是提示本身,而不是对它做摘要,但这个数字仍是一个有用的参照。

#附:Claude Code 可能会自动压缩你的上下文

就在我写这篇文章的时候,看到 Claude Code 报告:

 ⏺ Compacted while idle, before the prompt cache expired

当时我正在试验不同的上下文大小和缓存,刚抓取了我的 /context,只有 220.3k tokens。

上下文使用情况

看起来 Anthropic 也认同缓存未命中不是什么好事,只是在这个场景下,双方对最佳策略的看法不同——毕竟我当时只离开了一个多小时。

如果 Claude Code 能提供一个管理缓存过期时间的设置就好了。这样我就能根据手头的工作,把它设成:

“离开时长”可以作为一项输入,交给运行框架(harness)。

查看原文