大模型 API 缓存命中率深度解析:OpenAI / DeepSeek / Anthropic 三家机制对比与智能体端实践 (学习笔记)

引言:缓存命中率为什么值得花心思

在大模型应用的账单里,input token 往往占总成本的绝对大头,而长上下文应用(RAG、Agent、多轮对话)中,大部分 input token 是重复发送的------同一个 system prompt、同一批工具定义、同一段历史消息,每一轮都要重新传给服务端。

Prompt Caching 就是针对这个场景的优化:服务端按前缀缓存计算结果,命中后只按约 1/10 的价格计费,同时显著降低首 token 延迟(TTFT)。

但缓存不是"全有或全无"的。它的设计牵扯到请求的渲染顺序、工具的稳定性、厂商对"智能体应该如何工作"的假设。这篇文章分两部分:

  • API 厂商端:三家主流厂商的服务器端缓存机制对比
  • 智能体端:作为客户端/智能体框架,如何设计才能最大化命中率

第一部分:API 厂商端(服务器端缓存机制)

0. 一切缓存设计的核心不变量:前缀匹配

几乎所有主流厂商的 prompt cache 都是前缀匹配(prefix match) :缓存键由渲染后的提示词前缀的实际字节哈希决定,前缀中任何一个字节发生变化,其后所有内容全部失效

这个不变量是理解后面所有机制的基础。谁能让自己的稳定内容尽可能靠前、让易变内容尽可能靠后,谁就能最大化命中率。

1. OpenAI:显式的缓存路由与控制

OpenAI 的缓存设计基本结构:

复制代码

[固定系统指令][工具定义][历史消息][最新用户消息]

其服务器端机制分三步:

  • Cache Routing(缓存路由) :请求根据提示语前缀的哈希值被分配到对应机器。哈希通常由前 256 个字符生成(具体长度因模型而异)。这一步决定了请求落在哪台机器上------前缀哈希不同,就路由到不同机器,前一个请求写入的缓存别人读不到。
  • Cache Lookup(缓存查询):系统检查提示语开头是否命中该机器的缓存。
  • Cache Hit / Cache Miss:命中则按缓存费率计费并直接返回;未命中则全量处理,并在启用自动缓存时把前缀写入该机器供后续使用。

OpenAI 给客户端提供了三个控制参数:

参数 作用 类比
prompt_cache_key 指定缓存 key,让相似请求进入同一缓存分组 仓库编号
prompt_cache_options 决定自动/手动缓存,以及缓存时长 ttl 仓库管理规则
prompt_cache_breakpoint 指明缓存到哪个位置截止,后续不缓存 在货物上画截止线

示例(prompt_cache_breakpoint 的 explicit 模式):

复制代码

{

"model": "gpt-5.6",

"prompt_cache_key": "customer-service-v1",

"prompt_cache_options": { "mode": "explicit", "ttl": "30m" },

"messages": [

{

"role": "system",

"content": [

{

"type": "text",

"text": "这里是很长的客服规则......",

"prompt_cache_breakpoint": { "mode": "explicit" }

}

]

},

{ "role": "user", "content": "我的订单什么时候发货?" }

]

}

OpenAI 的已知问题 :工具定义排在缓存的第二位,只要工具发生变动,变动之后的缓存命中立即失效

2. DeepSeek:结构相似,问题相同

DeepSeek 的缓存结构:

复制代码

<BOS>[system prompt][tool descriptions / tool definitions][user1][assistant1][tool call / tool result][user2][assistant2]...[最新 user][assistant generation prefix]

与 OpenAI 大致相同:system prompt 在前,工具描述紧随其后,之后是交替的对话历史。因此缓存失效的问题也一样------工具定义一变,后续全部失效。

3. Anthropic:不同的渲染顺序与三段缓存层级

Anthropic 的渲染顺序是三家中最特殊的:

复制代码

tools(位置 0)→ system → messages

工具在位置 0 渲染,system 其次,messages 最后。这意味着:

  • tools 任何变动都会破坏整个缓存(包括 system 和 messages 的缓存)------所以 tools 必须高度稳定;
  • system 可以分段缓存,动态信息应放到末尾的 breakpoint 之后;
  • messages 本身就在不断变化,其命中靠的是"每轮只 append 新消息,历史前缀不变"。

为什么 Anapthropic 敢把最容易变动的 tools 放在最前面?这背后是它对智能体的设计哲学(后面详述)。

