什么是大模型缓存?
你每次跟 AI 对话,都要把整段对话历史发给大模型。模型需要”读完”所有内容才能回复你。
问题来了:读一遍很贵。
大模型按 token(大约 0.75 个中文字 = 1 token)收费,”读”(输入)和”写”(输出)分别计价。一段 10000 token 的对话,每次你发新消息,模型都要重新读这 10000 token —— 即使前 9900 token 跟上次完全一样。
缓存就是让模型记住已经读过的部分,下次不用重新读。
用生活比喻理解
想象你请了一个翻译,每次开会前都要把之前所有会议纪要重新念一遍给他听,他才能理解上下文。
- 没有缓存:每次开会,翻译重新念全部纪要(收全价)
- 有缓存:翻译说”上次的我都记着呢,只念新增的部分就行”(旧内容打折)
缓存怎么省钱?
以 Anthropic Claude 为例:
| 场景 | 输入价格 | 节省 |
|---|---|---|
| 正常读取 | $3 / 百万 token | — |
| 首次写入缓存 | $3.75 / 百万 token | 多花 25%(一次性成本) |
| 命中缓存 | $0.30 / 百万 token | 省 90% |
也就是说:
- 第一次对话稍微贵一点(要”存”进缓存)
- 之后每次对话,重复的部分只收 1⁄10 的价格
如果你的 system prompt(系统提示词)有 5000 token,每次对话都要发送它。一天 100 次对话:
- 不缓存:5000 × 100 = 50万 token 全价
- 有缓存:5000 × 1(全价写入)+ 5000 × 99(1折读取)= 约等于 15万 token 的钱
省了 70%。
缓存的工作原理
@startuml
!theme plain
skinparam backgroundColor #FEFEFE
participant "你" as U
participant "API" as A
participant "大模型" as M
participant "缓存" as C
== 第一次请求 ==
U -> A : 发送消息\n(system prompt + 对话历史)
A -> C : 计算前缀 hash
C --> A : 未命中
A -> M : 完整处理所有 token
M --> A : 回复
A -> C : 存入缓存(前缀部分)
A --> U : 返回回复\n(cache_creation_input_tokens: 5000)
== 第二次请求 ==
U -> A : 发送消息\n(同样的 system prompt + 更新的历史)
A -> C : 计算前缀 hash
C --> A : ✅ 命中!
A -> M : 只处理新增 token\n(缓存部分跳过计算)
M --> A : 回复
A --> U : 返回回复\n(cache_read_input_tokens: 5000)
@enduml
关键点:
- 缓存匹配的是前缀(从头开始连续相同的部分)
- 只要前面的内容不变,后面新增的内容不影响缓存命中
- 缓存有有效期(通常 5 分钟不使用就过期)
如何提高缓存命中率?
1. 把不变的内容放在最前面
消息顺序很重要。缓存只匹配从头开始连续相同的部分。
✅ 好的顺序:
[System Prompt] ← 不变,会被缓存
[长篇参考资料] ← 不变,会被缓存
[对话历史] ← 大部分不变
[用户最新消息] ← 新内容
❌ 差的顺序:
[时间戳: 2024-01-01 12:34:56] ← 每次都变!
[System Prompt] ← 因为前面变了,这里也无法命中
[对话历史] ← 全部无法命中
一个变化的字符在开头,就会导致整个缓存失效。
2. System Prompt 保持稳定
不要在 system prompt 里放:
- 当前时间(每秒都变)
- 随机数
- 每次请求都不同的用户信息
这些应该放在用户消息里,而不是 system prompt 里。
3. 参考资料放在 system prompt 后面、对话前面
如果你要让模型参考一篇长文档:
[System Prompt] ← 缓存 ✅
[参考文档全文] ← 缓存 ✅(只要不换文档)
[对话历史...] ← 部分缓存
[新消息] ← 不缓存(新内容)
4. 保持对话连续性
频繁开新对话 = 频繁创建新缓存 = 多花 25% 的写入成本。
在同一个对话里持续聊天,缓存命中率最高。
5. 达到最小缓存长度
不同模型有最小缓存要求:
- Anthropic Claude:1024 token(约 750 个中文字)
- OpenAI GPT:1024 token
太短的内容不会被缓存。所以简短的 system prompt 可能享受不到缓存优惠。
不同厂商的缓存策略
| 厂商 | 缓存方式 | 有效期 | 最小长度 |
|---|---|---|---|
| Anthropic (Claude) | 显式标记缓存断点 | 5 分钟 | 1024 token |
| OpenAI (GPT) | 自动缓存(无需标记) | ~5-10 分钟 | 1024 token |
| Google (Gemini) | 显式创建缓存对象 | 可自定义 | 较长 |
Anthropic 需要你在 API 请求中标记 cache_control,告诉它”到这里为止可以缓存”。
OpenAI 则是全自动的,不需要任何标记,系统自动判断哪些前缀可以缓存。
怎么知道缓存有没有生效?
API 返回的 usage 字段会告诉你:
{
"usage": {
"input_tokens": 200,
"cache_creation_input_tokens": 5000,
"cache_read_input_tokens": 0
}
}
cache_creation_input_tokens:首次写入缓存的 token 数(多花 25%)cache_read_input_tokens:命中缓存的 token 数(省 90%)input_tokens:没有被缓存的 token 数(全价)
理想状态:cache_read_input_tokens 占比越高越好。
总结
| 要点 | 说明 |
|---|---|
| 缓存是什么 | 让模型记住已读过的内容,不重复计费 |
| 省多少 | 命中缓存部分省 90% 输入费用 |
| 怎么提高命中 | 不变的内容放最前面,避免开头插入变化内容 |
| 最容易的优化 | 保持 system prompt 稳定 + 不频繁开新对话 |
| 最常见的坑 | 在 prompt 开头放时间戳,导致整个缓存失效 |
缓存不需要你做很多事情 —— 很多平台已经自动处理了。但理解它的原理,能帮你避免”明明用了缓存但一直没命中”的情况。