docs: 添加 API 参考文档和技术分析文档
This commit is contained in:
507
docs/analysis_reference/analysis_new-api.md
Normal file
507
docs/analysis_reference/analysis_new-api.md
Normal file
@@ -0,0 +1,507 @@
|
||||
# New-API 项目 API 代理转换层详细分析报告
|
||||
|
||||
## 一、项目概述
|
||||
|
||||
`new-api` 是一个用 Go 语言编写的 AI API 网关/代理项目,基于 Gin Web 框架和 GORM ORM 构建。其核心功能是将 30+ 种上游 AI 服务提供商(OpenAI、Claude/Anthropic、Google Gemini、AWS Bedrock、阿里通义千问、百度文心等)的 API 统一管理,并以标准化格式对外提供统一入口。
|
||||
|
||||
### 与同类项目的核心差异
|
||||
|
||||
New-API 是 One-API 的增强分支,在 One-API 的 OpenAI-only 输入基础上增加了**多协议输入**能力(同时接受 OpenAI、Claude、Gemini 三种格式的客户端请求)和 **Hub-and-Spoke 转换架构**(以 OpenAI 格式为内部枢纽)。同时引入了 **Chat Completions via Responses API** 内部路由、**Thinking-to-Content** 转换、异步任务适配器等高级特性。
|
||||
|
||||
---
|
||||
|
||||
## 二、技术架构
|
||||
|
||||
### 2.1 分层架构
|
||||
|
||||
项目采用经典的分层架构:**Router → Controller → Relay Handler → Adaptor → Upstream API**
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 客户端请求 │
|
||||
│ (OpenAI / Claude / Gemini / Embedding / Audio / Image ...) │
|
||||
└───────────────────────────┬──────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ router/relay-router.go │
|
||||
│ 路由层:URL路径 → RelayFormat 映射 │
|
||||
│ /v1/chat/completions → RelayFormatOpenAI │
|
||||
│ /v1/messages → RelayFormatClaude │
|
||||
│ /v1beta/models/* → RelayFormatGemini │
|
||||
│ /v1/responses → RelayFormatOpenAIResponses │
|
||||
│ /v1/embeddings → RelayFormatEmbedding ... │
|
||||
└───────────────────────────┬──────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ controller/relay.go │
|
||||
│ 控制器层:请求验证、计费预扣、重试循环 │
|
||||
│ │
|
||||
│ Relay() 函数: │
|
||||
│ 1. 解析验证请求 (GetAndValidateRequest) │
|
||||
│ 2. 生成 RelayInfo (GenRelayInfo) │
|
||||
│ 3. Token估算 + 敏感词检测 │
|
||||
│ 4. 价格计算 + 预扣费 │
|
||||
│ 5. 渠道选择 + 重试循环 │
|
||||
│ 6. 按 RelayFormat 分发到 Handler │
|
||||
└───────────────────────────┬──────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ relay/ 目录 - Handler + Adaptor 层 │
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │compatible_handler│ │claude_handler.go │ │
|
||||
│ │ (OpenAI格式) │ │ (Claude格式) │ │
|
||||
│ └────────┬─────────┘ └────────┬─────────┘ │
|
||||
│ │ │ │
|
||||
│ ┌────────┴─────────┐ ┌────────┴─────────┐ │
|
||||
│ │gemini_handler.go │ │responses_handler │ │
|
||||
│ │ (Gemini格式) │ │ (Responses API) │ │
|
||||
│ └────────┬─────────┘ └────────┬─────────┘ │
|
||||
│ └──────────┬───────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ relay/relay_adaptor.go │ │
|
||||
│ │ GetAdaptor(apiType) → channel.Adaptor │ │
|
||||
│ └──────────────────────┬───────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ relay/channel/adapter.go (Adaptor接口) │ │
|
||||
│ │ ConvertOpenAIRequest() - OpenAI格式请求转换 │ │
|
||||
│ │ ConvertClaudeRequest() - Claude格式请求转换 │ │
|
||||
│ │ ConvertGeminiRequest() - Gemini格式请求转换 │ │
|
||||
│ │ ConvertEmbeddingRequest() / Audio / Image / Rerank│ │
|
||||
│ │ ConvertOpenAIResponsesRequest() - Responses转换 │ │
|
||||
│ │ DoRequest() + DoResponse() │ │
|
||||
│ └──────────────────────┬───────────────────────────┘ │
|
||||
└─────────────────────────┼────────────────────────────────────┘
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 上游 AI 服务提供商 │
|
||||
│ OpenAI / Claude / Gemini / AWS Bedrock / 阿里 / 百度 / ... │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 核心设计模式
|
||||
|
||||
项目采用 **适配器模式 + Hub-and-Spoke 架构**:
|
||||
|
||||
1. **统一接口 (`channel.Adaptor`)**:定义所有提供商必须实现的转换方法
|
||||
2. **工厂函数 (`GetAdaptor`)**:根据 `apiType` 创建对应提供商的适配器实例
|
||||
3. **Hub-and-Spoke 转换架构**:以 OpenAI 格式作为内部规范格式(Canonical Format),所有其他格式先转换为 OpenAI 格式,再由 OpenAI 格式转换为目标格式
|
||||
|
||||
### 2.3 关键接口定义
|
||||
|
||||
**同步请求适配器接口** (`relay/channel/adapter.go`, 83 行):
|
||||
|
||||
```go
|
||||
type Adaptor interface {
|
||||
Init(info *relaycommon.RelayInfo)
|
||||
GetRequestURL(info *relaycommon.RelayInfo) (string, error)
|
||||
SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error
|
||||
ConvertOpenAIRequest(c, info, request *dto.GeneralOpenAIRequest) (any, error)
|
||||
ConvertClaudeRequest(c, info, request *dto.ClaudeRequest) (any, error)
|
||||
ConvertGeminiRequest(c, info, request *dto.GeminiChatRequest) (any, error)
|
||||
ConvertRerankRequest(c, relayMode int, request dto.RerankRequest) (any, error)
|
||||
ConvertEmbeddingRequest(c, info, request dto.EmbeddingRequest) (any, error)
|
||||
ConvertAudioRequest(c, info, request dto.AudioRequest) (io.Reader, error)
|
||||
ConvertImageRequest(c, info, request dto.ImageRequest) (any, error)
|
||||
ConvertOpenAIResponsesRequest(c, info, request dto.OpenAIResponsesRequest) (any, error)
|
||||
DoRequest(c, info, requestBody io.Reader) (any, error)
|
||||
DoResponse(c, resp, info) (usage any, err *types.NewAPIError)
|
||||
GetModelList() []string
|
||||
GetChannelName() string
|
||||
}
|
||||
```
|
||||
|
||||
**异步任务适配器接口** (`TaskAdaptor`):16 个方法,覆盖任务提交、轮询、计费估算等全生命周期。
|
||||
|
||||
---
|
||||
|
||||
## 三、支持的协议/格式类型
|
||||
|
||||
### 3.1 输入格式(RelayFormat)
|
||||
|
||||
**文件**: `types/relay_format.go` (19 行)
|
||||
|
||||
| RelayFormat 常量 | 值 | 对应路由 |
|
||||
|---|---|---|
|
||||
| `RelayFormatOpenAI` | `"openai"` | `/v1/chat/completions`, `/v1/completions`, `/v1/moderations` |
|
||||
| `RelayFormatClaude` | `"claude"` | `/v1/messages` |
|
||||
| `RelayFormatGemini` | `"gemini"` | `/v1beta/models/*`, `/v1/engines/:model/embeddings` |
|
||||
| `RelayFormatOpenAIResponses` | `"openai_responses"` | `/v1/responses` |
|
||||
| `RelayFormatOpenAIResponsesCompaction` | `"openai_responses_compaction"` | `/v1/responses/compact` |
|
||||
| `RelayFormatOpenAIAudio` | `"openai_audio"` | `/v1/audio/*` |
|
||||
| `RelayFormatOpenAIImage` | `"openai_image"` | `/v1/images/*` |
|
||||
| `RelayFormatOpenAIRealtime` | `"openai_realtime"` | `/v1/realtime` (WebSocket) |
|
||||
| `RelayFormatRerank` | `"rerank"` | `/v1/rerank` |
|
||||
| `RelayFormatEmbedding` | `"embedding"` | `/v1/embeddings` |
|
||||
| `RelayFormatTask` | `"task"` | 异步任务 (Suno/Video等) |
|
||||
| `RelayFormatMjProxy` | `"mj_proxy"` | `/mj/*` |
|
||||
|
||||
### 3.2 上游提供商 API 类型
|
||||
|
||||
**文件**: `constant/api_type.go` (40 行)
|
||||
|
||||
定义 35 种 API 类型(iota 0-34, 加 APITypeDummy=35),工厂函数 `GetAdaptor()` 映射了其中 29 种(其余复用 OpenAI 适配器或未使用):
|
||||
|
||||
| API 类型 | 提供商 | 适配器目录 |
|
||||
|---|---|---|
|
||||
| `APITypeOpenAI` (0) | OpenAI / Azure / OpenRouter / Xinference | `relay/channel/openai/` |
|
||||
| `APITypeAnthropic` (1) | Anthropic Claude | `relay/channel/claude/` |
|
||||
| `APITypeGemini` (9) | Google Gemini | `relay/channel/gemini/` |
|
||||
| `APITypeAws` (13) | AWS Bedrock | `relay/channel/aws/` |
|
||||
| `APITypeAli` (5) | 阿里云通义千问 | `relay/channel/ali/` |
|
||||
| `APITypeBaidu` (3) / `APITypeBaiduV2` (24) | 百度文心 | `relay/channel/baidu/`, `baidu_v2/` |
|
||||
| `APITypeZhipu` (4) / `APITypeZhipuV4` (10) | 智谱AI (GLM) | `relay/channel/zhipu/`, `zhipu_4v/` |
|
||||
| `APITypeXunfei` (6) | 科大讯飞 | `relay/channel/xunfei/` |
|
||||
| `APITypeTencent` (8) | 腾讯混元 | `relay/channel/tencent/` |
|
||||
| `APITypeOllama` (11) | Ollama | `relay/channel/ollama/` |
|
||||
| `APITypeDeepSeek` (21) | DeepSeek | `relay/channel/deepseek/` |
|
||||
| `APITypeVolcEngine` (23) | 火山引擎 | `relay/channel/volcengine/` |
|
||||
| `APITypeVertexAi` (19) | Google Vertex AI | `relay/channel/vertex/` |
|
||||
| `APITypeMistral` (20) | Mistral AI | `relay/channel/mistral/` |
|
||||
| `APITypeCohere` (14) | Cohere | `relay/channel/cohere/` |
|
||||
| `APITypeOpenRouter` (25) | OpenRouter | 复用 `openai/` |
|
||||
| `APITypeXai` (27) | xAI (Grok) | `relay/channel/xai/` |
|
||||
| `APITypeCoze` (28) | 扣子 | `relay/channel/coze/` |
|
||||
| `APITypeMoonshot` (30) | Moonshot (月之暗面) | `relay/channel/moonshot/` |
|
||||
| `APITypeMiniMax` (32) | MiniMax | `relay/channel/minimax/` |
|
||||
| `APITypeCodex` (34) | Codex | `relay/channel/codex/` |
|
||||
| ... 其他 | SiliconFlow, Cloudflare, Perplexity, Dify, Jina, Jimeng, MokaAI, Replicate, Submodel | 各自目录 |
|
||||
|
||||
---
|
||||
|
||||
## 四、转换层核心业务逻辑
|
||||
|
||||
### 4.1 格式转换核心 — Hub-and-Spoke 模式
|
||||
|
||||
项目以 **OpenAI 格式作为内部规范格式(Canonical Format)**,采用 Hub-and-Spoke 转换架构:
|
||||
|
||||
```
|
||||
客户端输入格式
|
||||
┌──────┬──────┬───────┐
|
||||
│OpenAI│Claude│Gemini │ ...
|
||||
└──┬───┴──┬───┴──┬────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────────────┐
|
||||
│ OpenAI 规范格式 (Hub) │
|
||||
│ dto.GeneralOpenAIRequest │
|
||||
└────────────┬──────────────┘
|
||||
│
|
||||
┌──────┼──────┐
|
||||
▼ ▼ ▼
|
||||
┌──────┐┌──────┐┌──────┐
|
||||
│OpenAI││Claude││Gemini│ ... (上游格式)
|
||||
└──┬───┘└──┬───┘└──┬───┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
上游API 上游API 上游API
|
||||
```
|
||||
|
||||
**请求转换方向**:
|
||||
- `Claude → OpenAI → 上游原生格式`(如上游是 Gemini: `Claude → OpenAI → Gemini`,链式转换)
|
||||
- `Gemini → OpenAI → 上游原生格式`
|
||||
- `OpenAI → 上游原生格式`(直接转换)
|
||||
|
||||
**响应转换方向**:
|
||||
- `上游原生格式 → OpenAI → 客户端格式`
|
||||
- 如客户端请求 Claude 格式且上游是 Gemini: `Gemini → OpenAI → Claude`
|
||||
|
||||
### 4.2 转换链跟踪 (RequestConversionChain)
|
||||
|
||||
`RelayInfo` 中维护 `RequestConversionChain []types.RelayFormat` 字段,记录请求格式变化轨迹。例如:
|
||||
|
||||
- 用户发送 OpenAI 格式,上游是 Claude:`["openai", "claude"]`
|
||||
- 用户发送 Claude 格式,上游是 OpenAI 兼容:`["claude", "openai"]`
|
||||
- 用户发送 Claude 格式,上游是 Gemini:`["claude", "openai", "gemini"]`(链式转换)
|
||||
|
||||
`FinalRequestRelayFormat` 记录最终发送到上游的格式。
|
||||
|
||||
---
|
||||
|
||||
## 五、核心转换实现
|
||||
|
||||
### 5.1 核心转换服务层 — `service/convert.go` (~1007 行)
|
||||
|
||||
这是整个项目的**中心格式转换库**,包含 OpenAI ↔ Claude、OpenAI ↔ Gemini 的双向转换函数:
|
||||
|
||||
| 函数 | 转换方向 | 位置 |
|
||||
|---|---|---|
|
||||
| `ClaudeToOpenAIRequest()` | Claude 请求 → OpenAI 请求 | line 17 |
|
||||
| `GeminiToOpenAIRequest()` | Gemini 请求 → OpenAI 请求 | line 658 |
|
||||
| `ResponseOpenAI2Claude()` | OpenAI 响应 → Claude 响应 | line 607 |
|
||||
| `StreamResponseOpenAI2Claude()` | OpenAI 流式 → Claude 流式 | line 255 |
|
||||
| `ResponseOpenAI2Gemini()` | OpenAI 响应 → Gemini 响应 | line 828 |
|
||||
| `StreamResponseOpenAI2Gemini()` | OpenAI 流式 → Gemini 流式 | line 907 |
|
||||
|
||||
### 5.2 Claude 适配器 — `relay/channel/claude/`
|
||||
|
||||
| 文件 | 行数 | 功能 |
|
||||
|---|---|---|
|
||||
| `relay-claude.go` | ~1009 | Claude 原生请求/响应转换 + 流式处理 |
|
||||
| `adaptor.go` | ~134 | 适配器实现 |
|
||||
| `dto.go` | — | Claude DTO 定义 |
|
||||
| `constants.go` | — | Claude 模型列表 |
|
||||
|
||||
**关键转换函数**:
|
||||
- `RequestOpenAI2ClaudeMessage()` — OpenAI→Claude 请求转换 (line 47): 工具转换 (function→input_schema)、Web Search 工具、tool_choice 映射 (required→any, named→tool)、parallel_tool_calls→disable_parallel_tool_use、Thinking adapter (Opus 4.6/4.7 adaptive/enabled 模式、ReasoningEffort→BudgetTokens 映射)、OpenRouter reasoning 参数覆盖、消息角色映射、媒体内容 (image/PDF→base64 source)
|
||||
- `StreamResponseClaude2OpenAI()` / `ResponseClaude2OpenAI()` — Claude→OpenAI 响应转换
|
||||
- `mapToolChoice()` — OpenAI tool_choice → Claude tool_choice
|
||||
|
||||
### 5.3 Gemini 适配器 — `relay/channel/gemini/`
|
||||
|
||||
| 文件 | 行数 | 功能 |
|
||||
|---|---|---|
|
||||
| `relay-gemini.go` | ~1900 | Gemini 原生请求/响应转换 + Thinking adapter + 原生直通处理 |
|
||||
| `adaptor.go` | ~287 | 适配器实现,支持多级链式转换 |
|
||||
| `relay-gemini-native.go` | 97 | Gemini 原生格式直通处理 |
|
||||
|
||||
**关键转换函数**:
|
||||
- `CovertOpenAI2Gemini()` — OpenAI→Gemini 请求转换 (line 201): GenerationConfig 映射、ThinkingAdaptor (thinking 后缀/budget clamp/effort level)、安全设置、工具转换 (tools→functionDeclarations + googleSearch/codeExecution/urlContext)、tool_choice→Gemini ToolConfig、ResponseFormat→responseMimeType+responseSchema、角色映射 (assistant→model, system→SystemInstructions)、Markdown 图片检测、ThoughtSignature bypass、Schema 清理
|
||||
- `ThinkingAdaptor()` — Thinking 配置适配 (line 134): 支持 `-thinking`、`-thinking-<budget>`、`-nothinking` 后缀,model-specific budget clamp
|
||||
- `responseGeminiChat2OpenAI()` / `streamResponseGeminiChat2OpenAI()` — Gemini→OpenAI 响应转换
|
||||
|
||||
**Gemini 适配器的链式转换支持**:
|
||||
- `ConvertClaudeRequest()`: 先通过 OpenAI 适配器 Claude→OpenAI,再 ConvertOpenAIRequest() 转 Gemini
|
||||
- `DoResponse()`: 先 Gemini→OpenAI,再根据客户端格式转 Claude/Gemini 输出
|
||||
|
||||
### 5.4 OpenAI 适配器 — `relay/channel/openai/`
|
||||
|
||||
| 文件 | 行数 | 功能 |
|
||||
|---|---|---|
|
||||
| `adaptor.go` | ~683 | OpenAI 适配器实现,含 Claude/Gemini→OpenAI 入口 |
|
||||
| `relay-openai.go` | ~718 | OpenAI 响应处理,含多格式输出分发 |
|
||||
| `helper.go` | ~261 | 流式格式分发器 `HandleStreamFormat()` |
|
||||
| `chat_via_responses.go` | ~550 | Chat Completions via Responses API 模式 |
|
||||
| `relay_responses.go` | ~150 | Responses API 原生处理 |
|
||||
| `relay_responses_compact.go` | ~44 | Responses Compact API 处理 |
|
||||
|
||||
**`HandleStreamFormat()`** — 流式响应核心分发器 (helper.go line 22):
|
||||
```go
|
||||
switch info.RelayFormat {
|
||||
case types.RelayFormatClaude:
|
||||
handleClaudeFormat(c, data, info) // → service.StreamResponseOpenAI2Claude
|
||||
case types.RelayFormatGemini:
|
||||
handleGeminiFormat(c, data, info) // → service.StreamResponseOpenAI2Gemini
|
||||
default:
|
||||
sendStreamData(c, data) // 直接透传 OpenAI 格式 (含 forceFormat/thinkToContent)
|
||||
}
|
||||
```
|
||||
|
||||
### 5.5 Chat Completions ↔ Responses API 转换 — `service/openaicompat/`
|
||||
|
||||
| 文件 | 行数 | 功能 |
|
||||
|---|---|---|
|
||||
| `chat_to_responses.go` | ~402 | Chat Completions → Responses API |
|
||||
| `responses_to_chat.go` | ~133 | Responses API → Chat Completions |
|
||||
| `policy.go` | 19 | 基于正则的策略路由:判断是否将 Chat 请求路由到 Responses API |
|
||||
|
||||
**Chat-via-Responses 优化**: 当配置开启时(通过正则策略匹配模型名),系统将 Chat Completions 请求内部转换为 Responses API 格式发送,再将响应转回 Chat 格式。这允许在不改变客户端 API 的前提下利用 Responses API 的独有特性(reasoning summaries、built-in tools)。
|
||||
|
||||
### 5.6 其他提供商适配器
|
||||
|
||||
| 提供商 | 转换逻辑 |
|
||||
|---|---|
|
||||
| **阿里 (ali/)** | OpenAI→DashScope 格式;Claude 先→OpenAI→阿里;支持 qwen 模型 Claude 兼容;异步图片生成 (X-DashScope-Async) |
|
||||
| **AWS Bedrock (aws/)** | OpenAI→Claude 格式(通过 claude 包转换);支持 Nova 模型特殊处理;API Key + AKSK 双认证模式 |
|
||||
| **Ollama (ollama/)** | OpenAI→Ollama `/api/chat` 或 `/api/generate`;Claude 先→OpenAI→Ollama |
|
||||
| **百度 (baidu/, baidu_v2/)** | OpenAI→百度文心格式 |
|
||||
| **智谱 (zhipu/, zhipu_4v/)** | OpenAI→智谱 GLM 格式 |
|
||||
| **讯飞 (xunfei/)** | OpenAI→讯飞星火格式 |
|
||||
| **腾讯 (tencent/)** | OpenAI→腾讯混元格式 |
|
||||
| **火山引擎 (volcengine/)** | OpenAI→火山引擎格式 |
|
||||
| **Vertex AI (vertex/)** | 继承 Gemini 适配器,添加 Google Cloud 认证 |
|
||||
| **DeepSeek / Mistral** | OpenAI 兼容(基础直通) |
|
||||
|
||||
---
|
||||
|
||||
## 六、详细转换流程分析
|
||||
|
||||
### 6.1 场景一:用户发送 OpenAI 格式,上游是 Claude
|
||||
|
||||
**请求路径**: `POST /v1/chat/completions` → Claude 上游
|
||||
|
||||
```
|
||||
1. 路由层: RelayFormatOpenAI → controller.Relay()
|
||||
2. 控制器: relayHandler() → relay.TextHelper()
|
||||
3. TextHelper():
|
||||
a. 解析请求 → dto.GeneralOpenAIRequest
|
||||
b. GetAdaptor(APITypeAnthropic) → claude.Adaptor
|
||||
c. adaptor.ConvertOpenAIRequest() → RequestOpenAI2ClaudeMessage()
|
||||
- 角色映射、工具转换、thinking adapter、参数映射
|
||||
d. 发送到 Claude /v1/messages 端点
|
||||
4. DoResponse():
|
||||
- 流式: ClaudeStreamHandler() → StreamResponseClaude2OpenAI()
|
||||
- 非流式: ClaudeHandler() → ResponseClaude2OpenAI()
|
||||
转换链: ["openai", "claude"]
|
||||
```
|
||||
|
||||
### 6.2 场景二:用户发送 Claude 格式,上游是 Gemini
|
||||
|
||||
**请求路径**: `POST /v1/messages` → Gemini 上游
|
||||
|
||||
```
|
||||
1. 路由层: RelayFormatClaude → controller.Relay()
|
||||
2. 控制器: ClaudeHelper()
|
||||
3. ClaudeHelper():
|
||||
a. 解析请求 → dto.ClaudeRequest
|
||||
b. Thinking adapter (Opus 模型)
|
||||
c. 可选: Chat-via-Responses 桥接
|
||||
d. GetAdaptor(APITypeGemini) → gemini.Adaptor
|
||||
e. adaptor.ConvertClaudeRequest():
|
||||
- 第一步: openai.Adaptor.ConvertClaudeRequest() → ClaudeToOpenAIRequest()
|
||||
- 第二步: CovertOpenAI2Gemini() → Gemini 格式
|
||||
- 转换链: ["claude", "openai", "gemini"]
|
||||
f. 发送到 Gemini generateContent 端点
|
||||
4. DoResponse():
|
||||
- 流式: GeminiChatStreamHandler() → streamResponseGeminiChat2OpenAI()
|
||||
再根据客户端格式: service.StreamResponseOpenAI2Claude()
|
||||
- 非流式: GeminiChatHandler() → responseGeminiChat2OpenAI()
|
||||
再根据客户端格式: service.ResponseOpenAI2Claude()
|
||||
```
|
||||
|
||||
### 6.3 场景三:用户发送 Gemini 格式,上游是 OpenAI
|
||||
|
||||
**请求路径**: `POST /v1beta/models/gemini-pro:generateContent` → OpenAI 上游
|
||||
|
||||
```
|
||||
1. 路由层: RelayFormatGemini → GeminiHelper()
|
||||
2. GeminiHelper():
|
||||
a. 解析请求 → dto.GeminiChatRequest
|
||||
b. Thinking adapter
|
||||
c. adaptor.ConvertGeminiRequest(): Gemini→OpenAI (GeminiToOpenAIRequest)
|
||||
d. 发送到 OpenAI /v1/chat/completions
|
||||
3. DoResponse():
|
||||
- OpenAI 响应 → Gemini 格式 (ResponseOpenAI2Gemini / StreamResponseOpenAI2Gemini)
|
||||
转换链: ["gemini", "openai"]
|
||||
```
|
||||
|
||||
### 6.4 场景四:Chat Completions 经由 Responses API
|
||||
|
||||
```
|
||||
1. POST /v1/chat/completions
|
||||
2. TextHelper() 检测到 ShouldChatCompletionsUseResponsesGlobal() 为 true
|
||||
3. chatCompletionsViaResponses():
|
||||
a. ChatCompletionsRequestToResponsesRequest() — Chat → Responses API
|
||||
b. adaptor.ConvertOpenAIResponsesRequest() — 转换为上游格式
|
||||
c. 发送请求到上游 /v1/responses
|
||||
d. OaiResponsesToChatHandler() / OaiResponsesToChatStreamHandler() — Responses → Chat
|
||||
e. 如果客户端格式是 Claude/Gemini,继续转换为对应格式
|
||||
转换链: ["openai", "openai_responses"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、特殊功能与高级特性
|
||||
|
||||
### 7.1 Pass-Through 模式
|
||||
|
||||
当全局 `PassThroughRequestEnabled` 或渠道 `PassThroughBodyEnabled` 启用时,请求体直接透传到上游,跳过所有格式转换。
|
||||
|
||||
### 7.2 字段过滤 (RemoveDisabledFields)
|
||||
|
||||
根据渠道安全设置过滤敏感字段: `service_tier`、`inference_geo`、`speed`、`store`、`safety_identifier`、`stream_options.include_obfuscation`。
|
||||
|
||||
### 7.3 参数覆写 (ParamOverride)
|
||||
|
||||
通过 `relay/common/override.go` 支持请求参数覆写(如强制 temperature、max_tokens)。
|
||||
|
||||
### 7.4 模型名称映射
|
||||
|
||||
支持将用户请求的模型名称映射为上游实际模型名称(渠道级配置)。
|
||||
|
||||
### 7.5 Thinking/Reasoning 适配
|
||||
|
||||
- **Claude**: `-thinking` 后缀 → 启用 extended thinking + BudgetTokens;Opus 4.6/4.7 adaptive 模式
|
||||
- **Gemini**: `ThinkingAdaptor()` 支持 `-thinking`、`-thinking-<budget>`、`-nothinking` 后缀;model-specific budget clamp
|
||||
- **OpenAI**: o-series 模型 → `-high/-medium/-low` 推理力度后缀
|
||||
|
||||
### 7.6 Thinking-to-Content 转换
|
||||
|
||||
渠道设置 `ThinkingToContent` 启用时,将 reasoning content 转换为带有 `<think\>...</think\>` 标签的普通文本内容,供不支持 reasoning 字段的客户端使用。
|
||||
|
||||
### 7.7 StreamOptions 适配
|
||||
|
||||
对支持 `stream_options` 的渠道自动添加 `include_usage: true` 以获取流式用量信息。
|
||||
|
||||
### 7.8 SSE Ping Keep-Alive
|
||||
|
||||
内置 ping 机制保持长时间流式连接活跃。
|
||||
|
||||
### 7.9 Header 覆写/透传
|
||||
|
||||
复杂的 Header 管理系统:支持占位符替换 (`{api_key}`, `{client_header:name}`)、正则规则透传、渠道级覆写。
|
||||
|
||||
### 7.10 异步任务适配器 (TaskAdaptor)
|
||||
|
||||
对视频/音乐等异步生成任务使用独立的 `TaskAdaptor` 接口,支持:任务提交、轮询、计费估算。覆盖平台:Suno、Kling、Jimeng、Vidu、Doubao、Sora、Gemini、Vertex AI、Hailuo 等。
|
||||
|
||||
---
|
||||
|
||||
## 八、转换矩阵总结
|
||||
|
||||
### 请求转换矩阵
|
||||
|
||||
| 客户端 \ 上游 | OpenAI | Claude | Gemini | Ali | AWS | Ollama |
|
||||
|---|---|---|---|---|---|---|
|
||||
| **OpenAI** | 直通 | OpenAI→Claude | OpenAI→Gemini | OpenAI→Ali | OpenAI→Claude(Bedrock) | OpenAI→Ollama |
|
||||
| **Claude** | Claude→OpenAI | 直通 | Claude→OpenAI→Gemini | Claude→OpenAI→Ali | 直通 | Claude→OpenAI→Ollama |
|
||||
| **Gemini** | Gemini→OpenAI | Gemini→OpenAI→Claude | 直通 | × | × | × |
|
||||
|
||||
### 响应转换矩阵
|
||||
|
||||
| 上游 \ 客户端 | OpenAI | Claude | Gemini |
|
||||
|---|---|---|---|
|
||||
| **OpenAI** | 直通 | OpenAI→Claude | OpenAI→Gemini |
|
||||
| **Claude** | Claude→OpenAI | 直通 | Claude→OpenAI→Gemini |
|
||||
| **Gemini** | Gemini→OpenAI | Gemini→OpenAI→Claude | 直通 |
|
||||
| **Ali/Ollama/其他** | →OpenAI | →OpenAI→Claude | × |
|
||||
|
||||
---
|
||||
|
||||
## 九、关键文件索引
|
||||
|
||||
| 文件路径 | 行数 | 功能 |
|
||||
|---|---|---|
|
||||
| `relay/channel/adapter.go` | 83 | Adaptor/TaskAdaptor 接口定义 |
|
||||
| `relay/relay_adaptor.go` | 165 | 适配器工厂函数 GetAdaptor/GetTaskAdaptor |
|
||||
| `types/relay_format.go` | 19 | RelayFormat 类型定义 |
|
||||
| `constant/api_type.go` | 40 | API 类型常量 (35种) |
|
||||
| `service/convert.go` | ~1007 | **核心转换库** (OpenAI↔Claude↔Gemini) |
|
||||
| `relay/channel/claude/relay-claude.go` | ~1009 | Claude 原生格式转换 |
|
||||
| `relay/channel/gemini/relay-gemini.go` | ~1900 | Gemini 原生格式转换 + Thinking adapter |
|
||||
| `relay/channel/gemini/relay-gemini-native.go` | 97 | Gemini 原生直通处理 |
|
||||
| `relay/channel/openai/adaptor.go` | ~683 | OpenAI 适配器 (含 Claude/Gemini 入口) |
|
||||
| `relay/channel/openai/helper.go` | ~261 | 流式格式分发器 HandleStreamFormat |
|
||||
| `relay/channel/openai/relay-openai.go` | ~718 | OpenAI 响应处理 (含 WebSocket 代理) |
|
||||
| `relay/channel/openai/chat_via_responses.go` | ~550 | Chat→Responses 内部路由 |
|
||||
| `service/openaicompat/chat_to_responses.go` | ~402 | Chat→Responses 转换 |
|
||||
| `service/openaicompat/responses_to_chat.go` | ~133 | Responses→Chat 转换 |
|
||||
| `relay/common/relay_info.go` | ~890 | RelayInfo 上下文对象 |
|
||||
| `relay/common/request_conversion.go` | 40 | 转换链跟踪 |
|
||||
| `controller/relay.go` | ~647 | 主控制器 (含重试循环) |
|
||||
| `router/relay-router.go` | 224 | 路由定义 |
|
||||
| `relay/compatible_handler.go` | 217 | OpenAI 格式文本请求处理 (TextHelper) |
|
||||
| `relay/claude_handler.go` | 214 | Claude 格式请求处理 (ClaudeHelper) |
|
||||
| `relay/gemini_handler.go` | 293 | Gemini 格式请求处理 (GeminiHelper) |
|
||||
| `relay/responses_handler.go` | 161 | Responses API 处理 |
|
||||
| `relay/chat_completions_via_responses.go` | 161 | Chat-via-Responses 桥接处理 |
|
||||
|
||||
---
|
||||
|
||||
## 十、总结
|
||||
|
||||
`new-api` 的转换层是一个**多协议 Hub-and-Spoke API 网关转换系统**,核心特点:
|
||||
|
||||
1. **Hub-and-Spoke 架构**: 以 OpenAI 格式为枢纽,避免 O(n²) 的转换矩阵,通过链式转换支持任意输入/输出格式组合
|
||||
2. **多格式输入**: 同一上游提供商可接受 OpenAI、Claude、Gemini 三种主流格式,通过 `RequestConversionChain` 跟踪转换路径
|
||||
3. **统一适配器接口**: `channel.Adaptor` 接口抽象所有提供商差异,新提供商只需实现该接口
|
||||
4. **Chat-via-Responses 优化**: 在不改变客户端 API 的前提下内部路由到 Responses API,利用其独有特性
|
||||
5. **Thinking 深度适配**: Claude/Gemini/OpenAI 三种 thinking/reasoning 模式均有完善的参数适配
|
||||
6. **流式实时转换**: SSE 流式响应逐块格式转换,包括复杂的状态机管理
|
||||
7. **异步任务支持**: 独立 `TaskAdaptor` 接口覆盖视频/音乐生成等异步场景
|
||||
8. **计费深度集成**: 转换层与预扣费、结算、退款等完整计费生命周期集成
|
||||
Reference in New Issue
Block a user