Messages 差异

与 Anthropic 官方 /v1/messages 对齐:Anthropic SDK 把 base_url 指向 https://api.model-r.com/v1 即可。差异集中在流式事件的细节、system 字段的写法、缓存标记的处理、思考预算的换算(换算表在总览页)。

支持清单

✅ 按官方语义支持(行为不同处在说明里加注);⊘ 不支持(说明写明实际发生什么)。

特性状态说明
顶层字段
model ✅ 填模型名称,以 /v1/models 返回为准
max_tokens ✅ 输出上限
system ✅ 字符串或内容块数组;数组只读 text 块,见下文
messages ✅ 至少一条;role 收 user、assistant、system(与官方一致,其余 role 返回 400)。system 指令两种写法都可用:顶层 system 字段,或 messages[] 里的 system 消息(Claude Code 等客户端的插入式写法)。工具结果用 user 消息里的 tool_result 块
temperature / top_p / top_k / stop_sequences ✅ 原样发给模型
tools / tool_choice ✅ tool_choice 四种官方写法都收
max_tool_calls ✅ 平台扩展:托管工具调用预算,与 Responses 同一种写法,平台自己消费,见下文
thinking ✅ budget_tokens 换算成档位(见总览页),原值保留、回显时还原,见下文
output_config.effort ✅ 较新的档位写法;与 enabled / disabled / key 写法的 thinking 同时出现返回 400,与 thinking: adaptive 可并用(此时以 effort 为准)
metadata / service_tier / truncate ✅ 原样发给模型
stream_options ⊘ 不携带;usage 由平台计量后放在响应里
其余顶层字段(如 Claude Code 的 context_management) ⊘ 不报错、不转发,静默忽略
内容块(messages[].content 里)
text ✅ 文本
image ✅ base64 / URL / file_id 三种 source
tool_use / tool_result ✅ 函数调用往返
thinking ✅ 思考历史(thinking + signature)
document ✅ base64 文档
server_tool_use / web_search_tool_result ✅ 服务端工具往返
file ✅ file_id / base64 两种 source
工具类型
function(custom) ✅ name、description、input_schema
托管工具 ✅ type 不带日期后缀(写 web_search,不写 web_search_20250305)——平台侧执行,见平台函数页
MCP connector ⊘ mcp_servers[] / mcp_toolset 返回 400,见总览页
响应形态
流式 SSE ✅ 不发 ping 事件,见下文
非流式 JSON ✅ 带 content[]、stop_reason、usage 的完整 message 对象

与官方的差异

托管工具的 type 不带日期后缀

官方的托管工具 type 带版本日期(web_search_20250305);平台按不带后缀的 type 识别(web_search)。带日期后缀的声明会被丢弃——模型收不到该工具,表现为模型回答没有联网搜索能力。声明、返回与流式形状见平台函数页。

max_tool_calls:托管工具调用预算

官方 Messages 请求结构没有这个字段;平台为两个接口保留同一种写法——顶层 max_tool_calls,与 Responses 一致。平台扩展字段,由平台自己消费,不发给模型;取值须为 ≥ 1 的整数(写 0 返回 400),不写时默认 8。预算按已执行的调用次数计:一轮并行发起的多个调用整批执行,可能一次花掉甚至超出剩余预算;预算用尽后的下一轮由平台强制收尾作答,强制收尾仍发起新调用则请求失败。

请求

{
  "model": "your-model",
  "messages": [{ "role": "user", "content": "查一下今天北京的天气" }],
  "tools": [{ "type": "web_search", "name": "web_search" }],
  "max_tool_calls": 5
}

流式不发 ping 事件

官方会周期性发 ping 事件作心跳;平台的流不发。按官方文档解析事件的客户端不受影响——ping 本来就是可忽略的事件。

平台的事件序列(开头)

event: message_start
data: { … }
 
event: content_block_start
data: { … }

message_start 里没有 model 字段

官方在 message_start 的 message 对象里带 model;平台不带。需要模型名时用请求里发的那一份。

返回(流的第一个事件)

event: message_start
data: {
  "type": "message_start",
  "message": { "id": "msg_…", "role": "assistant", "content": [], … }
}

tool_use 的参数逐段到达

content_block_start 里 tool_use 块的 input 是空字符串(官方是 {}),参数随后以 input_json_delta 增量到达。

返回(同一个工具调用的两帧)

event: content_block_start
data: {
  "type": "content_block_start",
  "index": 1,
  "content_block": { "type": "tool_use", "id": "toolu_…", "name": "get_weather", "input": "" }
}
 
event: content_block_delta
data: {
  "type": "content_block_delta",
  "index": 1,
  "delta": { "type": "input_json_delta", "partial_json": "{\"city\":" }
}

把收到的 partial_json 按顺序拼接成完整 JSON;不要依赖 content_block_start 里的 input 值。

cache_control 只在 tools 上有效

官方的缓存标记 cache_control 可以写在 messages、system、tools 上。平台只保留 tools 上的;messages 与 system 上的在解析时丢弃——请求不会失败,只是这些标记不被使用。

请求(messages 上的 cache_control 不生效)

{
  "model": "your-model",
  "max_tokens": 1024,
  "system": [{ "type": "text", "text": "你是一个助手", "cache_control": { "type": "ephemeral" } }],
  "messages": [ … ]
}

system 用数组时只读 text 块

system 传内容块数组时只有 text 块生效,其余块被跳过;响应回显时 system 恒为普通字符串。

thinking.budget_tokens 换算成档位

budget_tokens 按总览页的换算表折算成档位发给模型;原始数值保留,响应回显时逐字还原。另外 output_config.effort 与 thinking 是两代写法,同时出现返回 400;唯一例外是 thinking.type 写 adaptive(开与不开交给模型、不指深度,Claude Code 的官方搭配),可与 effort 并存,此时以 effort 为准。

请求

{
  "model": "your-model",
  "max_tokens": 1024,
  "thinking": { "type": "enabled", "budget_tokens": 8000 },
  "messages": [{ "role": "user", "content": "想清楚再回答" }]
}

8000 落在 ≤ 10240 一档,按 medium 发给模型;回显的 thinking.budget_tokens 仍是 8000。