跳到主要内容
AIRouter
关于我们
登录免费注册
AIRouter

统一接入全球大模型,按量计费,无最低消费。

support@airouter.hk

产品

  • 模型广场
  • 计费口径
  • 免费开始

开发者

  • 文档
  • 快速开始
  • 服务状态
  • API Key 管理

公司

  • 关于我们
  • 服务条款
  • 隐私政策

支持

  • 帮助中心
  • 登录
  • 进入控制台

© 2026 AIRouter. 保留所有权利。AIRouter 是模型聚合与路由服务,模型能力由各供应商提供。

所有系统运行正常

开发者文档

文档目录

入门

  • 平台介绍
  • 快速开始
  • 鉴权

API 参考

  • 对话补全
  • 图像生成
  • 文本向量化
  • 重排
  • 视频生成
  • 模型与路由

平台机制

  • 计费口径
  • 错误码与排查

入门

  • 平台介绍
  • 快速开始
  • 鉴权

API 参考

  • 对话补全
  • 图像生成
  • 文本向量化
  • 重排
  • 视频生成
  • 模型与路由

平台机制

  • 计费口径
  • 错误码与排查

对话补全

POST /v1/chat/completions —— 提交一段对话,由模型续写下一轮回复。

先理解这个接口#

对话补全接口只做一件事:接收完整的对话内容,由模型续写下一轮回复后返回。该接口不具备记忆能力,服务端不保存任何上下文;因此进行多轮对话时,需要把此前所有轮次连同模型上一次的回复一并重新提交。

对话内容放在 messages 数组里,按时间顺序排列。每条消息有 role 和 content 两个必填字段,role 表明这句话是谁说的。

`role`这句话是谁说的用来做什么
system开发者设定设定角色、语气与行为规则。通常置于数组首位,且仅出现一条
user终端用户实际的提问或指令
assistant模型上一轮的回答多轮对话时,将模型的上一次输出原样回填,模型据此获知自身此前的表述
tool工具执行结果模型要求调用函数后,你把执行结果用这个角色回填

一个三轮对话的 messages:注意 assistant 那条是模型之前说的,由你带回来

json
[  { "role": "system", "content": "你是一名简洁的技术支持助理,只用中文回答。" },  { "role": "user", "content": "我的订单还能退款吗?" },  { "role": "assistant", "content": "可以的,支付后 7 天内都能申请全额退款。" },  { "role": "user", "content": "那退到账要多久?" }]
上下文是你自己维护的
每一轮都要把完整历史重发,所以请求会越来越长,费用也随轮次增长——token 是按每次请求的全量输入计的。长对话建议只保留最近若干轮,或先做一次摘要再继续。

第一次调用#

下面三段代码做同一件事:问一个问题,打印模型的回答。

curl:最小请求

bash
curl https://ogrouter.ai/v1/chat/completions \  -H "Authorization: Bearer $AIROUTER_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "model": "openai/gpt-5.2",    "messages": [      { "role": "user", "content": "用一句话解释什么是向量数据库" }    ]  }'

响应:回答在 choices[0].message.content 里

json
{  "id": "chatcmpl-abc123",  "object": "chat.completion",  "created": 1754126400,  "model": "openai/gpt-5.2",  "choices": [    {      "index": 0,      "message": {        "role": "assistant",        "content": "向量数据库是一种按语义相似度而不是精确匹配来检索数据的存储系统。"      },      "finish_reason": "stop"    }  ],  "usage": {    "prompt_tokens": 21,    "completion_tokens": 28,    "total_tokens": 49  }}

finish_reason 说明模型停止生成的原因:stop 表示正常结束,length 表示达到了 max_tokens 上限(回复被截断,通常需要调高该上限后重试),tool_calls 表示模型请求调用工具。

Python:用官方 openai 库,改 base_url 即可

python
import osfrom openai import OpenAI
client = OpenAI(    api_key=os.environ["AIROUTER_API_KEY"],    base_url="https://ogrouter.ai/v1",)
response = client.chat.completions.create(    model="openai/gpt-5.2",    messages=[        {"role": "system", "content": "你是一名简洁的技术写作者。"},        {"role": "user", "content": "用一句话解释什么是向量数据库"},    ],)
print(response.choices[0].message.content)print(response.usage.total_tokens, "tokens")

Node.js:同样只改 baseURL

