diff --git a/README.md b/README.md index e5a60ef..5519adf 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,10 @@ OpenAI 兼容 API 代理服务器,用于在不同 LLM API 格式之间进行 ## 功能特性 +- **三种接口模式**: + - **统一格式接口**:`/v1/chat/completions` - 支持所有端点类型,自动格式转换 + - **OpenAI 透明代理**:`/v1/responses` - 直接转发 OpenAI 请求,零转换 + - **Anthropic 透明代理**:`/v1/messages` - 直接转发 Anthropic 请求,零转换 - **标准 OpenAI API 接口**:提供完全兼容 OpenAI 的 API 端点 - **多格式支持**:支持 Anthropic 和自定义 OpenAI 格式之间的自动转换 - **流式响应**:自动转换 SSE (Server-Sent Events) 流式响应为标准 OpenAI 格式 @@ -92,7 +96,16 @@ npm start 服务器默认运行在 `http://localhost:3000`。 -### API 端点 +### API 端点总览 + +| 端点 | 方法 | 支持类型 | 格式转换 | 适用场景 | +|------|------|---------|---------|---------| +| `/v1/models` | GET | - | - | 获取模型列表 | +| `/v1/chat/completions` | POST | anthropic, openai | ✅ 自动转换 | 需要统一OpenAI格式 | +| `/v1/responses` | POST | 仅 openai | ❌ 直接转发 | 已是目标格式,追求性能 | +| `/v1/messages` | POST | 仅 anthropic | ❌ 直接转发 | 已是目标格式,追求性能 | + +### API 端点详细说明 #### 1. 获取可用模型列表 @@ -120,21 +133,27 @@ curl http://localhost:3000/v1/models } ``` -#### 2. 对话补全(兼容 OpenAI) +#### 2. 统一格式接口 - 对话补全(带格式转换) ```bash POST /v1/chat/completions ``` +**功能特点:** +- ✅ 支持所有端点类型(anthropic, openai) +- ✅ 自动转换请求格式到目标端点格式 +- ✅ 自动转换响应为标准 OpenAI 格式 +- ✅ 适合需要统一接口的场景 + **请求参数:** - `model` (必需): 模型 ID -- `messages` (必需): 对话消息数组 +- `messages` (必需): 标准 OpenAI 格式消息数组 - `stream` (可选): 是否使用流式响应,默认 true - `max_tokens` (可选): 最大输出 tokens 数 - `temperature` (可选): 温度参数 0-1 - `top_p` (可选): Top-p 采样参数 -**示例(流式响应):** +**示例(Anthropic 模型,自动转换):** ```bash curl http://localhost:3000/v1/chat/completions \ -H "Content-Type: application/json" \ @@ -148,7 +167,7 @@ curl http://localhost:3000/v1/chat/completions \ }' ``` -**示例(非流式响应):** +**示例(OpenAI 模型,自动转换):** ```bash curl http://localhost:3000/v1/chat/completions \ -H "Content-Type: application/json" \ @@ -161,6 +180,71 @@ curl http://localhost:3000/v1/chat/completions \ }' ``` +#### 3. OpenAI 透明代理接口(不做转换) + +```bash +POST /v1/responses +``` + +**功能特点:** +- ⚠️ **仅支持 openai 类型端点** +- ❌ 请求体不做任何转换,直接转发 +- ❌ 响应体不做任何转换,直接转发 +- ✅ 适合已是目标格式,追求最高性能的场景 + +**限制:** +使用非 openai 类型模型会返回 400 错误: +```json +{ + "error": "Invalid endpoint type", + "message": "/v1/responses 接口只支持 openai 类型端点" +} +``` + +**示例:** +```bash +curl http://localhost:3000/v1/responses \ + -H "Content-Type: application/json" \ + -d '{ + "model": "gpt-5-codex", + "messages": [{"role": "user", "content": "Hello"}], + "stream": true + }' +``` + +#### 4. Anthropic 透明代理接口(不做转换) + +```bash +POST /v1/messages +``` + +**功能特点:** +- ⚠️ **仅支持 anthropic 类型端点** +- ❌ 请求体不做任何转换,直接转发 +- ❌ 响应体不做任何转换,直接转发 +- ✅ 适合已是目标格式,追求最高性能的场景 + +**限制:** +使用非 anthropic 类型模型会返回 400 错误: +```json +{ + "error": "Invalid endpoint type", + "message": "/v1/messages 接口只支持 anthropic 类型端点" +} +``` + +**示例:** +```bash +curl http://localhost:3000/v1/messages \ + -H "Content-Type: application/json" \ + -d '{ + "model": "claude-opus-4-1-20250805", + "messages": [{"role": "user", "content": "Hello"}], + "max_tokens": 1024, + "stream": true + }' +``` + ## API Key 自动刷新机制 代理服务器会自动管理 API key 的刷新: @@ -179,9 +263,47 @@ curl http://localhost:3000/v1/chat/completions \ [INFO] API key refreshed successfully ``` +## 接口模式选择指南 + +### 何时使用 `/v1/chat/completions`(统一格式) + +✅ **推荐场景:** +- 需要统一的 OpenAI 兼容接口 +- 应用代码已使用 OpenAI SDK +- 需要在不同 LLM 提供商之间切换 +- 不关心轻微的性能损耗 + +❌ **不推荐场景:** +- 已有原生格式的请求/响应处理逻辑 +- 对性能要求极高(需要避免格式转换开销) + +### 何时使用 `/v1/responses`(OpenAI 透明代理) + +✅ **推荐场景:** +- 请求已经是目标 OpenAI 端点格式 +- 追求最高性能,避免格式转换开销 +- 只使用 OpenAI 端点 + +❌ **不推荐场景:** +- 使用 Anthropic 端点(会返回错误) +- 需要格式转换 + +### 何时使用 `/v1/messages`(Anthropic 透明代理) + +✅ **推荐场景:** +- 请求已经是标准 Anthropic 格式 +- 追求最高性能,避免格式转换开销 +- 只使用 Anthropic 端点 + +❌ **不推荐场景:** +- 使用 OpenAI 端点(会返回错误) +- 需要格式转换 + ## 格式转换说明 -### Anthropic 格式转换 +> 注意:仅 `/v1/chat/completions` 接口会进行格式转换,`/v1/responses` 和 `/v1/messages` 直接转发,不做任何转换。 + +### Anthropic 格式转换(仅 /v1/chat/completions) **请求转换:** - `messages` → `messages`(提取 system 消息到顶层) @@ -194,7 +316,7 @@ curl http://localhost:3000/v1/chat/completions \ - 转换为标准 OpenAI chunk 格式 - 映射停止原因:`end_turn` → `stop`, `max_tokens` → `length` -### OpenAI 格式转换 +### OpenAI 格式转换(仅 /v1/chat/completions) **请求转换:** - `messages` → `input`