- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 概览
- 1. 为什么需要一层网关
- 2. 核心概念
- 3. 申请密钥与第一个 curl 请求
- 4. OpenAI SDK 无缝替换
- 5. 模型选择与路由
- 6. 流式输出 / 工具调用 / 结构化输出
- 7. 归属请求头与用量查询
- 8. 实务技巧与注意事项
- 参考资料
概览
一旦开始同时使用多个 LLM,很快就会撞上同一个问题。你想混用 OpenAI、Anthropic、Google、Meta 的模型,但每家供应商都有各自的 SDK、各自的认证方式、各自的计费、各自的请求 schema。换一个模型就得重写客户端代码,而只要有一家供应商宕机,服务就跟着停摆。
OpenRouter 把这一层收拾干净了。一个端点、一个 API 密钥,就能接入 60+ 家供应商的 300+ 个(最多约 500 个)模型,接口与 OpenAI API 完全兼容。也就是说,如果你已经在用 OpenAI SDK,只需要换掉 base_url 和 api_key,就能原样调用 Claude、Gemini、Llama。
本文依次讲清楚为什么要把 OpenRouter 当作网关来用、核心概念是什么,以及从申请密钥到路由/回退/流式输出,实际接入的每一步该怎么做。
1. 为什么需要一层网关
LLM 应用刚起步时,单个模型看起来就够用了。但一旦进入生产环境,就会冒出一些共同的需求。
- 不同任务适合不同模型。摘要想用便宜的模型,复杂推理想用前沿模型,二者要能分开。
- 不想被锁死在一家供应商上。一旦涨价或出故障,就得能迁到别的模型。
- 想把计费和用量汇总在一处看。每家供应商都单开一个仪表盘,效率太低。
网关把这个问题从应用代码里剥离出去。客户端始终请求同一个端点,换模型这件事变成只替换一个字符串(model 字段)。供应商路由、回退、计费汇总都交给网关处理。
| 直连方式 | OpenRouter 网关 |
|---|---|
| 每家供应商的 SDK/认证/schema 都不同 | 一个端点、一个密钥、兼容 OpenAI 的 schema |
| 换模型要改代码 | 只替换 model 字符串 |
| 每家供应商单独开计费账户 | 用一份余额统一计费 |
| 故障时要自己实现回退 | 通过 models 数组 / provider 路由自动回退 |
2. 核心概念
一个端点
所有调用都打向同一个 base URL。
https://openrouter.ai/api/v1
聊天补全(chat completions)请求打到 https://openrouter.ai/api/v1/chat/completions。认证使用标准的 Bearer token 请求头。
Authorization: Bearer YOUR_OPENROUTER_API_KEY
模型 ID
模型用 provider/model 格式的字符串指定。常见例子如下。
| 模型 ID | 说明 |
|---|---|
openai/gpt-4o | OpenAI GPT-4o |
anthropic/claude-3.5-sonnet | Anthropic Claude 3.5 Sonnet |
google/gemini-2.0-flash-exp | Google Gemini 2.0 Flash(实验版) |
meta-llama/llama-3.3-70b-instruct | Meta Llama 3.3 70B Instruct |
openrouter/auto | 自动路由器 — 由 OpenRouter 根据请求内容挑选模型 |
免费变体的 ID 末尾带 :free。完整目录以及每个模型的价格/上下文长度可以在模型页面查到,程序化查询则用 /api/v1/models 端点。
余额与免费额度
免费额度提供每天约 50 次免费请求,以及 25 个以上的免费模型(ID 以 :free 结尾)。付费使用按余额、按量计费,按实际执行的模型的 token 用量计费。充值余额时会收取约 5.5% 的小额手续费,但调用本身的成本,遵循的是实际处理该请求的模型的单价。
3. 申请密钥与第一个 curl 请求
先在 openrouter.ai/keys 申请 API 密钥。把密钥放进环境变量会比较方便。
export OPENROUTER_API_KEY="sk-or-你申请到的密钥"
现在用 curl 发一个最简单的请求试试。
curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "openai/gpt-4o", "messages": [{"role":"user","content":"Hello"}] }'
返回的响应结构与 OpenAI 的 chat completions 完全一致。想换模型的话,只需把 model 值换成 anthropic/claude-3.5-sonnet 或 google/gemini-2.0-flash-exp,请求的其余部分保持不变。
4. OpenAI SDK 无缝替换
"OpenRouter 兼容 OpenAI" 这句话的实际含义是:继续用官方 OpenAI SDK,只是把接入点指向 OpenRouter。
Python
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key="YOUR_OPENROUTER_API_KEY",
)
completion = client.chat.completions.create(
model="anthropic/claude-3.5-sonnet",
messages=[
{"role": "user", "content": "用一句话说明网关为什么有用"},
],
)
print(completion.choices[0].message.content)
在 OpenAI(...) 构造函数里,只需把 base_url 和 api_key 换成 OpenRouter 的值,之后 client.chat.completions.create(...) 的调用方式和平时完全一样。响应正文从 completion.choices[0].message.content 读取。
TypeScript
TypeScript 也是同样的思路。给 openai npm 客户端指定 baseURL 和 apiKey 即可。
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://openrouter.ai/api/v1',
apiKey: process.env.OPENROUTER_API_KEY,
});
const completion = await client.chat.completions.create({
model: 'anthropic/claude-3.5-sonnet',
messages: [{ role: 'user', content: 'Hello' }],
});
console.log(completion.choices[0].message.content);
不用 SDK,直接用 fetch 发 POST 也可以。只要端点和请求头对得上,行为完全一致。
const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Hello' }],
}),
});
const data = await res.json();
console.log(data.choices[0].message.content);
5. 模型选择与路由
供应商路由覆盖
同一个模型有时由多家供应商提供。这种情况下,OpenRouter 默认会根据价格、延迟、可用性自动选择供应商。想强制指定某种策略,就在请求里加入 provider 字段来覆盖默认行为。比如可以指定供应商优先级(order)、是否允许回退(allow_fallbacks)、排序标准(sort)等。
{
"model": "meta-llama/llama-3.3-70b-instruct",
"messages": [{ "role": "user", "content": "Hello" }],
"provider": {
"sort": "throughput",
"allow_fallbacks": true
}
}
模型级回退 — models 数组
与供应商路由分开,还可以指定按顺序依次尝试多个模型的回退。传入 models 数组后,会从头开始依次尝试。
{
"models": [
"openai/gpt-4o",
"anthropic/claude-3.5-sonnet",
"meta-llama/llama-3.3-70b-instruct"
],
"messages": [{ "role": "user", "content": "Hello" }]
}
回退会在触及速率限制、停机、上下文长度超限、内容审核错误等情况下触发。计费方式是要点所在。即便列出了多个模型,也只会对实际执行并生成响应的那个模型的 token 计费。尝试过但失败的模型不产生费用。
自动路由器 — openrouter/auto
当自己选模型比较为难时,可以把 model 值设为 openrouter/auto。OpenRouter 会根据请求内容路由到合适的模型。这在早期原型验证阶段,或者只是需要"一个能用的模型"的时候很有用。
6. 流式输出 / 工具调用 / 结构化输出
这三个功能的工作方式都和 OpenAI API 一致。
流式输出
传入 stream=True(TypeScript 里是 stream: true)就能以分块方式接收响应。
stream = client.chat.completions.create(
model="openai/gpt-4o",
messages=[{"role": "user", "content": "写一首短诗"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="")
工具 / 函数调用
工具(函数)调用同样沿用 OpenAI 的 schema。把函数定义放进 tools 数组,处理模型返回的 tool_calls,再把结果作为消息喂回去。
{
"model": "openai/gpt-4o",
"messages": [{ "role": "user", "content": "告诉我首尔的天气" }],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "返回某个城市的当前天气",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
}
]
}
结构化输出
也支持基于 JSON schema 的结构化输出。在 response_format 里指定 json_schema,就能强制响应遵循该 schema。
{
"model": "openai/gpt-4o",
"messages": [{ "role": "user", "content": "生成一个示例用户" }],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "user",
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" }
},
"required": ["name", "age"]
}
}
}
}
7. 归属请求头与用量查询
OpenRouter 支持可选的归属(attribution)请求头,用于 openrouter.ai 的排行榜(哪个应用在多用哪个模型)。这不是必填项,填了就能让自己的应用出现在排行榜上。
HTTP-Referer— 自己站点的 URLX-Title— 自己应用的名称
在 OpenAI SDK 里,这些请求头作为默认请求头传入。Python 用 default_headers,JavaScript 用 defaultHeaders。
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key="YOUR_OPENROUTER_API_KEY",
default_headers={
"HTTP-Referer": "https://your-site.example",
"X-Title": "My App",
},
)
const client = new OpenAI({
baseURL: 'https://openrouter.ai/api/v1',
apiKey: process.env.OPENROUTER_API_KEY,
defaultHeaders: {
'HTTP-Referer': 'https://your-site.example',
'X-Title': 'My App',
},
});
可用模型列表及其元数据通过 /api/v1/models 端点查询。
curl https://openrouter.ai/api/v1/models \
-H "Authorization: Bearer $OPENROUTER_API_KEY"
8. 实务技巧与注意事项
- 成本始终遵循实际执行的下层模型的单价。使用
openrouter/auto或models回退时,要记住单价会随实际执行的模型而变化。 :free模型免费,但速率限制较低。如果生产流量完全依赖免费模型,很快就会撞上限额。更适合用在原型验证或低负载场景。- API 密钥务必放在服务端。一旦在浏览器打包产物或客户端代码里暴露密钥,它就会被直接窃取。如果必须从前端发起调用,就在前面架一层自己的后端做代理,再由后端调用 OpenRouter。
- 换模型时响应 schema 依然保持兼容 OpenAI,不需要为每个模型重写解析代码。不过工具调用、结构化输出的支持程度可能因模型而异,切换到新模型时要实际验证该功能是否可用。
- 回退数组能提高稳定性,但如果把昂贵的模型放在末尾,故障发生时成本可能会飙升。排列回退顺序时,不仅要考虑可用性,也要把单价一并纳入考量。