微信扫码
添加专属顾问
揭秘Prompt Caching技术:如何让大模型推理速度提升6倍、成本降低90%? 核心内容: 1. Prompt Caching技术原理与工作流程 2. 性能对比:处理速度提升6倍,成本降低90% 3. 适用场景与具体使用方法
通过提示词缓存技术让大模型推理速度提升 n 倍、成本降低 xx%
今天学习了一下大模型的提示词缓存功能,读文档时更多的是在教学它的优势、使用方法、使用场景,
但没有告知技术原理,于是找大模型尝试了解了一下,然后干脆让大模型帮我写了一篇技术文档。
以下是大模型生成:
假设你有一本 10 万字的小说,需要基于这本书回答两个问题:
场景:
系统提示词: "以下是《傲慢与偏见》的完整内容:[10万字小说文本]"
第一次问答:
# 问题 1
User: "这本书的主题是什么?"
# API 处理
- 将 10 万字小说 + 问题分解为 100,020 个 tokens
- 逐层计算所有 tokens(40 层 Transformer)
- 创建缓存(保存计算结果)
- 返回答案
耗时: 2.5 秒
成本: $0.375第二次问答:
# 问题 2
User: "主要角色有哪些?"
# API 处理
- 发现系统提示词(10万字小说)与之前相同
- ✓ 从缓存直接加载已计算的结果(100,000 tokens)
- ✗ 仅计算新问题的部分(20 tokens)
- 返回答案
耗时: 0.4 秒(快了 6 倍!)
成本: $0.03(便宜了 90%!)Prompt Caching(提示词缓存) 是一种优化技术:
核心流程:
第一次请求: [长文本] + [问题1]
↓
完整计算所有 tokens
↓
保存计算结果到缓存 ← 创建缓存
↓
返回答案1
第二次请求: [长文本] + [问题2]
↓
检测到 [长文本] 部分相同 ← 前缀匹配
↓
✓ 加载 [长文本] 的缓存结果
✗ 仅计算 [问题2] 部分
↓
合并结果,返回答案2基于上述示例(10 万字小说 + 2 次问答):
| 处理的 tokens | ||
| 耗时 | ||
| 成本 |
Claude API 定价(Sonnet 4.5):
第一次问答(创建缓存):
Input (创建缓存): 100,020 tokens × $3.75/1M = $0.375
Output: 50 tokens × $15/1M = $0.00075
总计: $0.375第二次问答(读取缓存):
Input (读取缓存): 100,000 tokens × $0.30/1M = $0.030
Input (常规): 20 tokens × $3.00/1M = $0.00006
Output: 50 tokens × $15/1M = $0.00075
总计: $0.031节省分析:
如果没有缓存,两次问答总成本:
2 × (100,020 × $3/1M) = $0.60
使用缓存,两次问答总成本:
$0.375 + $0.031 = $0.406
节省: ($0.60 - $0.406) / $0.60 = 32%
如果是 10 次问答:
不使用缓存: 10 × $0.30 = $3.00
使用缓存: $0.375 + 9 × $0.03 = $0.645
节省: 78%在理解缓存原理之前,我们需要了解大模型是如何处理文本的。
输入文本: "这本书的主题是什么?"
↓
[1] Tokenization(分词)
将文本切分为 tokens
↓
[2] Embedding(嵌入)
每个 token 转换为高维向量(如 4096 维)
↓
[3] Transformer 层(重复 40+ 层)
│
├─ 自注意力机制(Attention)
│ ├─ 计算 Query (Q):当前关注什么
│ ├─ 计算 Key (K):提供什么信息 ← 缓存这个!
│ ├─ 计算 Value (V):具体内容是什么 ← 缓存这个!
│ └─ Attention 计算: Q 与 K/V 交互
│
└─ 前馈网络(FFN)
↓
[4] 输出层
生成下一个 token
↓
返回文本: "这本书的主题是爱情与社会阶级..."将文本切分为模型的最小处理单位 - Token:
# 示例
文本: "这本书的主题是什么?"
↓
Tokens: ["这", "本", "书", "的", "主题", "是", "什么", "?"]
↓
Token IDs: [1234, 5678, 9012, 3456, 7890, 2345, 6789, 0123]关键点:
在我们的示例中:
这是大模型最关键、最耗时的部分。
简化理解:
假设要理解"这本书的主题是什么?"这句话中"主题"这个词:
步骤 1: 为每个词计算三个向量
- Query (Q):我(主题)想查询什么信息?
- Key (K):其他词能提供什么信息?
- Value (V):其他词的具体内容是什么?
步骤 2: 计算相关性
用"主题"的 Q 与所有词的 K 计算相似度:
- "这" 的相关性:0.1
- "本" 的相关性:0.2
- "书" 的相关性:0.8 ← 高相关
- "的" 的相关性:0.1
- "主题" 的相关性:0.5
- "是" 的相关性:0.1
- "什么" 的相关性:0.3
步骤 3: 加权求和
根据相关性,将所有词的 V 加权组合:
output_主题 = 0.1×V_这 + 0.2×V_本 + 0.8×V_书 + ... + 0.3×V_什么为什么这里最耗时?
在我们的示例中(100,020 个 tokens):
单层 Transformer 需要计算:
- 100,020 个 Q 向量
- 100,020 个 K 向量 ← 这个可以缓存!
- 100,020 个 V 向量 ← 这个可以缓存!
- 100,020 × 100,020 的注意力矩阵(100 亿次计算!)
模型有 40 层:
- 总计算量 = 40 层 × 100,020 tokens = 4,000,800 次 K/V 计算
- 这就是为什么处理 10 万 tokens 需要 2-3 秒答案:缓存的是每一层 Transformer 中所有 tokens 的 Key (K) 和 Value (V) 向量。
不是缓存:
而是缓存:
以我们的示例为例(100,000 tokens 的小说):
# 缓存的完整结构
cache = {
"id": "cache_abc123",
"created_at": 1704902400,
"ttl": 300, # 5 分钟有效期
# Token 序列(用于匹配)
"tokens": [1234, 5678, 9012, ...], # 100,000 个 token IDs
# 每一层的 KV Cache
"layers": [
# Layer 0
{
"keys": [
# Token 0 的 key 向量
[k0_head0, k0_head1, ..., k0_head31], # 32 个注意力头
# Token 1 的 key 向量
[k1_head0, k1_head1, ..., k1_head31],
# ... 100,000 个 tokens
], # Shape: (100000, 32, 128)
"values": [
# 结构与 keys 相同
...
] # Shape: (100000, 32, 128)
},
# Layer 1-39 结构相同
...
]
}
# 存储大小估算(假设 float16)
每层大小 = 100,000 tokens × 32 heads × 128 dim × 2 (K+V) × 2 bytes
= 1.6 GB
40 层总大小 = 1.6 GB × 40 = 64 GB第一次请求(创建缓存):
# 处理 100,020 个 tokens(小说 + 问题1)
for layer in range(40): # 40 层
for token in all_100020_tokens: # 每个 token
# 1. 计算 K 和 V(耗时!)
k = W_k @ embedding(token) # 矩阵乘法
v = W_v @ embedding(token) # 矩阵乘法
# 2. 保存到缓存
cache.layers[layer].keys.append(k)
cache.layers[layer].values.append(v)
总计算量: 40 层 × 100,020 tokens × 2 (K和V) = 8,001,600 次计算
耗时: ~2.5 秒第二次请求(使用缓存):
# 检测到前 100,000 tokens(小说)相同
# 仅需处理新增的 20 tokens(问题2)
for layer in range(40):
# 1. 从缓存加载小说部分的 K/V(快速内存读取!)
cached_K = cache.layers[layer].keys # 100,000 个
cached_V = cache.layers[layer].values
# 2. 仅计算新问题的 K/V(仅 20 个 tokens)
new_K = []
new_V = []
for token in new_20_tokens:
k = W_k @ embedding(token)
v = W_v @ embedding(token)
new_K.append(k)
new_V.append(v)
# 3. 拼接
full_K = concat(cached_K, new_K) # (100020, 32, 128)
full_V = concat(cached_V, new_V)
# 4. 使用拼接后的 K/V 进行 Attention 计算
output = attention(Q, full_K, full_V)
总计算量: 40 层 × 20 tokens × 2 = 1,600 次计算
加速比: 8,001,600 / 1,600 = 5000 倍(仅 K/V 计算部分)
实际加速: ~6 倍(因为还有 Attention 计算等其他步骤)数学保证:
自注意力的计算公式:
Attention(Q, K, V) = softmax(Q · K^T / √d) · V
这个计算只依赖 K 和 V 的数值,不关心它们来自哪里:
# 场景 1:不使用缓存(全部计算)
K_all = compute_K([小说tokens] + [问题tokens])
V_all = compute_V([小说tokens] + [问题tokens])
result_1 = attention(Q, K_all, V_all)
# 场景 2:使用缓存(拼接)
K_cached = load_from_cache() # 小说部分
K_new = compute_K([问题tokens])
K_all = concat(K_cached, K_new) # 数值完全相同
V_cached = load_from_cache()
V_new = compute_V([问题tokens])
V_all = concat(V_cached, V_new)
result_2 = attention(Q, K_all, V_all)
# 验证
assert result_1 == result_2 # 完全相同!只要 K/V 矩阵的数值相同,无论是实时计算还是从缓存加载,最终结果都完全一致。
缓存通过精确的 token 序列前缀匹配来判断是否可以复用。
核心算法:
def find_cache_match(current_tokens, cache_db):
"""
查找与当前请求匹配的最长前缀缓存
"""
best_match = None
max_length = 0
for cache in cache_db:
# 逐个比较 token
match_length = 0
for i in range(min(len(current_tokens), len(cache.tokens))):
if current_tokens[i] == cache.tokens[i]:
match_length += 1
else:
break # 遇到不同就停止
# 必须 >= 1024 tokens 才能缓存
if match_length >= 1024 and match_length > max_length:
max_length = match_length
best_match = cache
return best_match, max_length第一次问答(创建缓存):
发送到 API:
System: [小说 100,000 tokens] + cache_control
User: [问题1 20 tokens] + cache_control
Token 序列:
[t1, t2, t3, ..., t100000, t100001, ..., t100020]
└──────── 小说 ────────┘ └──── 问题1 ────┘
创建缓存:
Cache_1.tokens = [t1, t2, ..., t100020]
Cache_1.layers[0-39] = 所有 tokens 的 K/V 矩阵第二次问答(匹配缓存):
发送到 API:
System: [小说 100,000 tokens] + cache_control ← 与第一次相同
User: [问题2 20 tokens] + cache_control ← 不同的问题
Token 序列:
[t1, t2, t3, ..., t100000, t200001, ..., t200020]
└──────── 小说 ────────┘ └──── 问题2 ────┘
↑ 前 100,000 个 tokens 完全相同
匹配过程:
1. 比较 Cache_1.tokens 与当前 tokens
2. 前 100,000 个完全匹配 ✓
3. 第 100,001 个开始不同 ✗
结果:
- 匹配长度: 100,000 tokens
- 从缓存加载: 前 100,000 个 tokens 的 K/V
- 重新计算: 后 20 个 tokens (问题2)在代码中,我们用 cache_control 标记缓存点:
response = client.messages.create(
system=[{
"type": "text",
"text": book_content, # 10万字小说
"cache_control": {"type": "ephemeral"} # ← 缓存到这里
}],
messages=[{
"role": "user",
"content": [{
"type": "text",
"text": "这本书的主题是什么?",
"cache_control": {"type": "ephemeral"} # ← 可选的第二个缓存点
}]
}]
)缓存点规则:
如果只在 System 添加 cache_control:
缓存内容 = [System 全部内容]
如果同时在 System 和 User 添加:
缓存内容 = [System 全部内容] + [之前的所有 messages] + [当前 User]关键:缓存点标记的是"从开头到这里"的所有内容,不是某一段!
# ❌ 错误理解:只缓存这一段
system = [
{"type": "text", "text": "Part A"},
{"type": "text", "text": "Part B", "cache_control": {...}}, # 错误!
{"type": "text", "text": "Part C"}
]
# Part C 不会被缓存
# ✓ 正确:缓存从开头到标记点的所有内容
system = [
{"type": "text", "text": "Part A"},
{"type": "text", "text": "Part B"},
{"type": "text", "text": "Part C", "cache_control": {...}} # 正确!
]
# 缓存 Part A + Part B + Part C请求 1: [━━━━━━━ 小说 100K ━━━━━━━][问题1 20]*
创建 Cache_1: 100,020 tokens
请求 2: [━━━━━━━ 小说 100K ━━━━━━━][问题2 20]*
匹配检测:
[━━━━━━━ 小说 100K ━━━━━━━] ← 与 Cache_1 完全匹配 ✓
└─────── 从缓存加载 ──────┘
[问题2 20] ← 重新计算 ✗
结果:
- Cache Read: 100,000 tokens
- Input: 20 tokens
- 总耗时: 0.4 秒import anthropic
client = anthropic.Anthropic(api_key="your_api_key")
# 第一次请求
response_1 = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1024,
system=[{
"type": "text",
"text": book_content, # 长文本内容
"cache_control": {"type": "ephemeral"} # ← 标记缓存点
}],
messages=[{
"role": "user",
"content": "这本书的主题是什么?"
}]
)
# 查看缓存统计
print(f"Input tokens: {response_1.usage.input_tokens}")
print(f"Cache write: {response_1.usage.cache_creation_input_tokens}")
print(f"Cache read: {response_1.usage.cache_read_input_tokens}")
# 输出:
# Input tokens: 100020
# Cache write: 100020 ← 创建了缓存
# Cache read: 0 ← 第一次没有缓存可读
# 第二次请求(5分钟内)
response_2 = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1024,
system=[{
"type": "text",
"text": book_content, # 相同的长文本
"cache_control": {"type": "ephemeral"}
}],
messages=[{
"role": "user",
"content": "主要角色有哪些?" # 不同的问题
}]
)
# 查看缓存统计
print(f"Input tokens: {response_2.usage.input_tokens}")
print(f"Cache write: {response_2.usage.cache_creation_input_tokens}")
print(f"Cache read: {response_2.usage.cache_read_input_tokens}")
# 输出:
# Input tokens: 20 ← 只计算新问题
# Cache write: 100020 ← 更新缓存
# Cache read: 100000 ← 从缓存读取!ephemeral |
注意:
def analyze_cache_usage(response):
"""分析缓存使用情况"""
usage = response.usage
# 计算总输入
total_input = usage.input_tokens + getattr(usage, 'cache_read_input_tokens', 0)
# 缓存命中率
cache_hit_rate = (
getattr(usage, 'cache_read_input_tokens', 0) / total_input * 100
if total_input > 0 else 0
)
# 成本估算
cost = (
usage.input_tokens * 3.00 / 1_000_000 +
getattr(usage, 'cache_read_input_tokens', 0) * 0.30 / 1_000_000 +
getattr(usage, 'cache_creation_input_tokens', 0) * 3.75 / 1_000_000 +
usage.output_tokens * 15.00 / 1_000_000
)
print(f"总输入: {total_input:,} tokens")
print(f" ├─ 从缓存: {getattr(usage, 'cache_read_input_tokens', 0):,} ({cache_hit_rate:.1f}%)")
print(f" └─ 新计算: {usage.input_tokens:,}")
print(f"缓存写入: {getattr(usage, 'cache_creation_input_tokens', 0):,}")
print(f"估算成本: ${cost:.6f}")
# 使用
analyze_cache_usage(response_2)
# 输出:
# 总输入: 100,020 tokens
# ├─ 从缓存: 100,000 (99.9%)
# └─ 新计算: 20
# 缓存写入: 100,020
# 估算成本: $0.030081✅ 长文档问答
✅ 固定提示词的应用
✅ 批量处理
❌ 单次请求
❌ 短文本
❌ 动态内容
是否有长文本(> 1K tokens)?
├─ 否 → ❌ 不使用缓存
└─ 是 → 是否有多次请求?
├─ 否 → ❌ 不使用缓存
└─ 是 → 内容是否相对固定?
├─ 否 → ❌ 不使用缓存
└─ 是 → ✅ 使用缓存!cache_control: {type: "ephemeral"}cache_read_input_tokens 确认命中
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-07-16
WorkBuddy 的同学看到请帮忙优化几个小问题
2026-07-08
精打细算虾养成指南: 省 Token 和把 AI 用好,从来就是一件事
2026-07-07
从零开始玩转循环 (Getting started with loops)【译】
2026-07-07
用好“AI 录音转写”,效率提升 3 倍,四个场景直接抄
2026-07-02
Claude团队:别再逐条喂Prompt,学会给Agent设计循环
2026-07-02
Agent 怎么沉淀技能:把一个好 prompt 变成全队资产
2026-07-01
从 Prompt 到 Skill:专业工作流的结构升级
2026-07-01
别让 AI 写的文档误导用户:从单次 Prompt 到高可信文档工程化实践
2026-04-21
2026-04-25
2026-05-02
2026-04-20
2026-04-19
2026-05-25
2026-04-18
2026-05-23
2026-06-10
2026-05-20
2026-06-17
2026-05-23
2026-05-16
2026-04-14
2026-02-28
2026-02-12
2026-02-12
2026-02-08
欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。
在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。
一、 定义
本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。
会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。
知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。
二、 账号注册与登录
登录方式:本网站支持以下登录方式,您可根据实际情况选择:
微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。
手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。
账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。
实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。
未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。
三、 服务内容与规范
知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。
服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。
禁止行为:您在使用服务时不得实施以下行为:
利用技术手段批量爬取、下载、转存知识库内容;
将知识库内容用于商业目的或未经授权地向第三方传播;
干扰本网站正常运行或侵犯其他用户合法权益;
发布违法违规信息或从事违反公序良俗的活动。
四、 知识产权声明
权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。
有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。
侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。
五、 个人信息保护
我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。
您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。
您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。
六、 免责声明
内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。
不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。
第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。
七、 违约责任
如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。
如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。
八、 法律适用与争议解决
本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。
因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。
九、 其他
本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。
本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。
我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。