OpenRouter 集成与实践
OpenRouter 集成与实践
提示词缓存
7 分钟阅读
提示词缓存
缓存提示词消息
为了降低推理成本,你可以在受支持的模型服务提供商和模型上启用提示词缓存。
大多数模型服务提供商会自动启用提示词缓存,但请注意:有些提供商(见下文的 Alibaba 和 Anthropic)要求你按消息启用。
使用缓存时(无论是在受支持模型上自动启用,还是通过 cache_control 属性),OpenRouter 会使用模型服务提供商粘性路由来最大化缓存命中——详见下方的模型服务提供商粘性路由。
模型服务提供商粘性路由
为了最大化缓存命中率,OpenRouter 使用模型服务提供商粘性路由,在一次已缓存请求之后,将你的后续请求路由到同一模型服务提供商端点。这对隐式缓存(例如 OpenAI、DeepSeek、Gemini 2.5)和显式缓存(例如 Anthropic 的 cache_control 断点)都自动生效。
工作原理:
- 在一次使用提示词缓存的请求之后,OpenRouter 会记住是哪个模型服务提供商处理了你的请求。
- 同一模型的后续请求会被路由到同一模型服务提供商,从而保持缓存处于热状态。
- 仅当该模型服务提供商的缓存读取价格低于常规提示词价格时,粘性路由才会激活,以确保你始终能从成本节省中受益。
- 如果粘性绑定的模型服务提供商不可用,OpenRouter 会自动回退到次优的模型服务提供商。
- 当你通过
provider.order指定了手动的模型服务提供商顺序时,不会使用粘性路由——此时以你显式指定的顺序为准。
粘性路由的粒度:
粘性路由按账户、按模型、按对话跟踪。默认情况下,OpenRouter 通过对每条请求中的第一条 system(或 developer)消息以及第一条非 system 消息做哈希来识别对话,因此共享相同开头消息的请求会被路由到同一模型服务提供商。这意味着不同对话会自然地粘到不同的模型服务提供商,在提升负载均衡和吞吐量的同时,保持各对话内部的缓存处于热状态。
使用 session_id 实现粘性会话
若要对粘性路由进行更显式的控制,可以在请求中传入 session_id。当存在 session_id 时,OpenRouter 会直接将其用作粘性路由键,而不再从消息哈希中派生。这对多轮智能体工作流尤其有用:即使请求之间的开头消息会变化,你仍希望路由到同一模型服务提供商。
你可以通过两种方式提供 session_id:
- 请求体:在请求体中把
session_id作为顶层字段。如果两者都提供,以请求体中的值为准。 - 请求头:设置
x-session-idHTTP 请求头。
session_id 最长为 256 个字符。
如果两者都未设置,OpenRouter 会回退到 OpenAI 风格的 prompt_cache_key 请求字段,将其作为粘性路由键。已经发送 prompt_cache_key 的客户端无需改动即可获得会话固定路由。
设置 session_id 后,粘性路由会在任何成功请求上激活——即使尚未观察到缓存用量——以便同一会话中的后续请求从一开始就能受益于提示词缓存。没有 session_id 时,粘性路由仅在检测到缓存命中之后才会激活。
使用 Auto Router 或 Pareto Router 等路由模型时,粘性路由还会固定解析后的模型——而不仅仅是模型服务提供商。这可以防止路由模型在同一对话的每一轮选择不同的模型。详见 Auto Router — 会话粘性。
跨模态分组请求
除粘性路由外,OpenRouter 还会使用 session_id 在日志页面的「会话」视图中对你的请求进行分组。同一个 session_id 会把对话轮次、重试以及不同模态的请求关联起来,让你可以在一处追踪完整的智能体会话。
这种分组适用于同步端点,而不仅仅是聊天补全:
- Chat 和 Responses:在请求体中发送
session_id,或使用x-session-id请求头。 - 嵌入、重排序、语音转文本、文本转语音、图像生成和视频生成:发送
x-session-id请求头。这些端点不接受请求体中的session_id。它们仅将该值用于分组,因此粘性路由不适用于这些端点。
256 字符限制对两种输入都适用。在多模态工作流中发送一致的 x-session-id,即可把所有这些生成归到同一会话下。例如:智能体先转写音频,再调用聊天模型,然后生成图像。
Batch API 目前尚未按其 session_id 对生成结果进行分组。
检查缓存用量
要查看每次生成因缓存节省了多少费用,你可以:
- 在活动(Activity)页面点击详情按钮
- 使用
/api/v1/generationAPI,文档见此 - 检查每条 API 响应中用量响应里的
prompt_tokens_details对象
响应体中的 cache_discount 字段会告诉你该响应在缓存用量上节省了多少。部分模型服务提供商(如 Anthropic)会在缓存写入上给出负折扣,但在缓存读取上给出正折扣(从而降低总成本)。
使用 Auto Router 或 Pareto Router 等路由模型时,粘性路由还会固定解析后的模型——而不仅仅是模型服务提供商。这可以防止路由模型在同一对话的每一轮选择不同的模型。详见 Auto Router — 会话粘性。
usage 对象字段
API 响应中的 usage 对象在 prompt_tokens_details 字段中包含详细的缓存指标:
关键字段包括:
cached_tokens:从缓存中读取的 Token 数量(缓存命中)。该值大于零时,说明你正在受益于已缓存内容。cache_write_tokens:写入缓存的 Token 数量。在建立新缓存条目的首次请求上会出现此字段。
OpenAI
缓存价格变化:
- 缓存写入:GPT-5.6 系列之前的模型无费用。GPT-5.6 及之后的模型即使使用自动缓存,也会按原始输入价格的 1.25 倍收取缓存写入费用——无需选择加入。
- 缓存读取:(视模型而定)按原始输入价格的 0.25 倍或 0.50 倍计费
OpenAI 的提示词缓存是自动化的,无需任何额外配置。提示词最短长度为 1024 Token。
点击此处了解更多关于 OpenAI 提示词缓存及其限制的信息。
显式提示词缓存
缓存价格变化:
- 缓存写入:按原始输入价格的 1.25 倍计费(与 GPT-5.6 及之后模型上的自动缓存写入费率相同)
- 缓存读取:按该模型的折扣缓存读取费率计费,与自动缓存相同
显式提示词缓存同时适用于 Chat Completions 和 Responses API,让你可以直接控制缓存边界,而不是依赖 OpenAI 自动放置断点。缓存前缀的最短 TTL 为 30 分钟。上游细节见 OpenAI 的显式提示词缓存文档。
OpenAI 显式提示词缓存仅由 OpenAI GPT-5.6 及更新版本支持。
有两项控制:
prompt_cache_breakpoint:放在单个文本内容块上(Responses 中为input_text,Chat Completions 中为text),用于标记可复用前缀的结尾。到该块为止的全部内容成为候选缓存前缀。自动缓存仍然启用。prompt_cache_options:放在请求根级。将mode设为"explicit"会禁用 OpenAI 托管的断点,因此只有标记了prompt_cache_breakpoint的块才会参与缓存。使用ttl请求缓存时长(例如"30m")。
Responses API:
Chat Completions API:
块级标记可以互换:带有 Anthropic 风格 cache_control 的文本块在路由到受支持的 OpenAI 模型时,会获得 prompt_cache_breakpoint;带有 prompt_cache_breakpoint 的块在路由到 Anthropic 或 Google 时,会获得默认(5 分钟)的 cache_control。TTL 不会被转换——发往 OpenAI 时会丢弃 cache_control 的 ttl,而请求级的 prompt_cache_options 仅适用于 OpenAI。
缓存活动会报告在 usage.input_tokens_details(Responses)和 usage.prompt_tokens_details(Chat Completions)中:cache_write_tokens 统计写入缓存的提示词 Token,cached_tokens 统计从缓存读取的提示词 Token。
Grok
缓存价格变化:
- 缓存写入:无费用
- 缓存读取:按原始输入价格的 0.25 倍计费
Grok 的提示词缓存是自动化的,无需任何额外配置。
Moonshot AI
缓存价格变化:
- 缓存写入:无费用
- 缓存读取:按原始输入价格的 0.25 倍计费
Moonshot AI 的提示词缓存是自动化的,无需任何额外配置。
Groq
缓存价格变化:
- 缓存写入:无费用
- 缓存读取:按原始输入价格的 0.5 倍计费
Groq 的提示词缓存是自动化的,无需任何额外配置。目前可用于 Kimi K2 模型。
Alibaba Qwen
显式缓存的价格变化:
- 缓存写入:按原始输入价格的 1.25 倍计费
- 缓存读取:按原始输入价格的 0.1 倍计费
Alibaba 提示词缓存需要显式缓存断点。在你想要缓存的内容块上添加
cache_control: { "type": "ephemeral" },语法与 Anthropic 显式缓存相同。缓存写入使用 5 分钟 TTL。
Alibaba 显式缓存可用于 deepseek/deepseek-v3.2、
qwen/qwen3-max、qwen/qwen-plus、qwen/qwen3.6-plus、
qwen/qwen3-coder-plus 和 qwen/qwen3-coder-flash。快照端点,
包括 qwen/qwen3.5-plus-02-15 和 qwen/qwen3.5-flash-02-23,不支持显式缓存。
示例
Anthropic Claude
缓存价格变化:
- 缓存写入(5 分钟 TTL):按原始输入价格的 1.25 倍计费
- 缓存写入(1 小时 TTL):按原始输入价格的 2 倍计费
- 缓存读取:按原始输入价格的 0.1 倍计费
有两种方式为 Anthropic 启用提示词缓存:
- 自动缓存:在请求顶层添加单个
cache_control字段。系统会自动将缓存断点应用到最后一个可缓存块,并随着对话增长向前推进。最适合多轮对话。 - 显式缓存断点:将
cache_control直接放在各个内容块上,以精细控制究竟缓存什么。显式断点上限为四个。建议将缓存断点留给大段文本,例如角色卡、CSV 数据、检索增强生成(RAG)数据、书籍章节等。
自动缓存(顶层 cache_control)受 Anthropic、Google Vertex AI、Azure 和 Amazon Bedrock 模型服务提供商以及 AWS 上的 Claude Platform 支持。在 Amazon Bedrock 上,OpenRouter 会把顶层字段转换为尾部缓存断点(Bedrock 的简化缓存管理),因为 Bedrock 的 InvokeModel API 不直接接受该顶层字段。显式的按块 cache_control 断点适用于所有兼容 Anthropic 的模型服务提供商,包括 Bedrock 和 Vertex。
Responses API 支持: Responses API 通过顶层 cache_control 支持自动缓存。input 条目内部的 Anthropic 风格按块 cache_control 不会通过 Responses API 暴露——请改用 OpenAI 的按块 prompt_cache_breakpoint,当请求被路由到 Anthropic 或 Google 时,OpenRouter 会将其转换为默认的 cache_control 断点。注意 prompt_cache_breakpoint 不携带 ttl;若需要设置缓存 ttl,请使用带 cache_control 的 Chat Completions 或 Anthropic Messages API。
默认情况下,缓存会在 5 分钟后过期,但你可以在 cache_control 对象中指定 "ttl": "1h",将其延长至 1 小时。
点击此处了解更多关于 Anthropic 提示词缓存及其限制的信息。
最低 Token 要求
每个模型都有可缓存提示词的最短长度(见 Anthropic 的缓存限制):
- 4,096 Token:Claude Opus 4.8、Claude Opus 4.7、Claude Opus 4.6、Claude Opus 4.5、Claude Haiku 4.5
- 2,048 Token:Claude Haiku 3.5
- 1,024 Token:Claude Sonnet 4.6、Claude Sonnet 4.5、Claude Opus 4.1、Claude Opus 4、Claude Sonnet 4
短于这些最低要求的提示词不会被缓存。
缓存 TTL 选项
OpenRouter 为 Anthropic 支持两种缓存 TTL 值:
- 5 分钟(默认):
"cache_control": { "type": "ephemeral" } - 1 小时:
"cache_control": { "type": "ephemeral", "ttl": "1h" }
1 小时 TTL 适用于更长的会话:你希望在多次请求之间保持已缓存内容,而不反复承担缓存写入成本。1 小时 TTL 的缓存写入更贵(基础输入价格的 2 倍,而 5 分钟 TTL 为 1.25 倍),但通过避免重复缓存写入,可以在较长会话中节省费用。显式缓存断点的 1 小时 TTL 适用于所有 Claude 模型服务提供商(Anthropic、Amazon Bedrock 和 Google Vertex AI)。
在 Batch API 中缓存
cache_control 断点在 Anthropic :batch 端点上的工作方式与同步 API 相同,但单个批次内的请求可能并发且以任意顺序处理——某行写入的缓存不保证对同一批次中的其他行可见。要获得可靠的缓存命中,请在共享前缀上使用 "ttl": "1h" 断点,并在连续批次中复用该前缀(或先用同步请求预热缓存):第一个批次支付缓存写入价格,后续批次在缓存保持热状态期间从缓存读取。
示例
自动缓存(推荐用于多轮对话)
使用自动缓存时,在请求顶层添加 cache_control。系统会自动缓存直到最后一个可缓存块的全部内容:
随着对话增长,缓存断点会自动向前推进,以覆盖不断增长的消息历史。
使用 1 小时 TTL 的自动缓存:
显式缓存断点(精细控制)
system 消息缓存示例(默认 5 分钟 TTL):
带 1 小时 TTL 的 user 消息缓存示例:
DeepSeek
缓存价格变化:
- 缓存写入:按与原始输入价格相同的费率计费
- 缓存读取:按原始输入价格的 0.1 倍计费
DeepSeek 的提示词缓存是自动化的,无需任何额外配置。
Z.AI
缓存价格变化:
- 缓存写入:无费用(Z.AI 目前将缓存输入存储列为限时免费)
- 缓存读取:按各模型页面上显示的折扣缓存输入费率计费(通常约为原始输入价格的 0.2 倍)
Z.AI 的提示词缓存是自动化的,无需任何额外配置。缓存读取会报告在用量响应中 prompt_tokens_details 的 cached_tokens 字段。
为提高缓存命中率,OpenRouter 会在每次请求中向 Z.AI 发送会话亲和键,该键由你的账户以及(若已提供)你的 session_id 派生。在多轮对话中传入 session_id,可使同一会话的请求落在同一缓存上。
Google Gemini
隐式缓存
Gemini 2.5 Pro 和 2.5 Flash 模型现在支持隐式缓存,提供与 OpenAI 自动缓存类似的自动缓存功能。隐式缓存可无缝工作——无需手动设置或额外的 cache_control 断点。
价格变化:
- 无缓存写入或存储费用。
- 缓存 Token 按原始输入 Token 成本的 0.25 倍计费。
请注意,TTL 平均为 3–5 分钟,但会有所变化。Gemini 2.5 Flash 的请求至少需要 1024 Token,Gemini 2.5 Pro 至少需要 4096 Token,才有资格被缓存。
缓存请求的价格变化
- 缓存写入: 按输入 Token 成本加上 5 分钟的缓存存储计费,计算如下:
- 缓存读取: 按原始输入 Token 成本的 0.25× 计费。
支持的模型与限制
只有部分 Gemini 模型支持缓存。请查阅 Google 的 Gemini API 定价文档以获取最新详情。
缓存写入具有 5 分钟的生存时间(TTL),且不会更新。5 分钟后缓存过期,必须写入新缓存。
Gemini 模型通常需要至少 4096 Token 才会发生缓存写入。缓存 Token 会计入模型的最大 Token 用量。Gemini 2.5 Pro 的最低要求为 4096 Token,Gemini 2.5 Flash 的最低要求为 1024 Token。
Gemini 提示词缓存在 OpenRouter 上的工作方式
OpenRouter 简化了 Gemini 缓存管理,抽象掉其中的复杂性:
- 你不需要手动创建、更新或删除缓存。
- 你不需要显式管理缓存名称或 TTL。
如何启用 Gemini 提示词缓存
OpenRouter 上的 Gemini 缓存要求你在消息内容中显式插入 cache_control 断点,类似于 Anthropic。我们建议主要对大块内容使用缓存(例如 CSV 文件、较长的角色卡、RAG 数据,或大段文本来源)。
Gemini 只有一个 systemInstruction 字段,且已缓存的 Gemini 内容
将该 systemInstruction 视为不可变。在 OpenRouter 上,这意味着
第一条 system 或 developer 消息内部的 cache_control 可以缓存
归一化后的系统提示词,但不能在同一条消息内保留未缓存的动态尾部。
如果你需要提示词的某一部分保持动态,请把该动态内容移到后面的
user 消息中,而不是追加在第一条 system 消息的已缓存块之后。
示例
system 消息缓存示例
当已缓存的 system 内容在请求之间保持稳定时,此模式有效。如果
你需要动态的提示词片段,请把它放在后面的 user 消息中,而不是
作为第一条 system 消息中未缓存的尾部内容。