# Anthropic 协议代理 ## Purpose TBD - 提供 Anthropic Messages API 的代理功能,通过协议转换实现与 OpenAI 兼容供应商的互操作 ## Requirements ### Requirement: 支持 Anthropic Messages API 端点 网关 SHALL 提供 Anthropic Messages API 端点 `POST /v1/messages` 供外部应用调用。 #### Scenario: 成功的非流式请求 - **WHEN** 应用发送 POST 请求到 `/v1/messages`,携带有效的 Anthropic 请求格式(非流式) - **THEN** 网关 SHALL 将 Anthropic 请求转换为 OpenAI 格式 - **THEN** 网关 SHALL 将转换后的请求转发到配置的供应商 - **THEN** 网关 SHALL 将 OpenAI 响应转换回 Anthropic 格式 - **THEN** 网关 SHALL 将转换后的响应返回给应用 #### Scenario: 成功的流式请求 - **WHEN** 应用发送 POST 请求到 `/v1/messages`,携带 `stream: true` - **THEN** 网关 SHALL 将 Anthropic 请求转换为 OpenAI 格式 - **THEN** 网关 SHALL 将转换后的请求转发给供应商 - **THEN** 网关 SHALL 将 OpenAI 流事件转换为 Anthropic 流事件 - **THEN** 网关 SHALL 使用 SSE 格式将转换后的事件流式返回给应用 ### Requirement: 将 Anthropic 请求转换为 OpenAI 格式 网关 SHALL 将 Anthropic Messages API 请求转换为 OpenAI Chat Completions API 格式。 #### Scenario: System 消息转换 - **WHEN** Anthropic 请求包含 `system` 字段 - **THEN** 网关 SHALL 将其转换为 `messages` 数组中 `role: "system"` 的消息 #### Scenario: Messages 转换 - **WHEN** Anthropic 请求包含 `messages` 数组 - **THEN** 网关 SHALL 在转换后的 OpenAI 请求中保留这些消息 - **THEN** 网关 SHALL 保留每条消息的 role 和 content #### Scenario: Tools 转换 - **WHEN** Anthropic 请求包含带有 `input_schema` 的 `tools` - **THEN** 网关 SHALL 将每个工具转换为 OpenAI 格式,使用 `function.parameters` 替代 `input_schema` - **THEN** 网关 SHALL 保留工具名称和描述 #### Scenario: Tool choice 转换 - **WHEN** Anthropic 请求包含 `type: "auto"` 的 `tool_choice` - **THEN** 网关 SHALL 将其转换为 OpenAI 格式的 `"auto"` - **WHEN** Anthropic 请求包含 `type: "any"` 的 `tool_choice` - **THEN** 网关 SHALL 将其转换为 OpenAI 格式的 `"auto"` - **WHEN** Anthropic 请求包含 `type: "tool"` 和 `name` 的 `tool_choice` - **THEN** 网关 SHALL 将其转换为 OpenAI 格式的 `{"type": "function", "function": {"name": }}` #### Scenario: Tool result 转换 - **WHEN** Anthropic 请求包含用户消息,其 `content` 数组包含 `type: "tool_result"` 块 - **THEN** 网关 SHALL 将每个工具结果转换为 `role: "tool"` 的消息 - **THEN** 网关 SHALL 从 `tool_use_id` 设置 `tool_call_id` - **THEN** 网关 SHALL 保留 content #### Scenario: Max tokens 处理 - **WHEN** Anthropic 请求包含 `max_tokens` - **THEN** 网关 SHALL 在 OpenAI 请求中包含它作为 `max_tokens` - **WHEN** Anthropic 请求不包含 `max_tokens` - **THEN** 网关 SHALL 设置默认值(4096)以满足 Anthropic 的要求 ### Requirement: 将 OpenAI 响应转换为 Anthropic 格式 网关 SHALL 将 OpenAI Chat Completions API 响应转换为 Anthropic Messages API 格式。 #### Scenario: Content 转换 - **WHEN** OpenAI 响应包含 `choices[0].message.content` - **THEN** 网关 SHALL 将其转换为 Anthropic 格式的 `content: [{"type": "text", "text": }]` #### Scenario: Tool calls 转换 - **WHEN** OpenAI 响应包含 `choices[0].message.tool_calls` - **THEN** 网关 SHALL 将每个工具调用转换为 `type: "tool_use"` 的内容块 - **THEN** 网关 SHALL 从 `tool_calls[].id` 设置 `id` - **THEN** 网关 SHALL 从 `tool_calls[].function.name` 设置 `name` - **THEN** 网关 SHALL 解析 `arguments` JSON 字符串并将其设置为 `input` 对象 #### Scenario: Finish reason 转换 - **WHEN** OpenAI 响应的 `finish_reason` 为 `"stop"` - **THEN** 网关 SHALL 在 Anthropic 响应中设置 `stop_reason: "end_turn"` - **WHEN** OpenAI 响应的 `finish_reason` 为 `"tool_calls"` - **THEN** 网关 SHALL 在 Anthropic 响应中设置 `stop_reason: "tool_use"` #### Scenario: Usage 转换 - **WHEN** OpenAI 响应包含带有 `prompt_tokens` 和 `completion_tokens` 的 `usage` - **THEN** 网关 SHALL 转换为 Anthropic 格式,使用 `input_tokens` 和 `output_tokens` ### Requirement: 转换流式事件 网关 SHALL 实时将 OpenAI 流事件转换为 Anthropic 流事件。 #### Scenario: Message start 事件 - **WHEN** 网关开始流式传输 Anthropic 响应 - **THEN** 网关 SHALL 发送带有消息元数据的 `message_start` 事件 #### Scenario: Content block start 事件 - **WHEN** OpenAI 流开始返回内容 - **THEN** 网关 SHALL 发送带有 `type: "text"` 的 `content_block_start` 事件 #### Scenario: Content delta 事件 - **WHEN** OpenAI 流发送带有内容的 delta - **THEN** 网关 SHALL 发送带有 `type: "text_delta"` 的 `content_block_delta` 事件,包含文本 #### Scenario: Tool use 流式传输 - **WHEN** OpenAI 流发送工具调用 delta - **THEN** 网关 SHALL 缓冲 `arguments` 块 - **THEN** 网关 SHALL 在工具调用开始时发送带有 `type: "tool_use"` 的 `content_block_start` - **THEN** 网关 SHALL 发送带有部分 JSON 的 `input_delta` 事件 #### Scenario: Content block stop 事件 - **WHEN** 内容块完成 - **THEN** 网关 SHALL 发送 `content_block_stop` 事件 #### Scenario: Message stop 事件 - **WHEN** OpenAI 流完成 - **THEN** 网关 SHALL 发送 `message_stop` 事件 ### Requirement: 支持 Anthropic 特有功能 网关 SHALL 支持映射到 OpenAI 能力的 Anthropic 特有功能。 #### Scenario: System prompt 作为独立字段 - **WHEN** Anthropic 请求包含 `system` 字段 - **THEN** 网关 SHALL 将其作为 OpenAI 格式的 system 消息处理 #### Scenario: 必需的 max_tokens - **WHEN** 收到 Anthropic 请求 - **THEN** 网关 SHALL 确保 `max_tokens` 存在(如果未提供则使用默认值) ### Requirement: 处理纯文本内容 网关 SHALL 在 Anthropic 请求和响应中支持纯文本内容。 #### Scenario: 消息中的文本内容 - **WHEN** Anthropic 请求在消息中包含文本内容 - **THEN** 网关 SHALL 正确处理和转发文本内容 #### Scenario: 拒绝多模态内容 - **WHEN** Anthropic 请求包含多模态内容(图片、文档) - **THEN** 网关 SHALL 返回错误,指示 MVP 不支持多模态内容 ### Requirement: 保留请求元数据 网关 SHALL 在转换过程中保留请求元数据。 #### Scenario: 模型名称保留 - **WHEN** Anthropic 请求指定模型名称 - **THEN** 网关 SHALL 在转换后的 OpenAI 请求中保留模型名称 #### Scenario: 自定义参数 - **WHEN** Anthropic 请求包含自定义参数(temperature, top_p 等) - **THEN** 网关 SHALL 在转换后的请求中保留这些参数