javascript
import OpenAI from 'openai';
const client = new OpenAI({  apiKey: process.env.AIROUTER_API_KEY,  baseURL: 'https://ogrouter.ai/v1',});
const response = await client.chat.completions.create({  model: 'openai/gpt-5.2',  messages: [    { role: 'system', content: '你是一名简洁的技术写作者。' },    { role: 'user', content: '用一句话解释什么是向量数据库' },  ],});
console.log(response.choices[0].message.content);

Java(openai-java SDK)

java
import com.openai.client.OpenAIClient;import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.models.chat.completions.ChatCompletion;import com.openai.models.chat.completions.ChatCompletionCreateParams;
OpenAIClient client = OpenAIOkHttpClient.builder()    .baseUrl("https://ogrouter.ai/v1")    .apiKey(System.getenv("AIROUTER_API_KEY"))    .build();
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()    .model("openai/gpt-5.2")    .addSystemMessage("你是一名简洁的技术写作者。")    .addUserMessage("用一句话解释什么是向量数据库")    .build();
ChatCompletion response = client.chat().completions().create(params);System.out.println(response.choices().get(0).message().content().orElse(""));
为什么能直接用 openai 库
本端点的请求与响应格式与业界最通用的对话补全格式一致,因此任何遵循该格式编写的客户端都可以直接指向本平台。你无需了解 OpenAI 本身,将其视为一种数据格式约定即可。

请求字段#

下表逐条说明请求体支持的字段。控制随机性的采样参数(temperature、top_p 等)单独列在下一节。未列出的字段会原样转发给上游。

modelstring必填
模型名。支持别名、:变体 与逗号降级链,语法见 模型与路由。
messagesarray必填
整段对话,按时间顺序排列;角色与多轮写法见上面的"先理解这个接口"。content 允许为 null(工具调用回合的合法形态),会被规范化成空文本部分。
max_tokensinteger
本次生成的输出上限。传了它,预扣的冻结额会更贴近实际支出;不传时按模型的最大输出能力估算,见 计费口径。
streamboolean
true 时返回 text/event-stream,帧序列见下一节。
stream_optionsobject
传 {"include_usage": true} 才会在流的末尾多收到一帧用量统计;不传的话整条流里没有任何用量信息。
tools / tool_choicearray / string
工具调用,透传。parallel_tool_calls 也透传;Anthropic 上游用方向相反的 disable_parallel_tool_use 表达,网关会自动取反。
response_formatobject
结构化输出。是否可用取决于目标端点,可配合 provider.require_parameters 强制只选支持它的线路。
reasoningobject
跨协议统一的思考开关:enabled 打开思考,effort 取 minimal / low / medium / high,max_tokens 给思考预算,exclude 表示照样思考但不返回思考内容。出站时映射成上游各自的字段(Anthropic 的 thinking、OpenAI 的 reasoning_effort);模型不支持时以上游行为为准,要强制只走支持它的线路请配合 provider.require_parameters。
providerobject
路由偏好(本平台扩展):白名单、黑名单、排序、价格上限、区域与合规约束。见 模型与路由。
modelsarray
模型级降级链。它不是 model 里逗号写法的替代品,而是与之合并去重(顺序为 model 的逗号链 → models → provider.models);主模型加兜底最多 4 个,多出来的静默忽略。
transformsarray
为兼容 OpenRouter 保留的字段:会被接收并记录,但当前不会对请求产生任何变换。输入超出上下文窗口时,请自行裁剪内容或改用长上下文模型。

一个带路由约束的请求体

json
{  "model": "anthropic/claude-fable-5",  "messages": [{ "role": "user", "content": "总结这份会议记录" }],  "provider": {    "sort": "price",    "only": ["cl-sp", "cl-of"],    "allow_fallbacks": true,    "max_price": { "prompt": "5.00000000", "completion": "20.00000000" }  }}

采样参数#

模型每生成一个词,实际是在一组候选词上计算概率分布后选取其一。下列参数用于控制这一选取过程,它们均为可选,不传时采用模型自身的默认值。