更细的机制层面,Anthropic 的缓存有三层独立层级,变化只破坏自己层级及以下的缓存:

变化 tools 缓存 system 缓存 messages 缓存
增删改工具定义
切换模型
修改 system prompt 内容
修改 tool_choice 或开关 thinking
修改 messages 内容

几个容易踩坑的工程细节:

  • 最小可缓存前缀 :不同模型要求不同,低于阈值即使打了标记也静默不缓存(Opus 5 是 512 tokens,Opus 4.6/Haiku 4.5 是 4096 tokens)。
  • 20-block 回看窗口:每个 breakpoint 最多向前回看 20 个 content block。Agent 循环中工具调用密集时,一轮可能新增超过 20 个 block,下一轮就找不到上一轮缓存。解法是每 15 个 block 左右放一个中间 breakpoint。
  • 并发请求时序:缓存条目在第一个响应开始流式输出后才可读。N 个前缀相同的并发请求都会 miss------先发一个请求等首 token,再发剩下的 N-1 个,就能全部命中。

Anthropic 的逃逸口(这两个机制恰好回答了"工具变了怎么办"):

  • mid-conversation system message :在 messages[] 里追加 {"role": "system", ...},代替修改顶层 system,不破坏缓存前缀;
  • mid-conversation tool changes (beta):在 messages[] 中以 tool_addition / tool_removal block 增删工具,工具声明时用 defer_loading: true 占位。

4. 三家对比与 Anthropic 的设计哲学

维度 OpenAI DeepSeek Anthropic
渲染顺序 system → tools → messages system → tools → messages tools → system → messages
缓存控制 prompt_cache_key + breakpoint + ttl 自动缓存为主 cache_control breakpoint
工具变动的代价 工具后全部失效 工具后全部失效 整个缓存全部失效

Anthropic 把 tools 放在位置 0,是一个带着强烈立场的设计------里面藏着它对"智能体应该怎样工作"的三条判断:

  1. 工具是能力边界,不是临时道具。 Agent 的工具集是身份的一部分(你是谁、能干什么),不是会话的装饰品。频繁换工具意味着身份在漂移,在模型的设计里这是异常行为。
  2. System Prompt 是约束,Messages 是事实。 System 说"你应该做 A",但 messages 中工具跑出来的结果是"实际发生了 B"。模型在矛盾时相信实际发生的事实。所以动态信息放 messages 是合理的------模型会自己判断优先级。
  3. 智能体的主流使用模式是长周期、少变动。 这个缓存设计假设你构建一个 agent → 运行几百万次 → 偶尔调整能力。它对"脚手架一次性搭好就跑"的模式做了极致优化,而对"每轮动态增减工具"的模式,回答是"去用逃逸口"。

第二部分:智能体端(客户端缓存机制)

看完厂商端,回到我们自己要写的智能体框架。客户端优化的核心就一句话:

1. 最初的认识:system 固化、messages 只追加

复制代码

system prompt:保持不动(字节级)

user message :只向后追加

原则是:旧的历史消息完全固化,所有新东西(新提问、工具结果)只追加到末尾。这样每次请求的整个前缀(system + 全部历史)都保持一致,服务端每轮都能命中缓存,成本曲线几乎是平的而不是线性增长。

顺带一提,思考链(thinking)等过程性垃圾数据也不要拼进历史,它们会无谓地增加前缀长度、拉低缓存性价比。

2. 难题:工具更新、记忆更新后如何让模型感知?

把 system 完全固化之后,一个自然的问题浮现出来:

更新了记忆、更新了工具之后,怎么把"实时变化"传递给大模型,让它随时知道?

直观想法:在下一轮 user message 里更新说明,或者做记忆重新加载、工具说明重新加载。这样现有历史 message 完全不变,缓存命中率有保障,同时模型能在最新一轮看到变化。

但这个想法部分可行,部分不可行

  • 记忆更新------可行:记忆本质是文本信息,追加成一条 user message 让模型看到,代价只是占一点上下文空间(注意旧版本记忆会残留在历史里,可能造成新旧矛盾,最好在压缩时处理)。
  • 工具变动------不可行 :参考 OpenAI 的缓存设计,tools 是 API 调用层的独立参数 ,与 systemmessages 平级。即使你在 user message 里写"现在有个新工具叫 X",模型也无法生成合法的 tool_use 调用------因为 tools 参数里没有对应 schema。反过来,tools 里定义了的工具,消息里说"已废弃",模型照样可能去调用。工具变更绕不开 tools 参数,而这正是破坏缓存的真正元凶。

