← 返回文章
Price of each turn's first call, by where the clock is written (median, multiple of the listed input price)
Cumulative cost of one 12-turn conversation on GPT-6 Luna (US cents)
Claude Opus 5.5 on OpenRouter, input price actually paid by each endpoint's cache hit rate (USD per 1M tokens)
发现
Copy article
提示缓存错误可能让您的组织在每一次 AI 交互中几乎多花 6x
破损的提示缓存对构建工具、运行内部 AI 平台或交付 AI 产品的组织造成的成本,以 4 labs 的模型衡量,并按实时流量定价,修复方法及如何持续监控它。
Developed by Robert E. Beckner III (Merlin) | rbeckner.com
多年前我开始想为什么 AI 从不似乎能很好地知道日期和时间。 询问对话它是哪一天可能需要几秒钟,我期望得到即时答案。 运行对话的计算机知道现在是什么时间。
我后来明白了其中一部分原因。 人们可以第二天回到对话,开始时给出的时间已变得过时。 必须再次提供它。 一个 harness,即围绕模型的程序,组装每个请求并运行循环,可以通过在每个请求前将当前时间写入模型指令来做到这一点。 我们在生产中使用的 agent runner 正是这样做的。
我早就知道提示缓存。 供应商存储请求的开始并在下一个请求以相同方式开始时按价格的一部分计费。 我并不了解其机制,无法看到像时间这样的行对其产生的影响。 我们在自己的生产成本中偶然发现了答案,我指挥了一系列实验来正确测量它,跨越每个实验室的一个当前模型,共4个实验室,并与OpenRouter的公开数据对比,看看其他人支付了多少。
答案很昂贵。 在 GPT-6 Luna 上,错误位置写入的时间使每一次对话的成本增加了 5.7×,且没有触发错误。 在交通组织之间发送这些模型时,输入是 96–99% 个令牌和 66–87% 美元实际支付的金额,因此缓存决定了大部分账单。 对于构建自己工具链、运行内部 AI 平台或交付 AI 产品的组织来说,这样的错误会在其运行期间悄悄地将每一次交互的成本乘以多倍。
这里的每个每回合数字均在 2026 年 9 月 23 日测量,直到 OpenRouter。 市场数据是 OpenRouter 自己的,同一天读取。
提示缓存存储请求的开始,并按十分之一计费
每次调用模型时都会再次发送整个对话:工具定义、系统提示(harness 编写的固定指令)、之前的每一次回合以及新的消息。
提供商保留最近请求的已处理开头。 当下一个请求以相同文本开始时,提供商读取已存储的前缀,而不是再次处理它。 在 GPT-6 Luna 上,OpenRouter 对读取计费为列出输入价格的 0.10×,第一次写入计费为 1.25×。 每次回合都重新写入的提示因此比完全没有缓存的提示更昂贵。
只有请求的开始可以被重用。 在任何位置的更改都会使其后的所有内容失效:
Diagram source
graph LR
A[工具定义] --> B[系统提示]
B --> C[之前的回合]
C --> D[新的用户消息]
B -. a changed line here voids B, C and D .-> D任何在开始附近写入并在每个回合更改的内容都会使整个对话处于风险之中。 当前时间是最简单的例子。
我们在自己的账单中发现了它,被我们自己的成本账本隐藏
这一发现始于我们在生产环境中运行的一个代理。 它的成本账本按标价计价每一次调用,并且根本没有显示缓存。 我发出了警报并开始考虑切换到不同的模型。
我正在合作的代理首先发现账本本身是错误的。 在 33 次调用中,它估计为 $0.064;提供商计费为 $0.023,比之少 2.7×. 根据令牌计数为每次调用定价,已抹去了提供商所应用的所有折扣。 读取提供商报告的成本则显示缓存在每一轮内部工作,但在每个新轮开始时失败。
它的第一个解释是缺少会话键,导致请求保持在同一服务器上。 它自己的探测驳斥了这一点:相同的提示已在 GPT-6 Luna 的轮次间从缓存读取,添加会话键、缓存键或显式缓存标记都没有改变任何东西。 原因在于系统提示本身。 进入约 95% 的时候,运行器写了两行在每轮都变化的内容:一个每轮工作目录和一个到分钟的时钟。 每轮的第一次调用在 1.25× 处再次写入整个提示。
将这两行移动到用户消息的末尾在生产环境中修复了它。 轮次 2 和 3 现在以 0.47–0.51× 开启,而不是 1.25×. 剩余部分是运行器仍在用户消息中发送的每轮上下文块。
时间的流逝决定了提示是被读取还是被重写
在测量之前,我的猜测是,确定性检查只能在时间过期时提供时间,作为单独的消息,并将提示的其余部分保留在缓存中。 它成立,前提是一个条件,而这个条件是文章其余部分所依据的规则。
为了直接测试,我们构建了一个探针,在不同时间点运行相同的对话,间隔 65 秒,使每一对之间分钟数发生变化。 GPT-6 Luna,一个 8.5K-令牌的系统提示,3 复制:
| 时钟所在位置 | 开启时间 | 从缓存读取 | 重写 | 价格与列出的输入 |
|---|---|---|---|---|
| 无时钟(对照) | 12 | 12 | 0 | 0.10× |
| 系统提示结束 | 12 | 0 | 12 | 1.25× |
| 第二条系统消息 | 12 | 0 | 12 | 1.25× |
| 用户消息开始 | 12 | 12 | 0 | 0.10× |
| 用户消息结束 | 12 | 12 | 0 | 0.10× |
| 它自己的消息,每一次回合 | 12 | 12 | 0 | 0.11× |
| 它自己的消息,仅在过期时 | 12 | 12 | 0 | 0.10× |
我的单独信息保留了缓存的两种形式,每一次交互以及仅在过期时。 条件是消息所在的位置。 在稳定指令之后,提供者会读取它之前的所有内容。 作为第二条系统信息,它位于指令之中,GPT-6 Luna 在 12 的 12 次交互中再次写下整个提示。
随后的规则很简短。 任何在交互之间变化的内容都放在不变化的内容之后。
只要文本不变,时钟不产生任何成本
缓存比较文本,因此只要文本保持不变,时钟是无害的。 在相同的探针中,间隔4秒,系统提示中的一分钟时钟每次都从缓存读取。 以间隔65秒,它在每一次轮次中强制完全重写。
分辨率决定了这种情况发生的频率。 系统提示中的一小时时钟和日期行在所有12次65秒运行的轮次开启时都从缓存读取,因为它们都没有滚动。 它们也会在每小时和每天破坏一次。 一分钟时钟在每一次开始于比前一次更晚一分钟的轮次时破坏。
缓存本身也会过期。 在单次计时运行中,GPT-6 Luna 在30分钟空闲后仍读取其存储前缀,并在1.25×后再次写入整个提示60. DeepSeek V4.1 Flash 在10分钟后读取并在60后错过。 Claude Opus 5.5 已经在10后错过,因为 Anthropic 的默认缓存持续 5 分钟,其 1 小时缓存写入成本为 2×. 那个第二天返回对话的人,文章开头的案例,发现所有三者都有陈旧时间和冷缓存。 那个第一次回到的轮次支付了整个提示的费用,无论工具包如何操作。 Placement决定其后的回合是否也如此。
4实验室的模型给出了4个不同答案
GPT-6 Luna是其中一个提供商的答案。 为了看看这条经验的普适性,我们在每个4实验室的一个当前模型上运行相同的放置,使用相同的2.5K-token提示,每个都固定到单一提供商:
Chart data
| GPT-6 Luna (OpenAI) | Claude Opus 5.5 (Anthropic) | DeepSeek V4.1 Flash (DeepInfra) | |
|---|---|---|---|
| No clock | 0.11 | 0.07 | 0.03 |
| System prompt | 1.25 | 1.24 | 0.13 |
| Second system | 1.25 | 0.08 | 0.04 |
| User message | 0.12 | 0.08 | 0.04 |
Reference line, listed input price: 1
GPT-6 Luna缓存完整消息。 一行更改会使包含它的消息及其后的所有内容失效。
Claude Opus 5.5缓存调用者标记的地方。 Anthropic的模型只缓存到
cache_control标记,工具箱放置的位置。 没有标记时,同一提示在每次调用时都计费全价。 在系统提示中放置标记时,块内的时钟成本为1.24×,而块外的第二个系统消息中的时钟则为0.08×. GPT-6 Luna惩罚的放置在Opus上是安全的。 在Opus价格下,每次转动开启的差价为$0.0214 对比 $0.0023. Opus也将相同提示计为4,056个token,而GPT-6 Luna计为2,395,因此相同文本在任何价格生效前就已多花1.69×token.DeepSeek V4.1 Flash以256-token块缓存,并且写入不额外收费。 读取结果恰好是256的倍数:未更改提示为2,560 token,系统提示末尾有时钟时为2,304 token。 更改行只需支付包含它的块。 初始调用按普通输入价格计费,读取按0.03–0.04×计费。 在每个放置的8次运行中,2个单独调用在同一次转动中错过缓存,而同一次运行随后读取时则被视为请求落在不同服务器,而非放置效果。 DeepSeek自己的端点是唯一被OpenRouter标记为自动缓存的,且我的账户隐私设置将其排除,因为该端点在付费流量上训练。 运行通过DeepInfra,该端点已缓存,Fireworks和Morph在两次调用检查中也已缓存。
Muse Spark 1.3在工具循环内读取其缓存,并在每个新转动开始时错过。 我们的第一次探测,向同一系统提示提出新问题,最多在10次调用中从缓存获取113个token,分别为2.9K、8.9K和19.4K个token. 当后续电话延伸了先前请求时,正如代理工具循环所做的那样,Muse 读取 2,801 的 2,966 个令牌并计费 0.17×. 下一轮用户发言,面对完整历史记录时,什么也不读。 OpenRouter 报告 Muse 在实时流量中的 86.1% 缓存命中率,这适用于以工具循环为主的工作负载。 在一次轮次开始时,时钟对 Muse 没有影响,因为那次调用无论如何都会失效。
相同的 harness 决策在每个模型上产生不同的成本。 先了解你的提供商使用哪种机制,然后再调整任何东西。
缓存命中带来了金钱,而不是速度
我们预期缓存的回合会更快地回答。 在 10 GPT-6 Luna 的顺序对调用中,使用 8.5K 令牌,第一次调用的中位数时间为 437 ms(来自缓存)和 490 ms(没有缓存). 这个差距落在样本的分布范围内。 在这个规模下,缓存改变了回合的成本,但保持了耗时大致相同。
所以我记得在询问时间时的暂停有其他原因。 错误位置的时钟成本是金钱。
在一次对话中,重写会累积
系统提示中的时钟位于整个对话之前,因此每一次重写都覆盖了其后增长的历史以及指令。 下面是一次12-回合GPT-6 Luna对话的测量成本,包括完整的供应商报告账单,包含输出和每个回合内的调用:
Chart data
| turn | Clock at the end of the system prompt | Clock at the end of the user message |
|---|---|---|
| 1 | 0.119 | 0.119 |
| 2 | 0.237 | 0.14 |
| 3 | 0.357 | 0.161 |
| 4 | 0.477 | 0.182 |
| 5 | 0.599 | 0.203 |
| 6 | 0.722 | 0.225 |
| 7 | 0.846 | 0.247 |
| 8 | 0.971 | 0.269 |
| 9 | 1.097 | 0.291 |
| 10 | 1.224 | 0.313 |
| 11 | 1.352 | 0.335 |
| 12 | 1.482 | 0.358 |
两行共享它们的第一次回合,当两者都写入缓存时。 从那以后,每个带有系统提示时钟的回合成本为5.7×,与在用户消息末尾的时钟相同回合的成本相比。 到第12回合时,对话已花费4.1×,且差距随每个回合扩大。
分数的几分钱在规模上成为一项费用。 该预测为每天服务10,000个对话的产品定价,每个对话都有一个8.5K-token的系统提示,20个回合,且历史每回合增长1,500个token. 每个模型使用其列出的价格和上述展示的缓存行为:
| 模型 | 缓存行为 | 每次对话,系统提示中的时钟 | 每次对话,用户消息末尾的时钟 | 每年差异 |
|---|---|---|---|---|
| GPT-6 Luna | 整条消息 | $0.057 | $0.0057 | $187K |
| Claude Opus 5.5 | 呼叫者的标记 | $2.28 | $0.14 | $7.8M |
| DeepSeek V4.1 Flash | 256-令牌块 | $0.042 | $0.0032 | $141K |
| Muse Spark 1.3 | 在回合开场时错过 | $0.57 | $0.57 | $0 |
DeepSeek 的块在时钟变化时保留系统提示,模型仍然更昂贵 13×,因为时钟后的历史超过了几回合内的指令。 Muse Spark 显示另一面:它在我们运行的每个回合开始时都错过了,因此放置没有节省任何费用,每个回合开场都付全价,$2.1M 一年用于相同流量。
在实时流量中,缓存命中率占据了大部分账单
我们的测量使用受控提示。 OpenRouter 发布相同模型在所有人流量上的成本,且相同机制在规模上也会出现。 几乎所有发送给这些模型的都是输入:96.3% 的 GPT-6 Luna 第一天的 token,98.5% 的 Claude Opus 5.5 的,DeepSeek V4.1 Flash 的,以及 98.9% 的 Muse Spark 1.3 的。 输入是缓存适用的地方,因此命中率决定了业务支付的大部分。
客户为 Claude Opus 5.5 每百万输入 token 支付 $0.87,按列出的 $4.00,$0.30 对 Muse Spark 1.3 的 $1.25,以及 $0.036 对 GPT-6 Luna 的 $0.10. 在同一天为相同模型提供服务的端点之间,支付的价格随命中率变化:
Chart data
| USD per 1M input tokens | |
|---|---|
| 92.2% hit | 0.557 |
| 89.9% hit | 0.658 |
| 88.7% hit | 0.727 |
| 81.6% hit | 0.974 |
| 77.4% hit | 1.123 |
| 0% hit | 4.399 |
Reference line, listed input price: 4
将每一次未命中计为缓存写入,每一次命中计为读取,预测每个 5 主要端点公布的价格误差在 2–13%. 仅命中率就能解释价格差异。 在 GPT-6 Luna 上,同样的模式从 $0.025 在 88.1% 命中率到 $0.075 在 49.4%,相差 3.
缓存错误在规模上给组织造成的成本
同样的放置决策在每种使用这些 API 的组织上产生不同的影响。
Harness 构建者一次性为每个用户设置命中率。 发送 Claude Opus 5.5 第一天流量最多的 5 应用都是代理,介于 2.9B 和 16.3B token 之间。 对于 10B 输入 token 的 harness,每点缓存命中率价值 $175K 一年. 上述 92.2% 与 77.4% 端点之间的差距在该流量下为 $2.07M 一年. 系统提示中的时钟每次重写开启都花费 $1.75M 到 $8.76M 一年,取决于开启是 1 调用 10 还是 1 调用 2. 这一决策也会传播:每个基于 harness 构建的产品都会继承其放置。 写作时我们在另一套 harness 中发现了相同的系统提示时钟,它运行的是同一 runner 的旧版本。
运行内部 AI 平台的公司为其背后的每个团队设置它。 一个网关为每个请求的系统提示打上时间戳或请求 ID 进行审计,将每个应用的开启转为写入,无论团队在其上构建什么。 计费是第二个暴露点。 按列表价格计费,输入成本看起来比 GPT-6 Luna 的账单大 2.8×,Muse Spark 1.3 上 4.1×,Claude Opus 5.5 上 4.6×. 我们自己的账本把 33 调用夸大了 2.7×,我几乎因其而更换模型。
发布 AI 产品的公司在每次对话中都要支付。 在一次对话中,错误的时钟每次开启成本为 5.7×. 在整个市场上,风险更大。 9 月 21 日,Muse Spark 1.3 通过 OpenRouter 处理了 88.5B 输入 token。 按列表价格为 $110.6K;客户支付了 $26.9K,而该流量每点命中率价值 $355K 一年. DeepSeek V4.1 Flash 同日处理了 2.68T 输入 token,按 DeepInfra 的价格每点价值 $1.33M 一年。 这些数字涵盖了一个路由器。 直接发送给供应商的流量不会出现在它们中。
解决方案:冻结每个请求的起始部分,并在末尾添加变化
这些成本的根源都指向同一机制,修复也是如此。 结构良好的代理 Harness 的约定读作其后果:
- 先稳定,后变化。 工具定义和系统提示在整个对话中保持冻结。 时间、工作目录、请求 ID 以及任何其他变化的内容都放在最新消息的末尾。
- 追加,永不编辑。 早期回合按原样发送。 编辑、重新排序或裁剪会使更改之后的一切失效。
- 使用你提供商的杠杆。 在 GPT-6 Luna 上,会话键和缓存标记不起作用,因为相同的提示已经命中。 在 Claude Opus 5.5 上,标记是整个机制。 在 DeepSeek V4.1 Flash 上,提供商的选择决定是否存在缓存。
- 粗化必须保持早期的内容。 系统提示中的日期行每天会断裂,分钟时钟在每个新分钟开始时会断裂。
- 或者省略时钟。 Harness 可以给模型一个返回时间的工具,因此提示永不变化,模型在需要时询问。 这会产生一次往返,在提问时发生。
- 从账单中结算。 价格来自提供商报告的成本。 由令牌计数和标价构建的账本隐藏了所有这些信息。
关注命中率,因为导致其失效的因素一直在变化
上述修复是一次单独的编辑。 周围的条件持续变化。 一个机架获得了新的挂钩,网关开始用 ID 标记请求,团队迁移到使用不同缓存机制的模型,提供商改变空闲前缀保持热度的时长。 这里的四个模型以四种不同方式缓存,Claude Opus 5.5 让缓存在空闲时间 10 分钟内变冷。 我们发现第二个机架的同一时钟仅仅停留在旧版本上。 这并未产生错误。
每次调用已返回查看所需的所有信息:提示 token、缓存 token、缓存写入 token 以及计费成本。 每次调用记录这些信息,并标记调用是开启新轮还是继续现有轮,这些字段给出每条路线和模型值得关注的三个数字:
- 开启轮次的读取率。 读取存储前缀的开启轮次占比。 错误位置的时钟将其从 12 的 12 下降到我们运行中的 0 的 12.
- 写入占比。 缓存写入 token 占所有输入的比例。 每轮都写入的路线支付 1.25×,且永不享受折扣。
- 相对于列表的有效输入价格。 账单自身的判定,从提供商报告的成本而非 token 计数得出。
对这些数字设定阈值可捕捉突然下降。 在数周数据中命名原因是一个分类问题,更新的模型类别更适合。 Jev,来自 TypeSafe,其制造商称之为 System One 模型。 它不会生成文本。 它接受状态和已输入的问题,并返回带有概率分布和置信度的已输入答案:在选项中做出选择、给出“是”的概率,或在有序尺度上的位置。 给定路线的每日缓存配置文件,它可以命名该日匹配的模式(健康、转弯开启重写、转弯之间缓存失效、到达不缓存的终点的流量),并说明其确定性,因此类别的变化成为警报。 我们在生产中使用它来分类文档,并在观察中对完成的代理剧集进行评分。 OpenRouter 将其列为每百万输入令牌 $0.042,输出不收费。 按此价格,对每条 1,000 路线的每日 2K 令牌配置文件进行分类,每年约需 $31,相比之下,单点命中率在上述 harness 规模下每年仅需 $175K.
一个持续重写其缓存的系统会在每一次对话的每一次转弯上支付溢价,持续运行期间,账单很少说明原因。 修复可以像时间写法一样小。 维持修复需要有人监视的数量。
我们测量的内容,以及仍需测量的内容
上述每个测量值均来自 OpenRouter 的每次调用字段(缓存令牌、缓存写入令牌和计费成本),时间为 2026 年 9 月 23 日。 市场数据来自 OpenRouter 当天公开模型页面的读取:实际支付的加权输入价格、每个端点的有效价格和缓存命中率,以及每个模型一天的令牌活动。 Claude Opus 5.5 和 GPT-6 Luna 于 9 月 22 日上线,因此它们的活动数据仅覆盖部分第一天,文章仅将其作为份额使用。 实验总成本为 $0.63,当账户使用量接近 $1 上限时探针拒绝启动。 价格为 OpenRouter 当天公布的列表价格。 OpenRouter 的缓存指南列出 OpenAI 次缓存读取,倍率为 0.25–0.50×;GPT-6 Luna 的读取计费为 0.10×,本文报告的是实际计费情况。
仍未解决的问题:每个模型的空闲缓存何时失效的确切点,单次计时运行仅在两端;每小时或日期时钟在真实对话间隙中何时失效;Muse Spark 在每轮开始时为何会错过未更改历史记录的情况;以及 DeepSeek 在其自身端点上的行为。 每轮修复已在我们的生产代理中上线,同一发现已排队用于运行旧版构建的第二个 harness.
关键归因
由我完成。 文章背后的问题:为什么 AI 从未能准确知道日期和时间,并且在应该即时给出答案时却需要几秒钟。 认为时间在会话中会过时并且需要再次提供,我猜测一个确定性的、仅在过时时才出现的消息会让提示保持缓存,并通过实验来测试它。 成本框架:为构建这些模型的企业量化,从利用构建器到运营自身内部 AI 平台的公司,现状以及其复合效应。 对持续观察的总结,使用 System One 模型(如 Jev)对缓存配置随时间进行分类,因为修复仅在有人持续监控时才有效。
由 Claude Opus 5.5 完成。 它发现我们的成本账本隐藏了缓存,2.7× 在 33 调用中,并将原因追溯到系统提示中每轮都变化的 2 行,. 它构建了现在已投入生产的运行器修复、探测器、分析以及每个数字背后的成本模型,并将机制与 OpenRouter 的公开市场数据进行匹配。 在 4 模型中,它识别出 3 种不同的缓存行为,包括 GPT-6 Luna 的整条消息行为,以及一个没有可用缓存的第四个模型。
持久的批评。
- 来自 Claude Opus 5.5 的首次解释:缺失的会话键。 它的探测器驳斥了这一点;相同的提示已在多轮中从缓存读取。
- 来自 Claude Opus 5.5 的测量结果,我的猜测:单独的时间消息仅在稳定指令之后才有效。 文章携带了我的想法,并附加了该条件。
共同达成。 发现时钟在文本不变时不产生费用,文本变化后则产生整个提示的费用。 以及文章所依据的规则:任何在轮次之间变化的内容都放在不变化的内容之后。
#AI#agents#benchmarking#performance#cost#experiential#insights