字段类型作用
temperaturenumber随机性。0 附近近乎确定(同样输入基本给同样输出),越大越发散。事实问答、代码生成用低值;创意写作用高值。这是最常调的一个
top_pnumber另一种收敛方式:只在累计概率达到 p 的候选词集合中选取。0.1 表示仅考虑概率最高的一小部分候选。与 temperature 调整其中之一即可,同时调整两者难以预期其效果
top_kinteger只在概率最高的 k 个候选词里挑。并非所有上游都支持
max_tokensinteger这次最多生成多少 token,是硬上限。达到该上限即截断,finish_reason 为 length
stopstring 或 array遇到这些字符串即停止生成,且停止串本身不会出现在结果中。可用于截断模型的自问自答式续写
seedinteger尽力而为的可复现性:相同输入配合相同 seed 倾向于产生相同输出。上游不保证严格一致,不应将其用作幂等键
frequency_penaltynumber按某个词已出现的次数递增地压低它再次出现的概率,用于抑制重复表述。
presence_penaltynumber只要某个词出现过即压低其概率,与出现次数无关。用于促使模型转换话题
repetition_penaltynumber开源模型常用的另一种重复抑制参数,作用与上述两个参数重叠
logit_biasobjecttoken 到偏置值的映射,直接抬高或压低特定 token 的概率。用来强制避开或倾向某些词
logprobsboolean返回每个输出 token 的对数概率,用于做置信度判断
并非每个参数在每条线路上都生效
同一个模型名在不同上游的实现里对参数的支持程度不同,不认识的参数通常被上游静默忽略而不是报错。要强制只走支持某参数的线路,用 provider.require_parameters,见模型与路由。

流式输出#

每一帧的格式是 data: <JSON>,JSON 结构为 chat.completion.chunk,流以 data: [DONE] 结束。[DONE] 不是合法 JSON,客户端必须先判断这个哨兵值再解析。

帧说明
角色帧choices[0].delta = {"role":"assistant"},只发一次。
内容增量delta.content 是文本片段;开启思考时会先发若干 delta.reasoning_content。
工具调用增量delta.tool_calls[].index 从 0 递增,同一个工具调用的 index 在整个流里稳定不变;function.arguments 是分片的 JSON 字符串,需按 index 拼接后再解析。
结束帧finish_reason 非空,delta 为空对象。
用量帧仅当 stream_options.include_usage 为 true:choices 为空数组且带 usage。
[DONE]结束哨兵。
流中错误必须逐帧检查
已经开始输出后才发生的错误无法再改 HTTP 状态码(它已经是 200)。此时网关会发一帧带 error 字段的数据、紧接着 [DONE]。客户端如果不检查每帧是否含 error,会把失败请求当成正常结束。

典型的一段流(: ping 是 SSE 注释行,用于防止中间层超时,标准解析器会忽略)

plain
data: {"choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}data: {"choices":[{"index":0,"delta":{"content":"维多利亚港的风"},"finish_reason":null}]}: pingdata: {"choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}data: {"choices":[],"usage":{"prompt_tokens":26,"completion_tokens":48,"total_tokens":74}}data: [DONE]
上游未返回用量时,平台会补齐一份估算值,usage 帧照常发送,因此用量统计逻辑不必按上游分别处理。估算标记不在响应体内:非流式请读响应头 X-AiRouter-Usage-Estimated,流式请在 调用日志 中查看——响应头在流开始时已经发出。

Python:逐字打印,帧里没有 content 的时候要跳过

