Helicone 模型注册表中 OpenRouter 兜底 Endpoint 接入指南:最坏情况定价与 5.5% 加价计算
【免费下载链接】helicone🧊 Open source LLM observability platform. One line of code to monitor, evaluate, and experiment. YC W23 🍓项目地址: https://gitcode.com/GitHub_Trending/he/helicone
导读
本文是 Helicone 开源 LLM 可观测性平台(packages/cost 模型注册表)内部运维指南的技术展开,讲解如何为模型文件添加OpenRouter 兜底(fallback)Endpoint。核心思路是:OpenRouter 作为动态路由聚合商,同一模型在不同上游供应商的价格各不相同,因此需要先找出每个模型最贵(worst-case)的端点价格,再叠加 OpenRouter 的5.5% 服务费作为托管计费(escrow)占位价。读完本文,你将掌握从 OpenRouter API 查询模型元数据、计算最坏情况价格、以严格注释格式写入endpoints.ts的完整实战流程。
OpenRouter 在路由优先级中的定位
在 Helicone 的模型注册表(Model Registry v2)中,请求路由遵循"BYOK 优先、PTB 兜底"的两阶段策略(详见 packages/cost/FLOWS.md):
- Phase 1(BYOK,Bring Your Own Key):尝试用户自带 API Key 的全部端点,按成本升序排序;
- Phase 2(PTB,Pass-Through Billing):尝试 Helicone 托管 Key 的全部端点,按定价升序排序。
OpenRouter 在这个体系中扮演通用兜底供应商角色,其priority取值为3(低于 BYOK=1 与 PTB=2),意味着在常规 BYOK / PTB 端点都失败后才被尝试。因为 OpenRouter 本身不直接拥有模型,而是动态把请求路由到不同上游供应商(Cerebras、SambaNova、Google 等),这些供应商的单价差异可能很大,所以必须为托管计费场景预留足够的 escrow 金额——这正是本文要解决的"最坏情况定价"问题。
该优先级字段在 packages/cost/models/types.ts 的EndpointConfig/ModelProviderConfig接口中均有定义(priority?: number,注释明确"Lower number = higher priority")。
Step 1:查找 OpenRouter 模型 ID
首先确认目标模型是否被 OpenRouter 支持。调用其公开模型列表接口,按模型名模糊过滤:
# 将 MODEL_NAME 替换为目标模型(如 gpt-4o、claude、qwen) curl -s "https://openrouter.ai/api/v1/models" | \ python3 -c "import json; import sys; data = json.load(sys.stdin); \ models = [m for m in data['data'] if 'MODEL_NAME' in m['id'].lower()]; \ for m in models[:10]: print(f\"{m['id']}: {m.get('name', 'N/A')}\")"以 qwen 系列为例:
curl -s "https://openrouter.ai/api/v1/models" | \ python3 -c "import json; import sys; data = json.load(sys.stdin); \ models = [m for m in data['data'] if 'qwen' in m['id'].lower()]; \ for m in models[:5]: print(f\"{m['id']}: {m.get('name', 'N/A')}\")"输出中的id(如qwen/qwen3-32b)即为后面写入endpoints.ts的providerModelId取值。注意:并不是所有模型都能在 OpenRouter 上找到,找不到的模型应跳过,不要强行添加(见文末"注意事项"第 5 条)。
Step 2:获取上下文长度与最大完成 Token 数
拿到模型 ID 后,需要同时读取context_length(上下文长度)和max_completion_tokens(最大完成 token 数):
# 将 MODEL_ID 替换为实际模型 ID(如 qwen/qwen3-32b) curl -s "https://openrouter.ai/api/v1/models" | \ python3 -c "import json; import sys; data = json.load(sys.stdin); \ for model in data['data']: if model['id'] == 'MODEL_ID': print(f\"Model: {model['id']}\") print(f\"Context length: {model.get('context_length', 'Not specified')}\") print(f\"Max completion tokens: {model.get('top_provider', {}).get('max_completion_tokens', 'Not specified')}\") break"IMPORTANT:OpenRouter 返回的
max_completion_tokens可能不等于context_length,两者必须分别核对。例如在仓库实测数据中,qwen3-32b:groq的contextLength为 131_072 而maxCompletionTokens仅为 40_960(见 packages/cost/models/authors/alibaba/qwen3/endpoints.ts)。对 OpenRouter 兜底端点,指南要求使用模型真实的上下文长度,而不是取端点的最大值。
Step 3:获取端点定价信息
通过 OpenRouter 的 endpoints 接口拉取该模型在所有上游供应商的定价,并排序找出最贵的一端:
# 将 MODEL_ID 替换为实际模型 ID(如 openai/gpt-4o) curl -s "https://openrouter.ai/api/v1/models/MODEL_ID/endpoints" | \ python3 -c " import json; import sys data = json.load(sys.stdin) endpoints = data['data']['endpoints'] # 展示所有供应商定价(按 prompt 单价降序排序) print('All endpoint pricing (sorted by prompt cost):') sorted_endpoints = sorted(endpoints, key=lambda e: float(e['pricing']['prompt']), reverse=True) for e in sorted_endpoints[:5]: prompt = float(e['pricing']['prompt']) completion = float(e['pricing']['completion']) print(f\"{e['provider_name']}: prompt=\${prompt:.10f} (\${prompt*1000000:.2f}/1M), completion=\${completion:.10f} (\${completion*1000000:.2f}/1M)\") "注意这里的价格单位:OpenRouter 返回的是每 token单价(如0.0000004),脚本乘以1_000_000换算为每百万 token 价格($0.40/1M),便于与各供应商官网标价对照。
Step 4:计算最坏情况定价并叠加 5.5% 加价
下面的脚本一次性完成三件事:找出 prompt / completion 的最贵单价、列出持有该价格的供应商名称、并计算 OpenRouter 加价后的最终占位价:
# 将 MODEL_ID 替换为目标模型(如 qwen/qwen3-32b) curl -s "https://openrouter.ai/api/v1/models/MODEL_ID/endpoints" | \ python3 -c " import json; import sys data = json.load(sys.stdin) endpoints = data['data']['endpoints'] # 找出最坏情况定价 max_prompt = max(float(e['pricing']['prompt']) for e in endpoints) max_completion = max(float(e['pricing']['completion']) for e in endpoints) # 找出哪些供应商持有最坏情况定价 prompt_providers = [e['provider_name'] for e in endpoints if float(e['pricing']['prompt']) == max_prompt] completion_providers = [e['provider_name'] for e in endpoints if float(e['pricing']['completion']) == max_completion] # 计算 OpenRouter 定价(5.5% 加价) or_prompt = max_prompt * 1.055 or_completion = max_completion * 1.055 print(f'Model: {data[\"data\"][\"id\"]}') print(f'\\nWorst-case prompt: \${max_prompt:.10f} (\${max_prompt*1000000:.2f}/1M)') print(f'Providers: {', '.join(prompt_providers[:3])}') print(f'\\nWorst-case completion: \${max_completion:.10f} (\${max_completion*1000000:.2f}/1M)') print(f'Providers: {', '.join(completion_providers[:3])}') print(f'\\nOpenRouter pricing with 5.5% markup:') print(f'Input: {or_prompt:.10f} (\${or_prompt*1000000:.2f}/1M)') print(f'Output: {or_completion:.10f} (\${or_completion*1000000:.2f}/1M)') "关键计算规则:最终占位价 = 最贵端点单价 × 1.055。1.055即 OpenRouter 的 5.5% 服务费系数。这部分金额对应 Helicone 的托管计费 escrow 预留——见 packages/cost/README.md 中关于 PTB(Helicone 负责计费,要求ptbEnabled: true)的说明。
Step 5:写入 Endpoint 文件
将计算结果写入该模型作者目录下的endpoints.ts,端点键格式为"模型名:openrouter",并严格遵循注释格式(后续步骤详述):
"model-name:openrouter": { providerModelId: "provider/model-name", // 来自 Step 1 provider: "openrouter", author: "author-name", // 与文件内已有端点保持一致 pricing: [ { threshold: 0, input: 0.000000422, // $0.42/1M - worst-case: $0.40/1M (ProviderName) * 1.055 output: 0.000000844, // $0.84/1M - worst-case: $0.80/1M (ProviderName) * 1.055 }, ], contextLength: 40_960, // 来自 Step 2 - 使用模型真实上下文长度 maxCompletionTokens: 40_960, // 通常与 contextLength 相同 supportedParameters: [ // 从相近端点复制,或使用 OpenRouter 通用参数 "frequency_penalty", "logprobs", "max_tokens", "presence_penalty", "seed", "stop", "temperature", "tool_choice", "tools", "top_logprobs", "top_p", ], ptbEnabled: true, // IMPORTANT: 兜底端点必须保持 true priority: 3, // 兜底优先级(BYOK=1 与 PTB=2 之后) endpointConfigs: { "*": {}, }, },字段说明与源码对应
上述字段均可对照 packages/cost/models/types.ts 中的类型定义理解其语义与约束:
| 字段 | 类型定义 | 说明 |
|---|---|---|
providerModelId | string | OpenRouter 侧的模型 ID(Step 1 查得) |
provider | ModelProviderName | 固定为"openrouter" |
author | AuthorName | 模型作者,如"alibaba"、"google",须与同文件其他端点一致 |
pricing | ModelPricing[] | threshold为上下文长度阈值(0 表示全量),input/output为每 token 单价 |
contextLength/maxCompletionTokens | number | Step 2 查得的真实值 |
supportedParameters | StandardParameter[] | 允许透传的请求参数白名单 |
ptbEnabled | boolean | 托管计费开关,兜底端点必须为true |
priority | number? | 路由优先级,数值越小越优先;OpenRouter 取 3 |
endpointConfigs | Record<string, EndpointConfig> | 部署级覆盖配置,通配"*"为空对象 |
在仓库中可找到多个遵循此模式的真实落地示例,例如 packages/cost/models/authors/alibaba/qwen3/endpoints.ts 中的"qwen3-32b:openrouter"端点,注释为// $0.42/1M - worst-case: $0.40/1M (Cerebras/SambaNova) * 1.055,与本文示例完全一致;又如 packages/cost/models/authors/google/gemini-2.5-pro/endpoints.ts 中的"gemini-2.5-pro:openrouter"端点,注释为// $2.64/1M - worst-case: $2.50/1M (Google >200K) * 1.055,它正是采用了分级定价中更高档位价格的实例。
注释格式规则(必须严格遵守)
pricing中每行的行内注释是后续维护与审计的唯一溯源依据,格式如下:
input: 0.000000422, // $X.XX/1M - worst-case: $Y.YY/1M (Provider1/Provider2) * 1.055 output: 0.000000844, // $X.XX/1M - worst-case: $Y.YY/1M (Provider1/Provider2) * 1.055其中:
- $X.XX/1M= 叠加 5.5% 加价后的最终每百万 token 价格;
- $Y.YY/1M= 原始最坏情况每百万 token 价格;
- (Provider1/Provider2)= 持有最坏情况定价的实际供应商名称(最多列 2~3 个);
- * 1.055= 加价系数,指明计算来源。
完整实战示例:接入 qwen3-32b
将上文四个步骤串起来,完整跑一遍qwen/qwen3-32b的接入流程:
# 1. 查找模型 curl -s "https://openrouter.ai/api/v1/models" | grep -i "qwen3-32b" # 输出: "id": "qwen/qwen3-32b" # 2. 获取上下文长度 curl -s "https://openrouter.ai/api/v1/models" | \ python3 -c "import json; import sys; data = json.load(sys.stdin); \ for m in data['data']: if m['id'] == 'qwen/qwen3-32b': print(f\"Context: {m.get('context_length')}\")" # 输出: Context: 40960 # 3. 获取最坏情况定价 curl -s "https://openrouter.ai/api/v1/models/qwen/qwen3-32b/endpoints" | \ python3 -c " import json; import sys data = json.load(sys.stdin) endpoints = data['data']['endpoints'] sorted_by_prompt = sorted(endpoints, key=lambda e: float(e['pricing']['prompt']), reverse=True) print('Top 3 most expensive (by prompt):') for e in sorted_by_prompt[:3]: print(f\"{e['provider_name']}: \${float(e['pricing']['prompt'])*1000000:.2f}/1M prompt, \${float(e['pricing']['completion'])*1000000:.2f}/1M completion\") " # 输出: # Cerebras: $0.40/1M prompt, $0.80/1M completion # SambaNova: $0.40/1M prompt, $0.80/1M completion计算:最贵 prompt 单价 $0.40/1M × 1.055 ≈ $0.422/1M;最贵 completion 单价 $0.80/1M × 1.055 ≈ $0.844/1M。换算为每 token 即为0.000000422与0.000000844。
最终写入 packages/cost/models/authors/alibaba/qwen3/endpoints.ts 的完整端点(与仓库中实际存在的内容一致):
"qwen3-32b:openrouter": { providerModelId: "qwen/qwen3-32b", provider: "openrouter", author: "alibaba", pricing: [ { threshold: 0, input: 0.000000422, // $0.42/1M - worst-case: $0.40/1M (Cerebras/SambaNova) * 1.055 output: 0.000000844, // $0.84/1M - worst-case: $0.80/1M (Cerebras/SambaNova) * 1.055 }, ], contextLength: 40_960, maxCompletionTokens: 40_960, supportedParameters: [ "frequency_penalty", "logprobs", "max_tokens", "presence_penalty", "seed", "stop", "temperature", "tool_choice", "tools", "top_logprobs", "top_p", ], ptbEnabled: true, priority: 3, endpointConfigs: { "*": {}, }, },关键注意事项
- 动态定价:写入文件的价格只是 escrow 的占位值。真实成本以 OpenRouter 响应体中的
usage.cost字段为准,接入后实际计费不会被占位价锁死。 - 上下文长度:使用 models API 返回的模型真实
context_length,不要取 endpoints 接口的最大值。 - ptbEnabled:OpenRouter 兜底端点始终设为
true,否则无法参与 Helicone 的托管计费链路。 - 供应商名称:注释中列出持有最坏情况定价的实际供应商(最多 2~3 个),便于日后价格变动时定位出处。
- 模型可用性:并非所有模型都上架 OpenRouter。若查询不到该模型,直接跳过,不要为其添加 OpenRouter 端点。
- 分级定价(Tiered Pricing):部分模型按上下文长度分档计价(典型如 Google Gemini 系列,见 packages/cost/models/authors/google/gemini-2.5-pro/endpoints.ts 中
threshold: 200000的第二档价格)。OpenRouter 可能只上报基础档价格,此时应:- 回到原供应商的 endpoint 文件查看是否存在多个
pricing阈值; - 取最高档价格作为最坏情况 escrow 计算基准;
- 示例:Gemini-2.5-pro 在 <200K token 时为 $1.25/1M,在 >200K token 时为 $2.50/1M,OpenRouter 兜底端点应取后者(仓库中实际写入
input: 0.00000264,即 $2.50/1M × 1.055); - 始终使用更高档位,确保 escrow 充足。
- 回到原供应商的 endpoint 文件查看是否存在多个
Troubleshooting
症状 1:价格看起来异常(如 $0.00/1M)
依次排查:
- 模型 ID 是否正确;
- endpoints API 是否真的返回了数据;
- 直接用原始 curl 命令查看响应原文,确认字段路径与数据结构。
症状 2:供应商名称显示为 "Unknown" 或空白
通常是float()转换失败导致。此时不要依赖数值比较,直接改用 JSON 中的字符串值参与判断与输出。
小结
OpenRouter 兜底端点的核心是一套"先探价、再取最坏、后加价"的可复现流程:通过 models 与 endpoints 两个公开 API 拿到模型元数据与全量供应商定价,取 prompt / completion 各自最贵档位乘以 1.055,按严格注释格式写入endpoints.ts,并保证ptbEnabled: true、priority: 3。这样既保证了托管计费 escrow 的充足性,又把真实计费交还给 OpenRouter 响应的usage.cost,实现了"占位保守、实算精确"的平衡。仓库中qwen3-32b、gemini-2.5-pro等端点是该流程的现成范例,新增模型时可对照 packages/cost/models/authors 目录下的既有实现快速上手。
【免费下载链接】helicone🧊 Open source LLM observability platform. One line of code to monitor, evaluate, and experiment. YC W23 🍓项目地址: https://gitcode.com/GitHub_Trending/he/helicone
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考