1
0
Files
nex/openspec/specs/anthropic-protocol-proxy/spec.md
lanyuanxiaoyao 915b004924 feat: 初始化 AI Gateway 项目
实现支持 OpenAI 和 Anthropic 双协议的统一大模型 API 网关 MVP 版本,包含:
- OpenAI 和 Anthropic 协议代理
- 供应商和模型管理
- 用量统计
- 前端配置界面
2026-04-15 16:53:28 +08:00

179 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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": <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": <content>}]`
#### 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 在转换后的请求中保留这些参数