AI技术·2026年4月20日·6 分钟

Prompt Caching:LLM 推理成本优化的核心机制

以 Claude Code 为案例,深入讲解 LLM 推理中的 Prompt Caching 机制——从 KV Cache 原理到缓存经济学,再到如何维持 92% 缓存命中率的实战策略,帮你省下大笔推理费用。

每次 AI Agent 采取行动,都会把整个对话历史重新发送给 LLM。

这包括系统指令、工具定义,以及它三个回合之前就已经处理过的项目上下文。所有这些内容在每一轮都会被重新读取、重新处理、重新计费。

Agent 请求示意图

对于长时间运行的 Agent 工作流来说,这种冗余计算往往是你整个 AI 基础设施中最昂贵的一项开支。

一个包含 20,000 个 token 的系统 prompt,运行 50 轮就意味着 100 万个 token 的冗余计算,按全价计费,却产生零新增价值。而且这个成本会在每个用户、每个会话之间不断叠加。

解决这个问题的方法就是 prompt caching。但要用好它,你需要理解底层到底发生了什么。

静态上下文 vs 动态上下文

在优化 prompt 之前,你需要先搞清楚什么在变、什么不变。

每个 Agent 请求都包含两个根本不同的部分:

静态前缀与动态后缀

静态前缀——在各轮之间保持不变的部分:系统指令、工具定义、项目上下文和行为准则。

动态后缀——随着每一轮不断增长的部分:用户消息、助手回复、工具输出和终端观察结果。

正是这种分离使 prompt caching 成为可能。基础设施会存储静态前缀的数学状态,这样后续共享相同前缀的请求就可以完全跳过计算,直接从内存中读取。

一旦你理解了这一点,本文中的每一个架构决策都会变得显而易见。

KV Cache 是如何工作的?

要理解缓存为何如此有效,你需要了解 Transformer 在处理 prompt 时实际做了什么。

每个 LLM 推理请求都包含两个阶段:

Prefill 和 Decode 阶段

Prefill 阶段处理整个输入 prompt。它对上下文中的所有 token 运行密集矩阵乘法,构建模型的内部表示。这是计算密集型的,非常昂贵。

Decode 阶段逐个生成 token。每个新 token 被添加到序列中,模型预测下一个。这个阶段是内存密集型的,因为它主要读取历史状态而非进行大量计算。

在 prefill 阶段,Transformer 为每个 token 计算三个向量:Query(查询)、Key(键)和 Value(值)。注意力机制利用这些向量来确定每个 token 与其他所有 token 之间的关系。任何给定 token 的 Key 和 Value 向量仅取决于它之前的 token,一旦计算完成就永远不会改变。

KV Cache 工作原理

没有缓存的情况下,这些 Key 和 Value 张量在每次请求后都会被丢弃,下一次请求会从头重新计算它们。对于一个 20,000 token 的前缀来说,这就意味着 20,000 个 token 的注意力机制的计算是完全没有必要的。

KV cache 通过将那些张量持久化存储在推理服务器上来解决这个问题,以 token 序列的加密哈希作为索引。当新请求携带相同的前缀到来时,哈希匹配,张量从内存中加载,这些 token 的 prefill 计算被完全跳过。

这将每个生成 token 的计算复杂度从 O(n²) 降到了 O(n)。而对于一个在 50 轮中重复出现的 20,000 token 前缀来说,这是一个巨大的削减。

经济学

定价结构才是让这个架构决策如此重要的关键。

缓存读取成本是基础输入价格的 0.1 倍,即每个缓存 token 享受 90% 的折扣。缓存写入成本是 1.25 倍,比存储 KV 张量贵 25%。延长一小时缓存成本是 2.0 倍。

以下是 Anthropic 各 Claude 模型的定价对比:

定价对比

这种计算方式只有在缓存命中率保持高位时才成立。最佳的生产实践案例就是 Claude Code。

Claude Code 的 30 分钟编码实战

Claude Code 的整个设计围绕一个核心目标:保持缓存热度。

以下是一次真实的 30 分钟编码会话的计费全景。

第 0 分钟:Claude Code 加载系统 prompt、工具定义和项目的 CLAUDE.md 文件。这个载荷超过 20,000 个 token,由于每个 token 都是全新的,这是整个会话中最昂贵的时刻。但你只需支付一次。

第 1-5 分钟:你开始下达指令,Claude Code 派出 Explore Subagent 导航代码库、打开文件、执行 grep 命令。所有这些都追加到动态后缀中。但 20,000 token 的静态前缀现在从缓存读取,价格从 $3.00/MTok 降到 $0.30/MTok。

