对话补全
POST /v1/chat/completions 的字段处理、流式响应、思考过程、工具调用、超时与中途断开的计费。
更新于 2026-10-24·阅读约 10 分钟
httpPOST https://api.scirouter.cn/v1/chat/completions请求与响应格式与 OpenAI Chat Completions 一致。字段语义以 OpenAI 文档为准,下文只列平台的处理方式。
请求
#json{
"model": "YOUR_MODEL_ID",
"messages": [
{ "role": "system", "content": "你是一名结构生物学助手。" },
{ "role": "user", "content": "帮我判断这段序列的二级结构倾向:MKTAYIAKQR…" }
],
"max_tokens": 1024,
"temperature": 0.3,
"stream": false
}| 字段 | 必填 | 平台的处理 |
|---|---|---|
model | 是 | 模型 id,见模型列表。模型不可调用时的错误见错误 |
messages | 是 | 不能为空数组,原样转给上游。助手消息上可带上一轮响应中的 thinking_blocks,平台原样接收,见带签名的思考块 |
max_tokens | 否 | 正整数。超限、未填写与上下文窗口的处理见 max_tokens |
max_completion_tokens | 否 | max_tokens 的新名称。两者都提供时,平台的校验与预扣以 max_tokens 为准,两个字段均原样转给上游;超限报错时 param 为 max_tokens |
temperature / top_p | 否 | 按模型的请求规则处理:超出范围的值夹到范围内,模型不接受采样参数时去掉,均在响应头 X-SciRouter-Param-Actions 中留痕;其他情况原样转给上游 |
stop | 否 | 字符串或字符串数组,其他类型返回 400 |
stream | 否 | 见流式响应 |
stream_options.include_usage | 否 | 流式时末尾多一个带 usage 的分片(choices 通常为空)。未设置或为 false 时平台去掉该分片 |
tools / tool_choice | 否 | 见工具调用。type: "mcp"、server_label: "scirouter" 的项是平台托管工具,由平台执行,见 MCP 与托管工具 |
metadata / user | 否 | 调用方的归因标签,不转给上游,见可观测性 |
scirouter | 否 | 顶层扩展字段,只接受 max_tool_rounds(托管工具的轮数,1–30),其他键返回 400。不转给上游 |
| 其他字段 | 否 | 按参数如何被处理的登记表分类处理 |
其他字段的处理:
| 类别 | 示例 | 处理 |
|---|---|---|
| 提示类 | seed、惩罚项、reasoning_effort 等 | 无法带到线路上时去掉并留痕 |
| 契约类 | response_format、n、logprobs 等 | 依次尝试翻译、模拟、换线路,均不可行时返回 400 unsupported_param |
| 计价类 | web_search_options | 返回 400 |
| 不在登记表中的专有参数 | — | 走 OpenAI 兼容入口时原样带上,走其他入口时去掉并留痕,见多厂商差异 |
请求体上限默认为 4 MB,超过时返回 413 payload_too_large。
max_tokens
| 情况 | 平台的处理 |
|---|---|
| 超过模型或套餐的单次上限 | 返回 400,details.limit 为上限。平台不自动截短 |
| 未填写,套餐有单次上限 | 平台填入模型与套餐上限中较小的值,发给上游 |
| 未填写,套餐无单次上限 | 使用上游的默认值 |
| 输入估算本身超过套餐的每分钟 token 数 | 400 validation_failed,details.reason 为 plan_tpm_exceeded,message 写明输入估算与套餐每分钟上限,见错误码。max_tokens 不参与这一判定:每分钟 token 数只按输出预留计入,见错误码「HTTP 429 的来源」 |
输入加 max_tokens 超过模型的上下文窗口 | 400 context_window_exceeded,带 details.limit / details.estimated,见参数如何被处理「上下文窗口」 |
预扣按「输入估算 + 输出上限」计算,未填写时按上表确定的上限;账户的充值余额大于 0 时,输出只按输出上限与平台设定值中的较小者估算。结束后按实际用量结算,实际超出的部分照扣,见认证与 API Key「预扣」。
非流式响应
#json{
"id": "chatcmpl-…",
"object": "chat.completion",
"created": 1758585600,
"model": "YOUR_MODEL_ID",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "这段序列……" },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 42, "completion_tokens": 318, "total_tokens": 360 },
"scirouter": { "request_id": "req_…", "attempts": 1, "cost_quota": 18240, "…": "…" }
}数值为示例。
scirouter字段与X-SciRouter-*响应头见可观测性。- 单次调用扣除的配额以
scirouter.cost_quota为准,不根据usage自行计算。 finish_reason为length表示回答被max_tokens截断。结构化数据或代码被截断时解析可能不报错,内容仍不完整;批处理按finish_reason判断,不按内容长度判断。
流式响应
#请求带 "stream": true 时,响应为 text/event-stream:
text: ping
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"这段序列"}}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":42,"completion_tokens":318,"total_tokens":360}}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[],"scirouter":{"request_id":"req_…","attempts":1,"cost_quota":18240}}
data: [DONE]读取流时处理以下四点:
- 以
:开头的行是注释,跳过。排队或上游长时间无输出时,网关约每 10 秒发送一行: ping心跳。官方 SDK 自动跳过。 choices可能为空数组。末尾的用量分片(include_usage为true时才有)、scirouter扩展分片与托管工具的进度分片均如此,直接读取choices[0]会越界。- 收到
data: [DONE]才表示正常结束。 出错时流中出现一个{"error": {...}}分片,随后断开,不发送[DONE]。未收到[DONE]即结束的流按失败处理,错误分片的格式见错误码。 - 错误分片可能出现在第一个内容分片之前。心跳发出后 HTTP 状态码已是 200,此后的错误(如排队超时)只能以错误分片返回。只检查状态码会将这些错误当作成功。
故障转移只发生在第一个字节之前。上游开始输出后,中途失败不换线路重试,返回错误分片。
思考过程
#推理模型的思考过程同时写在 reasoning_content 与 reasoning 两个字段中,内容相同,读取任一字段即可:非流式在 choices[].message 上,流式在 choices[].delta 上。
思考消耗的 token 在 usage.completion_tokens_details.reasoning_tokens 中(上游返回时才有),已包含在 completion_tokens 内。
带签名的思考块
#部分模型对思考过程签名。多轮工具调用时,须将上一轮的思考块连同签名一起带回,模型才能接续;只带回 reasoning_content 的文本会丢失签名。
这类模型的助手消息上另有扩展字段 thinking_blocks:非流式在 choices[].message 上,流式在 choices[].delta 上,签名在最后一个分片中。数组中每项为以下两种之一:
json[
{ "type": "thinking", "thinking": "…", "signature": "…" },
{ "type": "redacted_thinking", "data": "…" }
]- 下一轮将助手消息原样放回
messages,包括thinking_blocks,内容不做修改。平台原样接收,并优先将请求发回签发该签名的线路。 - 不签名的模型没有该字段。
- 字段名为上述
thinking/signature与redacted_thinking/data,已按此格式实现的客户端无需修改。
签名被拒时的重试
#请求落到其他线路时,签名可能无效并被厂商拒绝。线路走 Anthropic Messages 入口时,平台不返回该 400,在同一条线路上重试一次:
| 情况 | 重试方式 | 响应扩展块 param_actions 的 reshaped |
|---|---|---|
| 厂商判定这些思考块属于其他对话(此前的历史有改动),且该线路支持 | 请厂商只丢掉对不上的块及其后的思考块,其余照常使用。此后发往该线路的请求均如此发送 | 厂商给出的原因,如 thinking(prefix_binding_mismatch) |
| 其他情况 | 去掉请求历史中的思考块后重试 | thinking(signature_rejected) |
- 第一种方式重试后仍因签名被拒,或线路不支持该选项时,按第二种方式再重试一次;线路不支持的,此后不再按第一种方式发送。
- 第二种方式下,平台记录该线路拒绝过的思考块。此后发往该线路的请求,去掉历史中最后一条带有被拒块的消息及其之前的思考块,之后新增的思考块照常带上。
- 重试仍失败时按普通失败处理。
线路走其他入口时,厂商的 400 照旧原样交回。Anthropic 格式(/v1/messages)的调用不做上述重试:签名被拒的 400 照旧原样交回,由客户端去掉思考块后重发,见 Messages。
工具调用
#tools 与 tool_choice 按 OpenAI 格式编写,模型返回的 tool_calls 原样交给调用方。需要平台代为执行工具(如搜索网页、读取文献)时,使用托管工具,见 MCP 与托管工具。
模型未声明工具调用能力(GET /models 的 features)时,带 tools 的请求在选择线路前返回 400 unsupported_param,details.cause 为 feature_missing。
线路筛选
#选择线路时按以下条件过滤:
| 请求条件 | 跳过的线路 |
|---|---|
带 tools(模型已声明工具调用能力) | 不支持工具调用的线路 |
| 流式 | 不支持流式的线路 |
预计 token 数(输入 + max_tokens)超过线路的单次上限 | 该线路 |
没有满足条件的线路时返回 503 model_unavailable,details.reason 指明缺少的条件:
details.reason | 含义 |
|---|---|
tools_unsupported | 没有支持工具调用的线路 |
streaming_unsupported | 没有支持流式的线路 |
input_too_large | 预计 token 数超过线路的单次上限,常见于 max_tokens 过大,先调小 |
no_capable_endpoint | 同时缺少以上多项 |
以上几种不带 Retry-After,原样重试无效,去掉对应参数或更换模型。带 Retry-After 的 503(endpoints_busy / model_busy)表示暂时繁忙。见错误码「HTTP 503 的 details.reason」。
超时
#| 情况 | 结果 |
|---|---|
| 流式:上游开始响应后连续约 60 秒无任何数据(各线路可单独配置) | 504 upstream_timeout,details.timeout 为 idle。发生在第一个内容分片之前时换线路重试,之后返回错误分片 |
| 连接超时(默认约 10 秒,按线路) | 504 upstream_timeout,details.timeout 为 connect |
| 总时长上限(默认约 10 分钟,按线路) | 504 upstream_timeout,details.timeout 为 total |
| 上游自身报告超时 | 504,details.timeout 为 upstream |
| 上游的流未正常结束即断开 | 502 upstream_error,details.provider_error.code 为 stream_interrupted |
| 非流式:整个响应超过约 270 秒 | 504 upstream_timeout,details.timeout 为 response,不计费 |
非流式请求最长等待约 270 秒。 非流式请求须等完整生成后才有第一个字节,平台不按开始响应的时间判定,最多等待整个响应约 270 秒。该时长短于接入层(CDN)等待源站应答的 300 秒,超时时返回 JSON 错误体,不出现 CDN 的 524。
回答可能超过数分钟(推理模型、长输出)时使用流式。流式约每 10 秒发送一行心跳,不受 270 秒限制,受上表的空闲超时与总时长上限约束。
中途断开与计费
#| 情况 | 计费 |
|---|---|
| 非流式请求失败 | 不计费 |
| 流式请求输出一部分后失败 | 按已产生的用量计费:上游返回用量时按上游用量,未返回时估算(输入按估算,输出按已收到的正文、思考过程与工具调用参数) |
| 调用方主动断开,流式 | 网关同时取消上游,结果不保存;按断开前已产生的部分计费,口径同上 |
| 调用方主动断开,非流式 | 网关同时取消上游,结果不保存;无法获得用量,不计费 |
调用方主动断开后结果不保存,带 Idempotency-Key 重试时会重新调用并照常计费,见缓存与幂等。
错误
#| 状态码 | code | 触发条件 |
|---|---|---|
| 404 | model_not_found | 模型不存在 |
| 503 | model_unavailable | 模型维护中、已停用或尚未定价;无满足条件的线路见线路筛选 |
| 403 | model_not_allowed | 模型不在 Key、项目或套餐的白名单内,details.scope 为 key / project / plan |
| 403 | model_restricted | 模型只对获授权的团队开放 |
| 400 | context_window_exceeded | 输入加 max_tokens 超过模型的上下文窗口 |
| 400 | unsupported_param | 契约类参数无法处理,或模型未声明工具调用能力时带 tools |
| 413 | payload_too_large | 请求体超过上限(默认 4 MB) |
所有错误码与重试策略见错误码。