提示缓存:让 AI 记住算过的东西,账单直降八成
来自 @_avichawla 的详尽解释:KV 缓存原理、Anthropic 定价账、Claude Code 92% 命中率实战,以及三条铁律。
开篇:AI 智能体最贵的地方,是重复计算
AI 智能体每执行一个步骤,都会把整个对话历史重新发回给大模型:系统指令、工具定义、三轮之前处理过的项目上下文——全部再读一遍、再算一遍、再按全价计一次费。
算笔账:一个 2 万 token 的系统提示,跑 50 轮,就是 100 万 token 的冗余计算,按全价计费,却没产生任何新价值。对长时间运行的智能体工作流,这通常是整个 AI 基础设施里最贵的一项,而且每个用户、每个会话都在累积。
解法是提示缓存(prompt caching)。但要真正用好它,得先懂底层原理——这门课就是干这个的。
先分清:静态上下文 vs 动态上下文
优化提示之前,先分清每次请求里哪部分会变、哪部分不变。每个智能体请求都包含两种截然不同的部分:
- 静态前缀:所有轮次都不变——系统指令、工具定义、项目上下文、行为准则;
- 动态后缀:每轮都在变长——用户消息、助手回复、工具输出、终端观察。
基础设施会把静态前缀的数学状态存下来,后续共享同一前缀的请求直接从内存读,跳过计算。一旦理解这个拆分,后面所有的架构决策都会变得显而易见。
就像餐厅备菜:静态前缀是每天雷打不动的底汤、刀工、调料(提前备好),动态后缀是每桌客人点的菜(现点现做)。备菜做得好,上菜才快——缓存就是 AI 的"备菜间"。
KV 缓存的工作原理
要理解缓存为什么有效,得知道 Transformer 处理你的提示时到底在干什么。每个推理请求分两个阶段:
- 预填充(prefill)阶段:处理整个输入提示,对所有 token 做密集矩阵乘法,构建模型的内部表示。算力密集、贵。
- 解码(decode)阶段:一次生成一个 token,主要读历史状态。内存密集。
预填充时,Transformer 给每个 token 算三个向量:查询(Query)、键(Key)、值(Value)。关键性质:某个 token 的 Key 和 Value 只取决于它前面的 token,算完就不再变。
没有缓存时,这些键值张量每次请求后就被扔掉,下次从头再算。KV 缓存把它们持久化到推理服务器,以"token 序列的加密哈希"为索引;新请求前缀哈希命中,就从内存加载,完全跳过这些 token 的预填充计算。效果:每个生成 token 的计算复杂度从 O(n²) 降到 O(n)——对 2 万 token 前缀 × 50 轮,这是巨大的节省。
K/V 向量就像每道菜的"半成品":备好后不会变质(只取决于前面的 token),下次客人点同样的菜,直接从备菜间取,不用重新切配。哈希就是备菜盒上的标签,标签对上才能取。
经济学:定价结构决定一切
正是定价结构,让缓存从"可选项"变成"必修课"(Anthropic Claude 系列定价):
- 缓存读 = 基础输入价 × 0.1(每个缓存 token 享 90% 折扣);
- 缓存写 = 基础输入价 × 1.25(存 KV 张量付 25% 溢价);
- 延长 1 小时 = 基础输入价 × 2.0。
这笔账只有在缓存命中率够高时才划算——写一次 1.25×,读很多次 0.1×,命中率越高越赚。Claude Code 就是生产环境里的最佳范例。
实战:Claude Code 的 30 分钟编程课
Claude Code 的构建目标只有一个:保持缓存热度。看一次真实的 30 分钟会话,从计费角度长什么样:
- 第 0 分钟:加载系统提示 + 工具定义 + 项目 CLAUDE.md,超 2 万 token,全是新 token——这是整个会话最贵的一刻,但只付一次。
- 第 1–5 分钟:Explore 子智能体翻代码、跑 grep,结果追加到动态后缀;2 万 token 静态前缀按 $0.30/MTok(原价 $3.00)从缓存读。
- 第 6–15 分钟:Plan 子智能体收到的是摘要简报而非原始输出——传原始输出会无谓撑大动态后缀;出计划、你批准、开始改代码;命中率爬过 90%,每次命中重置 TTL,缓存持续保温。
- 第 16–25 分钟:你提修改,工具调用和终端输出堆积在动态后缀;会话已处理几十万 token,但 2 万 token 的地基每轮都走缓存。
- 第 28 分钟:运行 /cost——无缓存:200 万 token 按 Sonnet 4.5 费率要 $6.00;有缓存:92% 命中率,184 万 token 走缓存读,实付 $1.15,直降 81%。
哈希缓存的脆弱性:三条铁律
关于提示缓存,最反直觉的一句话:"1 + 2 = 3"能命中,"2 + 1"就是未命中。
基础设施对从头开始的完整 token 序列做哈希。序列里任何东西变了——哪怕只是两个元素的顺序——哈希就变,整个前缀按全价重算。这不是实现细节,而是 Claude Code 所有工程决策围绕的核心约束。生产环境真实踩过的坑:
- 系统提示里注入了时间戳 → 每次请求哈希都唯一;
- JSON 序列化在不同请求间排序不一致 → 工具 schema 哈希变了;
- 会话中途更新了 AgentTool 参数 → 2 万 token 缓存整体作废。
由此得出三条铁律:
- 会话中不增删工具——工具定义是缓存前缀的一部分,动它等于推倒地基;
- 不中途换模型——缓存是模型专属的,换更便宜的模型也要从零重建缓存;
- 不用改前缀来更新状态——Claude Code 的做法是把提醒追加到下一条用户消息,前缀保持不动。
缓存是"前缀匹配":中间插一个 token,后面全作废。所以时间戳、随机数、会话 ID 这类动态值,永远不要塞进系统提示或工具定义里。
落地:提示结构顺序、压缩与监控
无论用 Claude Code 还是自研智能体,提示都按这个顺序组织:
- 系统指令与行为规则置顶,会话中不变;
- 工具定义一次加载齐,不增不减;
- 检索到的上下文与参考文档放中间,会话内保持稳定;
- 对话历史与工具输出垫底——这是你的动态后缀。
开了自动缓存,缓存断点会随对话增长自动前移。不开的话就得手动跟踪 token 边界,边界错一位就彻底错过缓存。
快触及上下文上限时,别改写历史。保留原系统提示、工具和对话历史,把压缩指令作为一条新消息追加——缓存前缀复用,只为压缩指令本身那几个 token 付费。(跨会话的"记忆"则是另一套打法:用每日日志沉淀,详见《第 7 课》。)
最后,验证缓存是否真在工作:盯 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)
像盯 uptime 一样盯这个效率值。原文收束:提示缓存不是你打开的功能,而是你围绕它设计的架构纪律——静态在上、动态在下;不注时间戳、不乱序工具定义、不中途换模型、不动缓存断点上游的一切。Claude Code 用 92% 命中率、81% 降本证明了这套纪律的价值;做智能体不围绕缓存设计,等于把利润留在桌上。
整套纪律像图书馆管理:畅销书(静态前缀)永远放在进门第一排(置顶),借阅记录(动态后缀)每天更新放后排;书的编号(哈希)绝不能乱改,改了全馆的索引就对不上了。
术语翻卡:点卡片看解释
自测一下:点问题展开参考答案
每轮都把整个对话历史发回重算:2 万 token 系统提示 × 50 轮 = 100 万 token 冗余计算,按全价计费且每个用户、每个会话都在累积。
某 token 的 Key/Value 向量只取决于它前面的 token,算完不变;缓存把这些张量以 token 序列哈希为索引存下来,命中就从内存加载,单 token 复杂度从 O(n²) 降到 O(n)。
缓存读 0.1×(90% 折扣)、缓存写 1.25×(25% 溢价)、延长 1 小时 2.0×。命中率够高才划算。
哈希对完整 token 序列计算,任一改动(包括顺序)都导致全价重算。铁律:会话中不增删工具、不中途换模型、不用改前缀来更新状态(提醒追加到下一条用户消息)。
无缓存 $6.00,有缓存 92% 命中率实付 $1.15,省 81%。值得学:Plan 子智能体只收摘要简报而非原始输出,避免动态后缀无谓膨胀。