python
import osfrom openai import OpenAI
client = OpenAI(api_key=os.environ["AIROUTER_API_KEY"], base_url="https://ogrouter.ai/v1")
stream = client.chat.completions.create(    model="openai/gpt-5.2",    messages=[{"role": "user", "content": "写一首关于香港雨季的短诗"}],    stream=True,    stream_options={"include_usage": True},  # 不传这个就收不到用量帧)
for chunk in stream:    # 用量帧的 choices 是空数组,直接访问 [0] 会抛 IndexError    if not chunk.choices:        if chunk.usage:            print(f"\n\n共 {chunk.usage.total_tokens} tokens")        continue    delta = chunk.choices[0].delta.content    if delta:        print(delta, end="", flush=True)

Node.js:同样的循环

javascript
import OpenAI from 'openai';
const client = new OpenAI({  apiKey: process.env.AIROUTER_API_KEY,  baseURL: 'https://ogrouter.ai/v1',});
const stream = await client.chat.completions.create({  model: 'openai/gpt-5.2',  messages: [{ role: 'user', content: '写一首关于香港雨季的短诗' }],  stream: true,  stream_options: { include_usage: true },});
for await (const chunk of stream) {  const delta = chunk.choices[0]?.delta?.content;  if (delta) process.stdout.write(delta);  if (chunk.usage) console.log(`\n\n共 ${chunk.usage.total_tokens} tokens`);}

Java:逐字打印,用量帧要单独处理

java
import com.openai.core.http.StreamResponse;import com.openai.models.chat.completions.ChatCompletionChunk;import com.openai.models.chat.completions.ChatCompletionCreateParams;import com.openai.models.chat.completions.ChatCompletionStreamOptions;
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()    .model("openai/gpt-5.2")    .addUserMessage("写一首关于香港雨季的短诗")    // 不设 includeUsage 就收不到用量帧    .streamOptions(ChatCompletionStreamOptions.builder().includeUsage(true).build())    .build();
try (StreamResponse<ChatCompletionChunk> stream =        client.chat().completions().createStreaming(params)) {    stream.stream().forEach(chunk -> {        // 用量帧的 choices 是空数组,先判空再取下标        if (chunk.choices().isEmpty()) {            chunk.usage().ifPresent(u ->                System.out.printf("%n%n共 %d tokens%n", u.totalTokens()));            return;        }        chunk.choices().get(0).delta().content().ifPresent(System.out::print);    });}

用量口径#

  • 非流式响应总是带 usage;流式默认不带,需要显式传 stream_options.include_usage。
  • prompt_tokens 是全部输入 token,包含缓存读与缓存写部分;缓存读在 prompt_tokens_details.cached_tokens,缓存写在 cache_creation_input_tokens。按标准输入价计费的是三者相减后的余量。
  • completion_tokens 只含可见输出,不含思考 token;思考量在 completion_tokens_details.reasoning_tokens 里单独给出、单独计费。
  • 用量帧只报 token,不含金额。非流式的费用在响应头,流式的费用在 调用日志。

与 OpenAI 的已知差异#

字段差异
n原样透传给上游,网关不做拦截。是否真正返回多个候选取决于目标端点;计费按上游报告的总用量计算,因此 n 越大费用越高。
logit_bias / logprobs取决于目标端点是否支持;不支持时按 provider.require_parameters 决定是忽略还是换一条线路。
service_tier / store按白名单透传给 OpenAI 兼容上游,平台不做任何处理。
metadata会记录到平台请求日志(app_id / app_title / project_id 会被识别出来),但不透传给上游。
/v1/completions提供该端点,但仅为兼容存量 SDK:prompt 会被包装成一条 user 消息,响应按 legacy 形状返回(object 为 text_completion,正文在 choices[].text)。echo / suffix / best_of 与批量 prompt 一律返回 invalid_request,不会被静默忽略。新项目请直接使用 /v1/chat/completions。
响应体多一个字段非流式响应带 provider,值是命中的分组 code(与 X-AiRouter-Group 一致)。OpenAI 没有这个字段,SDK 会忽略它。

Anthropic 协议#

除上述格式外,网关还提供 POST /v1/messages,遵循 Anthropic 的 Messages 格式——这是另一套写法不同、能力相当的对话协议:system 不放在 messages 内,而是作为独立的顶层字段;返回正文是 content 数组而非单个字符串。若现有代码使用 Anthropic 官方 SDK,指向本平台即可运行;否则使用上述 /v1/chat/completions 即可。两条端点背后是同一批模型。

POST /v1/messages 与 Anthropic Messages API 兼容:model 一样支持别名、:变体 与逗号降级链,流式天然带用量(message_start / message_delta 里就有),不需要 include_usage。

curl:Anthropic 格式的同一个问题

bash
curl https://ogrouter.ai/v1/messages \  -H "X-Api-Key: $AIROUTER_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "model": "anthropic/claude-fable-5",    "max_tokens": 256,    "system": "你是一名简洁的技术写作者。",    "messages": [      { "role": "user", "content": "用一句话解释什么是向量数据库" }    ]  }'
路由扩展字段在这条端点上不生效
provider / models / transforms 这些扩展只在 OpenAI 协议的请求体里被识别。写在 /v1/messages 上会被当成未知字段原样转发给上游,通常会被上游拒绝并返回 400。要用路由偏好就走 /v1/chat/completions,或者把降级链写进 model 的逗号形式。
  • anthropic-version 无需传递:网关在出站时统一填入 2023-06-01。
  • anthropic-beta 目前不转发;客户端的自定义请求头不会传递到上游。
  • 错误封装是 Anthropic 形状,没有 code 字段,分支要靠 HTTP 状态与 error.type,见 错误码。
上一篇鉴权下一篇图像生成

本页目录

  • 先理解这个接口
  • 第一次调用
  • 请求字段
  • 采样参数
  • 流式输出
  • 用量口径
  • 与 OpenAI 的已知差异
  • Anthropic 协议