第 6-15 分钟:Plan Subagent 收到的是经过摘要的简报而非原始结果,因为传递原始输出会不必要地膨胀动态后缀。它产出一个实施方案,你审批通过后,Claude Code 开始修改代码。每一轮都从缓存读取静态前缀,命中率攀升至 90% 以上,每次访问都会重置 TTL 以保持缓存热度。

第 16-25 分钟:你提出修改要求,意味着更多的工具调用、更多的终端输出、更多的上下文积累在动态后缀中。此时会话已处理数十万个 token,但每一轮都在从缓存中读取那 20,000 token 的基础层。

第 28 分钟:你在终端运行 /cost。如果没有缓存,200 万个 token 按 Sonnet 4.5 的费率计算需要 $6.00。而缓存以 92% 的效率运行,其中 184 万个 token 是缓存读取,总成本仅 $1.15。单次任务的成本降低了 81%。

30 分钟编码会话计费全景

这就是热缓存的样子。静态基础层只需付费一次,之后就可以免费读取。只有动态尾部才是真正需要付费的部分。

破坏缓存的头号杀手

关于 prompt caching,最反直觉的一点是:

"1 + 2 = 3" 能命中缓存,但 "2 + 1" 却会缓存未命中。

基础设施会从头开始对整个 token 序列进行哈希。如果序列中的任何内容发生变化,哪怕只是两个元素的顺序调换,哈希值就会改变,整个前缀都会被以全价重新计算。

缓存失效示例

这不是一个小小的实现细节。它是 Claude Code 所有工程决策所围绕的核心约束。

以下是生产环境中真实发生过的缓存失效案例:

系统 prompt 中注入的时间戳导致每次请求都生成唯一的哈希值。

JSON 序列化器在不同请求之间以不同顺序排列工具 schema 的键,导致前缀失效。

一个 AgentTool 的参数在会话中途被更新,清空了整个 20,000 token 的缓存。

由此可以推导出三条规则:

不要在会话过程中修改工具。工具定义是缓存前缀的一部分,增加或删除工具会使下游所有内容失效。

不要在会话中途切换模型。缓存是模型特定的,这意味着在对话过程中切换到更便宜的模型需要从头重建整个缓存。

不要通过修改前缀来更新状态。Claude Code 不会编辑系统 prompt,而是在下一条用户消息中追加一个提醒标签,让前缀保持不变。

最大化缓存命中的 Prompt 结构

无论你使用 Claude Code 还是从零构建自己的 Agent,同样的规则都适用。

按以下顺序组织你的 prompt:

系统指令和行为规则放在最顶部。会话过程中不要修改。

预先加载所有工具定义。不要添加或删除。

接下来是检索到的上下文和参考文档。在会话期间保持稳定。

对话历史和工具输出放在最底部。这就是你的动态后缀。

Prompt 结构

在 Anthropic API 上启用自动缓存后,缓存断点会随着对话增长自动推进。如果没有这个功能,你需要手动追踪 token 边界,一旦边界设错就会完全错过缓存。

当接近上下文限制时进行上下文压缩,使用缓存安全的分叉方式。保持相同的系统 prompt、工具和对话历史,然后将压缩指令作为新消息追加。缓存的前缀会被复用,唯一需要计费的新 token 就是压缩指令本身。

缓存安全分叉

如何验证缓存是否生效

要验证缓存是否正常工作,监控每次 API 响应中的这三个字段:

cache_creation_input_tokens 是写入缓存的 token 数。

cache_read_input_tokens 是从缓存中读取的 token 数。

input_tokens 是未使用缓存直接处理的 token 数。

你的缓存效率 = cache_read_input_tokens / (cache_read_input_tokens + cache_creation_input_tokens)。像监控可用时间一样去追踪它。

Prompt caching 不是你打开的一个开关。它是你需要围绕其设计的架构纪律。

核心思想很简单:将 prompt 组织成静态内容在顶部、动态内容在底部增长的结构。基础设施会对前缀进行哈希,存储 KV 张量,并在每次后续读取时给你 90% 的折扣。

但真正的纪律在于细节。不要在系统 prompt 中注入时间戳,不要打乱工具定义的顺序,不要在会话中途切换模型,不要修改缓存断点上方的任何内容。

Claude Code 展示了大规模应用的效果——92% 的缓存命中率和 81% 的成本削减。如果你在构建 Agent 却没有围绕 prompt caching 来设计,你正在浪费大部分成本优势。