OpenRouter 集成与实践
OpenRouter 集成与实践
面向模型服务提供商
9 分钟阅读
模型服务提供商集成
面向模型服务提供商
如果你希望成为模型服务提供商并在 OpenRouter 上出售推理服务,请填写我们的表单开始接入。
在当前模型文档格式之前已完成集成?旧版扁平格式仍为现有集成保留支持。
要有资格在 OpenRouter 上提供推理,你必须具备以下条件:
1. 列出模型端点
你必须实现一个端点,返回应由 OpenRouter 提供服务的全部模型。每个模型描述为一组带类型的输入和输出模态对象:每个模态各自拥有其能力、约束、透传参数、定价和容量。仅无所属模态的请求作用域价格和容量条目保留在文档根级。
以下是响应格式示例:
id 字段应为 OpenRouter 调用你的 API 时使用的精确模型标识符。
所有 cost_usd 字段均为字符串格式,以避免浮点精度问题,且必须使用美元(USD)。
先前的扁平模型文档格式(带有 pricing.overrides、supported_sampling_parameters、supported_features 和 capacity_tpm 的扁平 pricing 对象)仍为现有集成保留支持,但所有新集成请使用上述格式。
有效的量化值为:int4、int8、fp4、mxfp4、nvfp4、fp6、fp8、mxfp8、fp16、bf16、fp32。精度未声明时使用 null(或省略该字段)。
可选的 tokenizer 字段命名模型使用的分词器家族(例如 GPT、Claude、Llama3、Gemini)。与 quantization 一样,它描述的是模型整体,因此位于根级而非任何模态之下。未知时请省略。
2. 模态
一份文档必须至少声明一种输入模态和一种输出模态。
输入模态
有效的输入模态类型为:text、image、video、audio、file。
每条输入模态记录包含:
| 字段 | 是否必填 | 说明 |
|---|---|---|
type | 是 | 模态判别器 |
supported_inputs | 否 | 该模态的带类型约束(见下文) |
pricing | 否 | 针对该输入计费的价格(见定价) |
capacity | 否 | 该输入声明的吞吐限制(见容量) |
passthrough_parameters | 否 | 作用域限定于该输入的模型服务提供商特定参数(见透传参数) |
supported_inputs 对象使用与输出 supported_parameters 相同的能力描述符语法,并对每个已知值域使用封闭枚举:
| 模态 | 约束字段 |
|---|---|
text | max_context_length、max_prompt_length |
image | sources、formats、detail_levels、references、role、max_content_size_bytes |
video | sources、formats、max_duration_seconds、max_content_size_bytes |
audio | sources、formats、max_duration_seconds、max_content_size_bytes |
file | sources、formats、references、max_content_size_bytes |
常见约束字段:
sources,媒体的提供方式:url、base64formats,接受的 MIME 类型,例如图像为image/png、image/jpeg、image/webp、image/gif;视频为video/mp4、video/webm;音频为audio/wav、audio/mpeg;文件为application/pdf、text/plain、text/markdown、text/html、text/csv、application/jsondetail_levels(图像):auto、low、high、originalrole(图像),图像在请求中扮演的角色:reference、first_frame、last_framereferences(图像、文件),描述请求可包含多少个参考项的整数描述符,例如{ "type": "integer", "min": 0, "max": 10 }max_context_length(文本),总上下文窗口:输入和输出 Token 合计max_prompt_length(文本),单独的最大输入长度;仅当它与上下文窗口不同时才声明
单值限制(max_context_length、max_prompt_length、输出 max_length、max_duration_seconds、max_content_size_bytes)是带有 value 和可选 unit(second、pixel、byte、token、character)的对象:
输出模态
有效的输出模态类型为:text、image、video、speech、transcription、embeddings、rerank、audio。
每条输出模态记录包含:
| 字段 | 是否必填 | 说明 |
|---|---|---|
type | 是 | 模态判别器 |
supported_parameters | 是 | 该模态接受的生成参数的描述符映射 |
streaming | 否 | 该输出是否支持原生服务器发送事件(SSE)流式传输(不适用于 embeddings / rerank) |
max_length | 否 | 最大输出长度(仅 text) |
pricing | 否 | 针对该输出计费的价格(见定价) |
capacity | 否 | 该输出声明的吞吐限制(见容量) |
passthrough_parameters | 否 | 作用域限定于该输出的模型服务提供商特定参数 |
能力描述符
supported_parameters 和 passthrough_parameters 是从参数名到带类型描述符的映射,描述该参数接受什么:
| 类型 | 形态 | 含义 |
|---|---|---|
range | { "type": "range", "min": 0, "max": 1 } | [min, max] 内的任意数字均有效 |
integer | { "type": "integer", "min": 1, "max": 128000, "unit": "token" } | [min, max] 内的任意整数均有效 |
boolean | { "type": "boolean" } | 支持(存在)或不支持(缺失) |
enum | { "type": "enum", "values": ["standard", "priority"] } | 可接受值的离散允许列表 |
array | { "type": "array", "items": { ... }, "max_items": 4 } | 由 items 描述的值列表 |
object | { "type": "object", "properties": { ... } } | 带有按键描述符的嵌套对象 |
unknown | { "type": "unknown" } | 可接受,但值域未经机器描述 |
描述符可以携带可选的 default,对数值类型还可以携带 unit。缺失的键表示该参数不受支持。
3. 定价
定价使用嵌套在所属模态上的数组。每条定价记录具有 type(计费种类)、unit(计费基准)和 cost_usd 字符串。unit 是基础计费单位,并不承诺一口价:按图像和按 Token 的价格可以随所属模态声明的参数缩放。
每个定价作用域接受它可以计费的单位。输入记录接受 token、image、second 或 character。输出记录接受这些单位再加上 request。根级 request 条目始终按 request 计费,web_search 条目按 search 计费。其他组合会在校验时被拒绝。
通过校验的文档是有效声明,并不保证今天就会对每个已声明的 SKU 计费:OpenRouter 对其流水线支持的 SKU 计费并记录其余部分,对新声明的 SKU 形态的计费会随支持落地而到来。请声明你实际收取的费用;不要为了迁就 OpenRouter 当前的计费范围而裁剪文档。
输入定价类型(位于输入模态记录上):
| 类型 | 含义 |
|---|---|
prompt | 该输入每消耗一单位的成本 |
cached_prompt | 从提示词缓存读取每单位的成本 |
cache_write | 写入提示词缓存每单位的成本 |
输出定价类型(位于输出模态记录上):
| 类型 | 含义 |
|---|---|
completion | 该输出每生成一单位的成本 |
internal_reasoning | 内部推理 Token 每单位的成本 |
请求定价类型(根级 pricing 数组,根级仅有这些价格):
| 类型 | 含义 |
|---|---|
request | 每请求的固定成本 |
web_search | 每次执行网络搜索的成本 |
不要用零值填充价格:对你不计费的 SKU 请省略定价记录。作为独立可计费行暴露的真正免费 SKU 可以使用 "0"。没有 pricing 数组的模态只是未定价。
使用 overrides 的条件定价
条件定价(例如长上下文档位)以声明方式附加到它所修改的那条定价记录上,使用 when 谓词:
对于按比例缩放的定价,在 supported_parameters 中声明控制旋钮,并按这些参数名附加覆盖项。普通谓词映射对其键应用 AND:
when 谓词要么是参数到条件的映射,要么是使用 allOf、anyOf 和 not 的组合。组合成员本身也是谓词,因此这些运算符可以嵌套。条件复用运算符 equals、gte、lte 和 min_items,每个条件对象恰好使用一个运算符;组合对象恰好携带 allOf、anyOf 或 not 之一。普通的多键映射等价于对单键映射做 allOf。
覆盖记录按顺序求值。在匹配的谓词中,靠后的记录胜出。这使得无需 OR 嵌套即可表达按分辨率与步数组成的价格矩阵。谓词可以引用所属模态声明的参数,或请求派生的量,例如提示词 Token 数。
覆盖谓词基于参数。随时间变化的定价不是覆盖,因为时间不是请求参数。见分时定价。
缓存定价
缓存价格是模态 pricing 数组中的一等 SKU。当限定字段不同时,多条记录可以具有相同的 type。一条记录的有效身份是其 type 连同其限定字段,因此两个 TTL 不同的 cache_write 记录是独立 SKU。两个有效身份相同的记录无效。
ttl_seconds 是该价格适用的缓存生存时间。它是限定字段,而不是 type 字符串的一部分,因此模型服务提供商可以在不扩展定价类型枚举的情况下增加生存时间。implicit 标记请求并未要求、由模型服务提供商主动发起的缓存,默认值为 false。显式和隐式缓存模式可以共存于同一模型。
缓存定价位于输入侧。提示词缓存存储并重新读取输入 Token,因此缓存记录属于输入模态记录,绝不属于输出。write 一词描述的是写入提示词缓存,而不是生成输出。
缓存价格是基础记录,不是覆盖。覆盖仍保留给生成参数上的请求条件定价。缓存 SKU 可枚举,以便计费和产品界面可以直接展示它们。模型服务提供商可以将 TTL 作为请求参数,该价格仍建模为缓存 SKU 而不是覆盖。缓存记录本身可以为真正的请求条件定价携带覆盖,例如长上下文档位提高缓存写入费率,但绝不能用于 TTL 差异。
缓存定价按模态划分,因此图像输入模态可以按自己的费率携带自己的缓存记录。同时提供两种显式写入生存时间以及由模型服务提供商主动发起的缓存的文本输入模态如下所示:
隐式记录上的零成本是有意为之。它表示模型服务提供商作为独立行暴露的真正免费 SKU。当模型服务提供商不对此计费时,请省略该 SKU。
分时定价
随时间变化的价格(高峰与非高峰费率)遵循与缓存生存时间相同的模式:时间窗口是定价记录上的一对结构化限定字段,而不是覆盖。时间不是请求参数,因此覆盖的 when 谓词没有可引用的对象。
utc_start 和 utc_end 是 UTC 中的 HHMM 值(0000–2359;分钟分量必须为 00–59),必须成对声明,且必须不同。窗口是半开的(包含 utc_start,排除 utc_end),并且可以跨越午夜。没有窗口的记录是所有其他时段的基础费率。在高峰窗口以更高费率计费的文本模态如下所示:
时间窗口在输入和输出定价记录上均可接受。与 ttl_seconds 一样,窗口是记录有效身份的一部分,因此不同窗口的记录是独立 SKU,两个窗口相同的记录无效。
4. 容量
容量使用与定价相同的带类型、按作用域放置方式。每个输入和输出模态都可以携带自己的 capacity 数组,作为 pricing 的兄弟字段。根级 capacity 数组仅保存请求作用域条目。这不会增加新的根级结构。
每条容量记录具有描述限制对象的 type、给出基准的 unit、一个 per 窗口,以及一个正整数 value:
容量类型复用所属作用域的定价类型。输入记录使用输入定价类型,输出记录使用输出定价类型,根级记录使用请求定价类型。输出和根级记录还可以使用 concurrency 表示同时进行中的工作。concurrency 没有 per 窗口。有效窗口为 minute、hour 和 day。缺失的 capacity 数组表示限制未声明,而不是零。
容量记录的身份是其 type、unit 和 per 窗口的组合,两个身份相同的记录无效。仅窗口不同的记录可以共存,因此同一维度上的每分钟突发限制和每日配额都可以声明。concurrency 记录没有窗口,因此仅按 type 和 unit 唯一。
在不同作用域中声明的限制是同时生效的独立桶:按模态的 Token 限制和根级请求限制各自在自己的维度上约束流量,只有当请求所消耗的每一项已声明限制都还有余量时,该请求才会被准入。在一个作用域中声明限制不会放宽或替换另一个作用域中的限制。
这种复用可以区分提示词、缓存提示词和输出容量,而无需为每个维度添加单独字段。容量和定价保持为独立的兄弟数组,因为模态可以声明限制而不声明价格,或声明价格而不声明限制。单位按作用域约束,与定价单位完全相同:一条记录接受其作用域(输入、输出或根级)可以计费的任意单位,因此图像容量表示为每分钟图像数,视频容量表示为每分钟输出秒数,不匹配的配对(例如按 search 计的 prompt 容量)会在校验时被拒绝。校验不会收窄到所属模态自身的计费单位,这就是为什么图像输出模态可以携带以 request 为单位的 concurrency 记录。
以下是覆盖文本输入、文本输出、图像输出和请求作用域的容量声明:
5. 透传参数
透传参数是 OpenRouter 原样转发的、特定于模型服务提供商的扩展通道,有别于归一化的 supported_parameters。它们按作用域放置:
- 请求作用域参数(适用于整个请求)位于根级
passthrough_parameters映射中。 - 输入作用域参数(由一种输入模态拥有,例如参考媒体控件)位于该输入记录上。
- 输出作用域参数(由一种输出模态拥有的生成控件)位于该输出记录上。
每个映射使用相同的能力描述符语法,因此消费方可以校验值,而不是猜测:
6. 数据中心与合规
声明每个端点的物理服务位置及其数据处理姿态:
datacenters[].country_code:ISO 3166-1 alpha-2 国家代码。datacenters[].region:模型服务提供商作用域的区域标识符(例如us-east-1)。compliance.zdr,零数据保留:不保留提示词,也不使用提示词进行训练。compliance.hipaa:HIPAA 合规。其他布尔认证标志(SOC 2、GDPR、FedRAMP 等)可能会随时间添加。
7. 运维字段
运维字段控制模型可用性与路由:
| 字段 | 说明 |
|---|---|
deprecation_date | ISO 8601 日期或 UTC 整点。见弃用日期 |
is_ready | 上线控制。见使用 is_ready 控制上线 |
is_free | 免费变体标记。见使用 is_free 的免费模型变体 |
discount_to_user | 面向用户的小数折扣。见使用 discount_to_user 的折扣 |
openrouter.slug | 该模型映射到的 OpenRouter slug |
弃用日期
如果模型已安排弃用,请以 ISO 8601 格式包含 deprecation_date 字段。OpenRouter 接受仅日期值或特定 UTC 整点:
- 对仅日期的弃用使用
YYYY-MM-DD。仅日期值默认为该日 13:00 UTC。 - 使用
YYYY-MM-DDTHH:00:00Z请求特定 UTC 整点,例如2025-06-01T15:00:00Z。
当 OpenRouter 的模型服务提供商监控检测到弃用日期或时间时,它会自动更新端点,向用户显示弃用警告。超过弃用时间的模型可能会自动从市场上隐藏。
使用 is_ready 控制上线
默认情况下,当 OpenRouter 的模型服务提供商监控在你的 /v1/models 响应中看到新模型时,它会自动暂存该端点、运行基线测试,并在测试通过且定价配置完成后取消隐藏(使其上线)。如果你需要在公告之前上传模型,或临时将模型下线,请设置可选布尔字段 is_ready:
行为:
is_ready: false会跳过对新暂存端点的基线测试,使其保持隐藏,并自动隐藏当前已上线的任何匹配端点。用它在上线前预先上传模型,或与我们协调将已上线模型下线。is_ready: true以及省略/缺失该字段都会保留默认的自动暂存和自动取消隐藏行为。
使用 is_free 的免费模型变体
如果你想提供模型的免费版本,请设置 is_free: true:
行为:
is_free: true将该端点标记为免费端点(:free后缀)。- 与
is_free: true一并发送的任何定价都会被忽略。免费端点始终为零成本。 is_free: false或省略该字段会保留默认行为(标准付费变体)。
你可以同时列出同一模型的免费和付费版本。只需始终在免费版本上设置 is_free: true。
使用 discount_to_user 的折扣
要为用户看到并支付的价格提供折扣,请包含可选的 discount_to_user 字段。它是 OpenRouter 应用于你所展示定价的小数分数:
行为:
0.2表示用户看到并支付的价格比你列出的定价低 20%。cost_usd为"0.000024"时显示为0.0000192。- 该折扣适用于每个已定价 SKU(提示词、补全、图像、缓存读取等),包括条件覆盖和时间窗口。
0、省略的字段或缺失的字段都表示无折扣。- 负值会应用加价而不是折扣,因此
-0.1显示的价格高 10%。 - 值为
1或更高会使模型免费(或负价),这不是有效折扣。模式会将其作为校验错误拒绝,因此请使用低于1的值。
将 discount_to_user 作为数字发送,而不是字符串。与 cost_usd 字段不同,它不加引号。
8. 模式下载
完整模式以 OpenAPI 3.1 文档提供,其中每个封闭值域(模态类型、定价类型和单位、容量窗口、描述符类型、媒体来源、格式)都作为显式 enum 呈现:
9. 自动充值或发票
OpenRouter 要使用该模型服务提供商,我们必须能够自动为推理付费。这可以通过自动充值或发票完成。
10. 可用性监控与流量路由
OpenRouter 会自动监控模型服务提供商的可靠性,并根据可用性指标调整流量路由。你的端点可用性计算为:成功请求 ÷ 总请求(排除用户错误)。
会影响可用性的错误:
- 身份验证问题(401)
- 支付失败(402)
- 未找到模型(404)
- 所有服务器错误(500+)
- 流中途错误
- 带有错误结束原因的成功请求
不影响可用性的错误:
- 错误请求(400)——用户输入错误
- 载荷过大(413)——用户输入错误
- 速率限制(429)——单独跟踪
- 地理限制(403)——单独跟踪
流量路由阈值:
- 最低数据量:开始计算可用性之前需要 100+ 次请求
- 正常路由:95%+ 可用性
- 降级状态:80–94% 可用性 → 获得较低优先级
- 宕机状态:<80% 可用性 → 仅作为回退使用
该系统确保流量自动流向最可靠的模型服务提供商,同时给临时问题留出恢复时间。
11. 性能指标
OpenRouter 会在每个模型页面上公开跟踪所有模型服务提供商的 TTFT(首 Token 时间)和吞吐量(Token/秒)。
吞吐量计算为:输出 Token ÷ 生成时间,其中生成时间包括获取延迟(从请求到服务器首次响应的时间)、TTFT 和流式传输时间。这意味着你端上的任何排队都会体现在吞吐量指标中。
要保持指标有竞争力:
- 在负载下尽早返回 429,而不是排队请求
- 一旦 Token 可用就立即流式发送
- 如果处理需要时间(例如推理模型),请发送 SSE 注释作为保活,以便我们知道你仍在处理该请求。否则我们可能会因获取超时而取消,并回退到另一个模型服务提供商
12. Auto Exacto:工具调用流量路由
Auto Exacto 是一个路由步骤,会为所有包含工具的请求自动重新排序模型服务提供商。它默认在每个工具调用请求上运行,并可能改变你的端点接收到的工具调用流量。
流量如何受到影响
Auto Exacto 会把工具调用流量转向在工具使用质量信号上表现良好的模型服务提供商。指标强的模型服务提供商会被移到路由顺序的前面,并会收到更多工具调用请求;信号较弱的模型服务提供商会被降低优先级,流量会减少。
非工具调用流量不受 Auto Exacto 影响——它继续遵循标准的按价格加权路由。
排名因素如何确定
Auto Exacto 使用三类信号,全部来自你端点上的真实流量和评测:
- 吞吐量——从实际路由到你端点的请求中实时测得的每秒 Token 数(可在任意模型页面的性能选项卡上看到)。
- 工具调用成功率——你的端点在无错误的情况下完成工具调用的可靠程度(同样可在性能选项卡上看到)。
- 基准数据——我们对模型服务提供商端点运行的内部评测结果。我们正在积极收集这些数据,并将很快在你的模型服务提供商控制台中提供,以便你审查并在自己的环境中运行相同基准。
这些就是你的模型服务提供商控制台中可用的同一批指标。完成接入后,我们的团队可以为你开通访问权限。
降优先级阈值如何工作
吞吐量和工具调用成功率使用中位数 + MAD(中位数绝对偏差)方法,将当前信号值与服务该模型的实时模型服务提供商组进行比较。基准准确率则使用该模型早期基准窗口的历史基线,因此一旦该窗口关闭,其截止值不会随当前对等组移动。
每个信号的敏感度不同:
- 基准准确率——截止值是该模型和基准类型大约前 21 天基准评测的基线:该窗口内各端点分数的中位数减去 2 个标准差(中位数 − 2σ)。每个窗口随该模型和基准类型的第一个合格结果开启。窗口仍在进行时,基线会根据迄今收集到的全部合格结果定期重新计算,因此任何模型服务提供商针对该基准类型的新合格结果都可能移动截止值;窗口关闭后,当前构成的基线不再接受后续基准运行的结果,另一模型服务提供商分数的后续变化也不会移动截止值。分数低于截止值、或完全缺失基准数据的端点会被降低优先级。
- 吞吐量——低于中位数超过 1.5 个标准差的模型服务提供商会被降低优先级。更宽的裕度用于考虑由分时负载模式引起的自然吞吐量波动。
- 工具调用成功率——低于中位数超过 2 个标准差的模型服务提供商会被降低优先级。成功率聚集在接近 100% 处,因此这一更宽的裕度可以避免惩罚正常噪声,同时捕获真正损坏的端点。
实时信号需要至少 4 个模型服务提供商才会计算统计阈值;基准阈值需要适用基线窗口内的 4 个端点。低于适用数量时,不会对该信号应用降优先级。
端点被放入三个层级之一:
- 良好——数据充足且没有低于阈值的信号。这些获得最高路由优先级。
- 数据不足——近期流量不足以评估。这些排在已知良好的模型服务提供商之后,但排在被降低优先级的端点之前。端点至少需要 100 次常规请求(30 分钟窗口)和 200 次工具调用请求(2 小时窗口)才能被评估。
- 已降低优先级——一个或多个信号低于阈值。这些被排到最后路由。
持续的速率限制(429)会减少可用于评估的成功请求量,使我们更难收集足够的基准数据把你的端点放入最高层级。尽早返回 429 仍然优于排队,但在可能的情况下尽量减少速率限制,有助于确保你的端点有足够数据获得公平评估。
如何提升你的排名
要最大化路由到你端点的工具调用流量:
- 保持高工具调用可靠性——确保你的端点始终返回格式正确的工具调用响应。
- 优化吞吐量——尽量减少排队,并在 Token 可用时立即流式发送(见上方的性能指标)。
- 在负载下尽早返回 429——与其排队并降低吞吐量,不如返回速率限制错误,以便我们用另一个模型服务提供商重试,同时保持你的指标健康。
关于 Auto Exacto 的完整面向用户文档,见 Auto Exacto。