跳到主要内容

协议参考

ai-proxyai-proxy-multi 插件使用相同的请求协议检测与转换流程。该流程会先识别客户端格式,再将请求路由到已配置的服务提供方或所选实例。

有关插件专用配置,请参阅 ai-proxyai-proxy-multi

请求协议检测

插件会先识别客户端协议,再将其与所选服务提供方或实例支持的协议进行匹配。以下检测规则适用于两个插件。

请求要求

如果请求包含 Content-Type,其值必须为 application/json。如果省略该请求头,插件会将请求体视为 JSON。在选择服务提供方或实例前,插件会拒绝不支持的内容类型和无效请求体。

请求体不能超过 max_req_body_size,默认值为 67,108,864 字节。超过此限制的请求会收到 HTTP 413 响应。在 API7 网关中,此配置自 3.9.x 版本线的 3.9.14 和 3.10.x 版本线的 3.10.1 起可用;在 APISIX 3.17.0 及更高版本中可用。

检测顺序

插件按以下顺序检查规则:

客户端协议请求体信号路径要求
Bedrock Converse请求体包含 messages 数组。路径以 /converse 结尾;允许自定义前缀。
Anthropic Messages请求体是 JSON 对象。路径以 /v1/messages 结尾;允许自定义前缀。
OpenAI Responses请求体包含 input路径以 /v1/responses 结尾;允许自定义前缀。
OpenAI Chat Completions请求体包含 messages 数组。路由匹配的任意路径。
OpenAI Embeddings请求体包含 input,且前面的规则均不匹配。路由匹配的任意路径。

路径特定规则会先于仅基于请求体的规则执行,从而避免将包含 messages 的 Bedrock Converse 和 Anthropic Messages 请求识别为 Chat Completions。Responses 和 Embeddings 请求都使用 input,因此包含 input 但不包含 messages 的请求会被识别为 Embeddings,除非其路径以 /v1/responses 结尾。

其他任何非空 JSON 对象都会按透传处理。只要请求转换未改变请求体,此模式会保留原始请求路径,并可以复用原始请求体。服务提供方身份认证和 override.endpoint 仍然生效。空请求体或无效请求体会被拒绝。

检测后处理

对于已命名的协议,如果所选服务提供方支持该协议,插件会直接使用检测到的协议而不执行转换。否则,插件会查找已注册的转换器,将请求转换为服务提供方支持的协议。如果既没有原生支持,也没有兼容的转换器,请求会被拒绝。

检测到的协议和请求体决定日志插件将 request_type 记录为 ai_stream 还是 ai_chat。响应解析则根据上游响应的内容类型区分流式与非流式响应。

Anthropic 到 OpenAI 的转换

Anthropic Messages 客户端可以通过 ai-proxyai-proxy-multi 向支持 OpenAI Chat Completions 的后端发送请求。插件会将客户端请求转换为 OpenAI 格式,并将后端响应转换为 Anthropic 格式。此转换只支持 Anthropic Messages API 的一部分:保留部分字段、转换其他字段,并丢弃不支持的字段。

何时执行转换

当请求路径以 /v1/messages 结尾且请求体是 JSON 对象时,插件会将其识别为 Anthropic Messages 请求。如果所选服务提供方支持 Anthropic Messages,请求会直接使用该协议而不进行转换。如果服务提供方支持的是 OpenAI Chat Completions,共享转换器会转换请求和响应。

不支持相反的客户端/后端组合:OpenAI Chat Completions 客户端不能使用此转换器调用 Anthropic Messages 后端。

对于 ai-proxy-multi,是否需要转换由所选实例决定。转换配置示例使用 ai-proxy;有关多实例配置,请参阅 ai-proxy-multi

请求转换

转换后的请求体根据允许列表构建。下表汇总转换器会读取的 Anthropic 输入。无法识别的字段会在请求到达后端前被丢弃。

请求字段

Anthropic 字段OpenAI 字段行为
modelmodel转发;但如果路由通过 options.model 固定模型,则不转发。
max_tokensmax_completion_tokens重命名。
stop_sequencesstop重命名。
temperaturetop_p同名字段转发。
streamstream,以及 stream_options.include_usage插件设置 stream_options.include_usage,使流中包含用量信息。
system位于消息开头且 role: system 的消息文本块会拼接成一个字符串。
tools[](自定义工具)tools[].function如果工具名称包含 [a-zA-Z0-9_-] 以外的字符,或长度超过 64 个字符,则会改写为符合 OpenAI 命名规则的名称;响应中会恢复原名称。
tool_choicetool_choice转换:{"type": "auto"} 变为 "auto"{"type": "any"} 变为 "required"{"type": "none"} 变为 "none"{"type": "tool", "name": "..."} 变为指定该函数的对象。
tool_choice.disable_parallel_tool_useparallel_tool_calls: false转换。
thinkingreasoning_effort近似转换。连续的 budget_tokens 值会映射到一个离散的推理强度级别;阈值取决于版本。
output_config.effortreasoning_effortthinking.typeadaptive 时使用。不同版本支持情况不同,请参阅版本兼容性
output_formatoutput_config.formatresponse_format不同版本支持情况不同,请参阅版本兼容性
metadata.user_iduser重命名。
service_tierservice_tier转发。

