提示词缓存
用提示词缓存降低 BigModel.io 的输入成本:使用 Anthropic cache_control 断点、读取 cached_tokens,并了解缓存读取与写入如何计费。
当一个请求的开头与之前的请求有相同的长前缀(系统提示词、工具定义、文档)时,供应方可以从缓存中复用这部分内容。命中缓存的 token 按模型的缓存读取价计费,而不是完整的输入价。
| 缓存触发方式 | 接口 | 响应中的字段 |
|---|---|---|
用 cache_control 标记断点 |
/v1/messages |
usage.cache_creation_input_tokens、usage.cache_read_input_tokens |
| 供应方自动缓存 | /v1/chat/completions |
usage.prompt_tokens_details.cached_tokens |
模型目录中每个模型页面都列出每百万 token 的输入、输出、缓存读取和缓存写入价格。依赖某个模型的缓存之前,先看它的模型页面是否有缓存读取价。
模型是否缓存、何时缓存由其供应方决定。只要上游报告了缓存 token,BigModel.io 就按缓存价计费,用量记录中会显示为缓存读取 token。
#缓存如何计费
- 缓存读取 token 按缓存读取价计费。在 Chat Completions 上,
cached_tokens会从输入 token 中扣除并按缓存读取计费,不会重复收费。 - 缓存写入 token(Messages 的
cache_creation_input_tokens)按缓存写入价计费。如果模型分别定价 5 分钟和 1 小时缓存写入,则各自按对应价格计费。 - 总费用再乘以分组倍率,与所有用量相同。见计费与充值。
用量页面中,每条请求的 token 提示框会显示缓存创建(5m / 1h)和缓存读取 token。
#在 Messages API 中使用 cache_control
在你希望缓存的前缀的最后一个块上加 cache_control。从开头到这个块(含)的所有内容都会成为缓存前缀。
curl https://bigmodel.io/v1/messages \
-H "Authorization: Bearer $BIGMODEL_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "glm-5.3",
"max_tokens": 256,
"system": [
{"type": "text", "text": "你是 Acme 的客服。<此处粘贴一份很长的政策文档>",
"cache_control": {"type": "ephemeral"}}
],
"messages": [{"role": "user", "content": "退款流程是怎样的?"}]
}'import os
from anthropic import Anthropic
client = Anthropic(base_url="https://bigmodel.io", api_key=os.environ["BIGMODEL_API_KEY"])
policy = open("policy.md").read() # 一段较长且不变的前缀
for question in ["退款流程是怎样的?", "可以更换套餐吗?"]:
msg = client.messages.create(
model="glm-5.3",
max_tokens=256,
system=[{"type": "text", "text": policy, "cache_control": {"type": "ephemeral"}}],
messages=[{"role": "user", "content": question}],
)
u = msg.usage
print(u.cache_creation_input_tokens, u.cache_read_input_tokens, u.input_tokens)import Anthropic from "@anthropic-ai/sdk";
import { readFileSync } from "node:fs";
const client = new Anthropic({ baseURL: "https://bigmodel.io", apiKey: process.env.BIGMODEL_API_KEY });
const policy = readFileSync("policy.md", "utf8");
for (const question of ["退款流程是怎样的?", "可以更换套餐吗?"]) {
const msg = await client.messages.create({
model: "glm-5.3",
max_tokens: 256,
system: [{ type: "text", text: policy, cache_control: { type: "ephemeral" } }],
messages: [{ role: "user", content: question }],
});
console.log(msg.usage.cache_creation_input_tokens, msg.usage.cache_read_input_tokens);
}第一次调用应显示缓存创建 token,第二次显示缓存读取 token。上游是否遵循断点取决于分组背后的模型。
#网关的处理规则
cache_control会透传给供应方。- 每个请求最多保留 4 个断点,多余的会被移除:先从
tools移除,再从messages,最后从system。 - 思考块上不允许
cache_control,会被移除。
#Chat Completions 的自动缓存
对于自动缓存的供应方,你不需要额外传参。保持每次请求的开头完全一致(相同的系统提示词、相同的工具列表和顺序),把变化的内容放在末尾,然后读取结果:
completion = client.chat.completions.create(model="deepseek-v4-flash", messages=messages)
details = completion.usage.prompt_tokens_details
print(details.cached_tokens if details else 0)#验证配置
在几分钟内发送两次相同长前缀的请求。第二次响应中,cache_read_input_tokens(Messages)或 prompt_tokens_details.cached_tokens(Chat Completions)应大于 0。在用量页面,第二条请求的 token 提示框会显示缓存读取 token,费用也更低。
#常见问题排查
缓存读取始终为 0。 两次请求的前缀不同(系统提示词里有时间戳、工具顺序变了),前缀短于供应方的最小长度,缓存已过期,或模型不支持缓存。让前缀逐字节一致,并确认模型页面有缓存读取价。
每次调用都有缓存创建 token。 前缀每次都不同,所以每次都写入新缓存。把会变化的内容移到断点之后。
部分断点似乎被忽略。 你发送了超过 4 个断点,多余的被移除。保留最有价值的断点(通常是系统提示词和工具列表末尾)。
供应方返回与 cache_control 相关的 400。 上游模型不接受该字段,请对该模型去掉 cache_control。
/v1/messages 返回 404。 Key 的分组只支持 Chat Completions,此时只能依赖自动缓存。
#相关文档
- 计费与充值:完整的费用计算公式。
- Messages API 参考。
- 用量:查看每条请求的缓存 token。
更新于 · 以 Markdown 查看