3. 工程实践:稳定段 + 动态段

所以纯靠"messages 只追加"并不能解决全部问题。兼顾缓存与动态性的工程做法是把 system prompt 分段

复制代码

system = 稳定段(身份、核心约束、规则) ← 几乎不变,缓存完美命中

+

动态段(记忆索引、技能描述、workspace 指令) ← 变化时才变

  • 稳定段放在前面、几乎不动,保证缓存前缀稳定;
  • 动态段放在末尾 breakpoint 之后,变化只影响缓存的后半部分,不破坏稳定段;
  • 再加一层:把记忆、工具执行的结果通过 tool_result 自然写进 messages------这是天然的动态通道,不需要额外设计监控机制。

工具描述想要字节级固化 ,关键是三点:工具列表顺序固定(按名称排序)、schema 序列化确定(sort_keys=True)、以及尽量少动------把工具当成身份而不是临时道具。

4. 工具变动情况

目前工具变动的情况没有更好的方法,主流的智能体当前都会破坏掉高缓存,所以尽量不要变动工具。

总结

缓存命中率不是客户端单方面能决定的,它反映的是厂商的设计哲学与客户端的工程策略如何对齐:

  • 厂商端:前缀匹配是铁律,三家在 tools 的位置上分道扬镳------Anthropic 选择"工具即身份"的激进设计,换来跨请求、跨会话的最大前缀复用,同时用逃逸口兜底。
  • 客户端:核心是"稳定内容固化、动态内容后置"------system 分段、messages 只追加、变化尽量走消息通道而非顶层参数。

最后给一个实用 checklist:

  1. system prompt 冻结,动态信息放 breakpoint 之后;
  2. tools 定义一次,排序稳定,序列化确定;
  3. messages 只 append,永不修改历史;
  4. 工具/记忆变化优先走 tool_result 或 mid-conversation 通道;
  5. 高频 fan-out 场景先发 1 个请求预热缓存再并发;
  6. usage.cache_read_input_tokens 验证,如果长期为 0,检查是否有静默失效源(时间戳、乱序 JSON、动态工具集)。

如果你也想弄懂 Claude Code 这类 Coding Agent 到底是怎么工作的,这个仓库也许能帮你少走一些弯路。目前我的github的项目(OpenAI SDK 版),我学习的课程为learn-claude-code的v2版本课程(感谢原作者),大家一起学习,共同进步。如果对你有帮助,请为我点一个Star。

项目地址:https://github.com/peijiping/learn-claude-code-langchain

相关推荐
jufeng13071 小时前
【系列:手搓自主 AI Agent:Hermes 架构原理剖析 · 第 8 篇】
python·ai agent·配置系统
ArkAPI2 小时前
Claude Code 连发安全修复:AI 编程 Agent 的权限,正在成为新的“安全事故高发区”
人工智能·大模型·api·codex·ai工具·claude code·arkapi
花千树-0107 小时前
Harness Marketplace 剖析系列 - 之 Codex:Plugin、Marketplace 与通用插件目录
codex·ai agent·skill·mcp·marketplace·ai plugin开发·智能体生态
NutShell Wang10 小时前
「音画同生」时代开启:2026 年 8 月 AI 视频生成四大发布复盘
人工智能·开源·aigc·ai agent·智能体·vibe coding
鱼日先生10 小时前
Dify 企业级实验(04):性能优化实战——长流程从 60 秒到秒回有哪些手段?
人工智能·工作流·dify·ai agent·大模型应用·ai 训练
新知图书12 小时前
1.1 从大语言模型到智能体:范式演进
人工智能·ai agent·智能体·智能体工程
朴实赋能12 小时前
AI Agent + NFC + 同地标拼购:本地生活实体店的“数字获客“技术解法与MVP验证思路
人工智能·生活·ai agent·实体店获客·实体店数字化·ai 获客·nfc 获客
TonyLee01713 小时前
Claude Code + DeepSeek:服务器安装与使用笔记
linux·服务器·deepseek·claude code
北漂燕郊杨哥13 小时前
Agent 时代的「安卓时刻」:DeepSeek 开源 Harness 背后的战略棋局
开源·ai agent·deepseek·deepseekharness