消息内容

Anthropic 内容OpenAI 等效形式行为
字符串形式的 messages[].content内容相同的字符串形式 messages[].content转发。
text文本内容部分或纯字符串具体形式取决于版本,请参阅版本兼容性
使用 Base64 源的 image使用 data: URL 的 image_url转换。后端模型是否接受图片输入因模型而异。
使用 URL 源的 image使用相同 URL 的 image_url原样转发。
使用 Base64 源的 document使用 data: URL 的 image_url近似转换。文档字节会放入 OpenAI Schema 定义为图片的字段中,因此后端是否接受不在该 Schema 的保证范围内。
tool_use包含 tool_calls 的助手消息转换。消息历史中的工具名称处理取决于版本,请参阅版本兼容性
tool_resultrole: tool 的消息转换。其与普通文本的相对顺序取决于版本,请参阅版本兼容性

丢弃的字段

后端不会收到以下字段,响应中也不会提示字段已被移除:

Anthropic 字段丢弃原因
top_kOpenAI Chat Completions 没有等效参数。
cache_control没有等效字段;转换后的请求不包含缓存指令。
citations转换器在两个方向都不映射引用。
消息历史中的 thinkingredacted_thinkingOpenAI Chat Completions 没有等效字段;同一助手消息中的普通文本会保留。
Anthropic 内置工具(computer_bash_text_editor_web_searchcode_execution_转换器没有这些工具的映射。

请求头

如果请求包含 x-api-key 请求头但不包含 Authorization 请求头,转换器会将该 Key 作为 Bearer Token 放入 Authorization。它会移除原始 x-api-key 请求头,以及名称以 anthropic-x-stainless- 开头的请求头。

响应转换

转换器只读取 choices[0] 中的补全字段;其他 OpenAI choice 会被丢弃。顶层 usageerror 字段会单独映射。

OpenAI 响应字段Anthropic 响应行为
message.contenttext 内容块转换。
message.reasoning_contentmessage.reasoningthinking 内容块后端返回非空字符串时转换。非流式块的签名为空,请参阅已知限制
message.tool_callstool_use 内容块转换。如果原始名称可用,会恢复经过规范化的工具名称。
finish_reasonstop_reasonstopcontent_filter 变为 end_turnlength 变为 max_tokenstool_callsfunction_call 变为 tool_use。其他值默认为 end_turn
usageinput_tokensoutput_tokens 和可用的缓存 Token 字段prompt_tokens 变为 input_tokenscompletion_tokens 变为 output_tokens。如果缓存详情可用,会从 input_tokens 中扣除缓存的提示词 Token,并报告为 cache_read_input_tokens;如果提供了 cache_creation_input_tokens,也会包含该字段。
errorAnthropic 错误对象正常解析的上游响应体包含错误对象时转换。HTTP 429、5xx 和传输错误可能绕过此转换。

对于流式响应,转换器会为 OpenAI 文本、推理和工具调用增量发出 Anthropic 消息及内容块事件。初始 message_start 中的用量值为零;最终 Token 用量在 message_delta 中发出。如果后端在受支持的用量块中提供缓存 Token 字段,也可以包含这些字段。报告流式用量的客户端应读取最终事件,且不应假设缓存 Token 字段一定存在。

版本兼容性

API7 网关 3.9.x 和 3.10.x 会分别接收修复。请查看实际运行版本所在的列。

行为API7 网关 3.9.xAPI7 网关 3.10.xAPISIX
所有工具都被丢弃时,移除失去关联的 tool_choice3.9.16 及更高版本3.10.2 及更高版本3.17.0 中不支持
后端工具调用格式错误时降级处理,而不是使响应失败3.9.16 及更高版本3.10.2 及更高版本3.17.0 中不支持
message_start.content 序列化为数组3.9.16 及更高版本3.10.3 及更高版本3.17.0 中不支持
识别 Anthropic 当前的结构化输出形式3.9.16 及更高版本3.10.3 及更高版本3.17.0 中不支持
thinking.type: adaptive 使用 output_config.effort3.9.16 及更高版本3.10.3 及更高版本3.17.0 中不支持
thinking.budget_tokens 使用下述四级映射3.9.16 及更高版本3.10.3 及更高版本3.17.0 中不支持
将仅含一个文本块的用户消息作为内容数组发送,并把包含多个文本块的助手消息拼接为字符串3.9.16 及更高版本3.10.3 及更高版本3.17.0 中不支持
消息历史中的工具名称与声明的工具保持一致地改写3.9.16 及更高版本3.10.3 及更高版本3.17.0 中不支持
tool_result 消息放在同一用户消息的普通文本之前3.9.16 及更高版本3.10.3 及更高版本3.17.0 中不支持
用户消息同时包含 tool_result 时保留媒体内容3.9.16 及更高版本3.10.3 及更高版本3.17.0 中不支持

这些版本差异会影响结构化输出、消息内容、推理强度和工具历史,具体如下。

结构化输出

API7 网关 3.9.15 及更早版本、API7 网关 3.10.0 至 3.10.2,以及 APISIX 3.17.0,只能识别转换器过去预期的形式:output_configoutput_format 包含 type: json_schemajson_schema 字段,或者包含 type: jsontype: json_object

Anthropic 当前会把 Schema 放在 output_format.schemaoutput_config.format 中。API7 网关 3.9.x 从 3.9.16 起识别这种形式;3.10.x 从 3.10.3 起识别。这些版本会规范化 Schema,并发送启用严格模式的 response_format。在更早版本中,后端不会收到 response_format,客户端也不会收到错误。

消息内容形式

在早于该项变更的版本中,只包含一个文本块的用户消息会以纯字符串发送;包含多个文本块的助手消息会以内容数组发送。只接受其中一种形式的后端,在升级前后会表现不同。

推理强度

不同版本使用不同的 budget_tokens 映射。较早的映射适用于 APISIX 3.17.0,以及 API7 网关对应版本线中早于 3.9.16 或 3.10.3 的版本。较新的映射分别从 API7 网关 3.9.16 和 3.10.3 起适用。

budget_tokens较早版本较新版本
小于 1024lowminimal
1024 至 2047lowlow
2048 至 4095lowmedium
4096 至 16383mediumhigh
16384 或更高highhigh
未提供mediumminimal

工具历史

在较早版本中,消息历史里的 tool_use 名称不会按照相应的已声明工具名称改写。同一用户消息中的普通文本也可能先于 tool_result 消息发送,并且该消息中的媒体内容会被丢弃。严格的后端可能会拒绝名称或顺序不匹配。API7 网关 3.9.16 及更高版本和 API7 网关 3.10.3 及更高版本会一致地改写历史名称、优先放置工具消息并保留媒体内容。

已知限制

以下限制可能会影响所有受支持版本中的转换请求和响应。

流式传输可能在没有终止事件的情况下结束

如果后端关闭流时没有发送格式正确、分隔完整的最后一帧,插件不会发出结尾的 message_deltamessage_stop 事件。依赖 message_stop 的客户端可能无限等待,或将该流视为不完整。上述所有版本都会受到影响。请设置客户端超时,并将流意外结束视为失败。

转换后的 thinking 块不包含有效签名

对于非流式响应,插件会将该块的 signature 设置为空字符串;对于流式响应,插件会发出不含签名的 thinking 增量。要求有效签名的客户端无法将任一转换形式作为已签名的 Anthropic thinking 块重放。如果后端把推理内容嵌入普通消息内容,响应中的推理会显示为可见文本。

错误响应不一定采用 Anthropic 格式

HTTP 429、5xx 和传输超时响应可能绕过响应转换。客户端应做好接收不符合 Anthropic 错误 Schema 的上游或网关错误响应体的准备。

不验证后端能力

插件会转换请求,但不会检查后端模型是否支持转换结果。后端可能返回 HTTP 200,却静默忽略某项能力,例如丢弃图片、忽略 response_format 或不返回工具调用。

不同模型的后端行为不同,同一模型名称的不同日期快照也可能不同。请验证计划使用的具体模型,不要根据某个后端笼统推断。

验证后端兼容性

请针对每个后端模型测试以下转换输入,因为即使原始 Anthropic 请求有效,后端仍可能拒绝它们:

  • 指定名称的 tool_choice 转换器会输出指定函数的对象或 "required"。有些后端在模型进行推理时只接受 "auto"。如果后端拒绝转换后的形式,请从客户端发送 {"type": "auto"}
  • thinking 与较小的 max_tokens 同时使用。 thinking 会变为 reasoning_effort,可能使后端预留推理预算。如果该预算超过转换后的 max_completion_tokens,后端会拒绝请求。启用 thinking 时请提高 max_tokens
  • document 块。 转换器只能将其作为图片提供给后端。无法读取它的模型可能会生成虚构内容,而不是报告错误。
  • 混合文本、媒体和 tool_result 内容。 较早版本可能会把普通文本放在转换后的工具消息之前,并丢弃同一用户消息中的媒体内容。如果后端验证工具消息顺序,请测试这种形式,或升级到会先放置工具消息并保留媒体内容的版本。

相关配置