# One-API 项目转换层深度分析报告

## 一、项目概览

One-API 是一个基于 Go 语言（Gin 框架）开发的大模型 API 网关代理项目。其核心功能是：**将用户发来的统一 OpenAI 格式请求，转换为各家大模型厂商的原生 API 格式，转发请求后，再将厂商的响应统一转换回 OpenAI 格式返回给用户**。

对外暴露的接口完全兼容 OpenAI API 规范，用户只需更改 `base_url` 和 `api_key` 即可使用。

### 与同类项目的核心差异

One-API 是此类项目的**鼻祖和基线**，采用最简单的架构模式——仅支持 OpenAI 格式作为唯一输入/输出协议，所有转换都是 **OpenAI ↔ 厂商原生格式** 的双向转换。New-API 在其基础上增加了 Claude/Gemini 输入支持和 Hub-and-Spoke 架构。One-API 的设计追求简洁实用：56 种渠道类型通过三层映射归并为 19 种 API 类型，其中 18 种 OpenAI 兼容渠道直接复用同一适配器，实现零开销透传。

---

## 二、项目目录结构

```
one-api/
├── main.go                    # 程序入口
├── router/
│   └── relay.go               # 路由定义（/v1/chat/completions 等）
├── middleware/
│   ├── auth.go                # Token 认证
│   ├── distributor.go         # 渠道分发（负载均衡）
│   └── rate-limit.go          # 限流
├── controller/
│   └── relay.go               # 入口控制器（含重试逻辑）
├── relay/                     # ★ 转换层核心目录
│   ├── adaptor.go             # Adaptor 工厂函数 (69行)
│   ├── adaptor/               # 各厂商 Adaptor 实现
│   │   ├── interface.go       # Adaptor 接口定义 (9方法)
│   │   ├── common.go          # 公共辅助函数
│   │   ├── openai/            # OpenAI 适配器（基座）
│   │   ├── anthropic/         # Anthropic Claude 适配器
│   │   ├── gemini/            # Google Gemini 适配器
│   │   ├── geminiv2/          # Gemini V2 模型适配器
│   │   ├── ali/               # 阿里通义千问适配器
│   │   ├── baidu/             # 百度文心适配器
│   │   ├── zhipu/             # 智谱 ChatGLM 适配器
│   │   ├── tencent/           # 腾讯混元适配器
│   │   ├── xunfei/            # 讯飞星火适配器
│   │   ├── aws/               # AWS Bedrock Claude 适配器 (含子适配器)
│   │   │   ├── claude/        #   Claude on Bedrock
│   │   │   └── llama3/        #   Llama3 on Bedrock
│   │   ├── vertexai/          # Google Vertex AI (含子适配器)
│   │   │   ├── claude/        #   Claude on Vertex AI
│   │   │   └── gemini/        #   Gemini on Vertex AI
│   │   ├── ollama/            # Ollama 适配器
│   │   ├── coze/              # Coze 适配器
│   │   ├── cohere/            # Cohere 适配器
│   │   ├── cloudflare/        # Cloudflare Workers AI 适配器
│   │   ├── deepl/             # DeepL 翻译适配器
│   │   ├── replicate/         # Replicate 适配器
│   │   ├── palm/              # Google PaLM 适配器
│   │   ├── proxy/             # 通用代理适配器
│   │   ├── aiproxy/           # AIProxy 适配器
│   │   └── ... (38个子目录)
│   ├── controller/            # 中转控制器（按功能分类）
│   │   ├── text.go            # 文本类请求处理 (115行)
│   │   ├── image.go           # 图片生成请求处理 (238行)
│   │   ├── audio.go           # 音频请求处理 (281行)
│   │   ├── proxy.go           # 通用代理请求处理
│   │   ├── helper.go          # 辅助函数（配额、计费等）
│   │   └── error.go           # 统一错误处理
│   ├── meta/
│   │   └── relay_meta.go      # 请求元数据结构 (66行)
│   ├── model/                 # 内部数据模型
│   │   ├── general.go         # 统一 OpenAI 请求结构 (88行)
│   │   ├── message.go         # 消息结构（支持多模态） (91行)
│   │   ├── misc.go            # Usage、Error 等通用结构 (27行)
│   │   ├── tool.go            # Tool/Function Calling 结构
│   │   └── image.go           # 图片请求结构
│   ├── apitype/
│   │   └── define.go          # API 类型枚举 (19种)
│   ├── channeltype/
│   │   ├── define.go          # 渠道类型枚举 (56种)
│   │   ├── helper.go          # ChannelType → APIType 映射
│   │   └── url.go             # 各渠道默认 BaseURL (52条)
│   ├── relaymode/
│   │   ├── define.go          # 中转模式枚举 (11种)
│   │   └── helper.go          # URL 路径 → 中转模式映射
│   └── billing/               # 计费相关
└── model/                     # 数据库模型
    ├── channel.go             # 渠道配置
    └── ...
```

---

## 三、转换层技术架构

### 3.1 整体架构图

```
                    ┌─────────────────────────────────────────┐
                    │         用户请求 (OpenAI 格式)            │
                    │   POST /v1/chat/completions              │
                    └──────────────────┬──────────────────────┘
                                       │
                    ┌──────────────────▼──────────────────────┐
                    │           router/relay.go                │
                    │   路由: /v1/* → controller.Relay         │
                    └──────────────────┬──────────────────────┘
                                       │
                    ┌──────────────────▼──────────────────────┐
                    │          middleware (中间件链)             │
                    │  CORS → GzipDecode → PanicRecover        │
                    │  → TokenAuth → Distribute                │
                    │  1. 解析 Token, 验证身份                   │
                    │  2. 根据模型名选择渠道(随机负载均衡)         │
                    │  3. 将渠道信息注入 gin.Context             │
                    └──────────────────┬──────────────────────┘
                                       │
                    ┌──────────────────▼──────────────────────┐
                    │         controller/relay.go              │
                    │  1. 根据 URL 判断 relayMode               │
                    │  2. 调用 relayHelper 分发                  │
                    │  3. 失败时自动重试(切换渠道)                │
                    └──────────────────┬──────────────────────┘
                                       │
              ┌────────────────────────┼────────────────────────┐
              │                        │                        │
    ┌─────────▼──────────┐  ┌─────────▼──────────┐  ┌─────────▼──────────┐
    │ RelayTextHelper    │  │ RelayImageHelper   │  │ RelayAudioHelper   │
    │ text.go (115行)    │  │ image.go (238行)   │  │ audio.go (281行)   │
    └─────────┬──────────┘  └─────────┬──────────┘  └─────────┬──────────┘
              │                        │                        │
              └────────────────────────┼────────────────────────┘
                                       │
                    ┌──────────────────▼──────────────────────┐
                    │        relay/adaptor.go                  │
                    │  GetAdaptor(apiType) → 具体Adaptor实例     │
                    └──────────────────┬──────────────────────┘
                                       │
              ┌────────────────────────┼────────────────────────┐
              │                        │                        │
    ┌─────────▼──────────┐  ┌─────────▼──────────┐  ┌─────────▼──────────┐
    │ openai.Adaptor     │  │ anthropic.Adaptor  │  │ gemini.Adaptor     │
    │ ConvertRequest()   │  │ ConvertRequest()   │  │ ConvertRequest()   │
    │ DoRequest()        │  │ DoRequest()        │  │ DoRequest()        │
    │ DoResponse()       │  │ DoResponse()       │  │ DoResponse()       │
    └─────────┬──────────┘  └─────────┬──────────┘  └─────────┬──────────┘
              │                        │                        │
              └────────────────────────┼────────────────────────┘
                                       │
                    ┌──────────────────▼──────────────────────┐
                    │         上游大模型厂商 API                 │
                    └─────────────────────────────────────────┘
```

### 3.2 核心设计模式：适配器模式

**Adaptor 接口** (`relay/adaptor/interface.go`, 21 行):

```go
type Adaptor interface {
    Init(meta *meta.Meta)                                    // 初始化元数据
    GetRequestURL(meta *meta.Meta) (string, error)           // 构建请求 URL
    SetupRequestHeader(c, req, meta) error                   // 设置认证请求头
    ConvertRequest(c, mode, request) (any, error)            // 请求体转换 (OpenAI → 厂商)
    ConvertImageRequest(request) (any, error)                // 图片请求转换
    DoRequest(c, meta, requestBody) (*http.Response, error)  // 发送 HTTP 请求
    DoResponse(c, resp, meta) (usage, err)                   // 响应体转换 (厂商 → OpenAI)
    GetModelList() []string                                  // 返回支持的模型列表
    GetChannelName() string                                  // 返回渠道名称
}
```

**9 个方法**构成最精简的适配器接口，相比 New-API 的 15+ 方法接口更聚焦。

### 3.3 三层映射关系

项目通过三层映射将"渠道"与"转换逻辑"关联：

```
ChannelType (渠道类型)  →  APIType (API 类型)  →  Adaptor (适配器实例)
     (56 种)                  (19 种)                 (18 个实现)
```

- **ChannelType**: 具体的厂商/服务商标识（56 种）
- **APIType**: 共享同一套转换逻辑的分组（19 种，定义在 `relay/apitype/define.go`）
- **Adaptor**: 负责具体转换逻辑的实例

**映射代码**: `relay/channeltype/helper.go` 的 `ToAPIType()` 函数。

**关键设计**: 18 种 OpenAI 兼容渠道的 APIType 被映射为 `apitype.OpenAI`，直接复用 `openai.Adaptor`，无需编写独立转换逻辑。兼容渠道列表 (`relay/adaptor/openai/compatible.go`):

```go
var CompatibleChannels = []int{
    Azure, AI360, Moonshot, Baichuan, Minimax, Doubao,
    Mistral, Groq, LingYiWanWu, StepFun, DeepSeek, TogetherAI,
    Novita, SiliconFlow, XAI, BaiduV2, XunfeiV2,
}
```

另有 OpenRouter、AliBailian、GeminiOpenAICompatible 也有特殊映射处理。

### 3.4 Adaptor 工厂

**文件**: `relay/adaptor.go` (69 行)

`GetAdaptor(apiType int)` 映射 18 种 API 类型到具体适配器实例（Proxy 类型额外处理）。

---

## 四、请求处理完整流程

### 4.1 路由阶段

**文件**: `router/relay.go` (74 行)

所有 `/v1/` 下的请求都经过中间件链：`CORS() → GzipDecodeMiddleware() → RelayPanicRecover → TokenAuth → Distribute`

### 4.2 中间件阶段

#### Token 认证 (middleware/auth.go, 167 行)
- 从 `Authorization` 头提取 `Bearer <token>`
- 管理员可通过 `sk-<token>-<channelId>` 指定特定渠道
- 验证 Token 有效性，提取 userId、tokenId
- 从请求体解析 `model` 字段，验证模型可用性
- 支持 IP 子网限制

#### 渠道分发 (middleware/distributor.go, 102 行)
- 获取用户分组 (group)
- 根据 group + model 随机选择一个可用渠道
- 将渠道信息注入 `gin.Context`：渠道类型、API Key、BaseURL、ModelMapping 等
- 渠道类型转换为 APIType，存入 meta

### 4.3 控制器阶段

**文件**: `controller/relay.go` (156 行)

```go
func Relay(c *gin.Context) {
    relayMode := relaymode.GetByPath(c.Request.URL.Path)
    bizErr := relayHelper(c, relayMode)
    // 失败时自动重试：切换到其他渠道
    for i := retryTimes; i > 0; i-- {
        channel := CacheGetRandomSatisfiedChannel(group, model)
        SetupContextForSelectedChannel(c, channel, model)
        bizErr = relayHelper(c, relayMode)
    }
}
```

`relayHelper` 根据 `relayMode` 分发：
- `ChatCompletions / Completions / Embeddings / Moderations` → `RelayTextHelper`
- `ImagesGenerations` → `RelayImageHelper`
- `AudioSpeech / AudioTranscription / AudioTranslation` → `RelayAudioHelper`
- `Proxy` → `RelayProxyHelper`

**重试策略**: 429 和 5xx 触发重试，400 和 2xx 不重试。管理员指定渠道时不重试。

### 4.4 转换处理阶段 — RelayTextHelper

**文件**: `relay/controller/text.go` (115 行)

```go
func RelayTextHelper(c *gin.Context) *model.ErrorWithStatusCode {
    // 1. 解析请求（统一按 OpenAI 格式解析）
    meta := meta.GetByContext(c)
    textRequest := getAndValidateTextRequest(c, meta.Mode)

    // 2. 模型名称映射
    textRequest.Model = getMappedModelName(textRequest.Model, meta.ModelMapping)

    // 3. 强制系统提示词注入
    setSystemPrompt(textRequest, meta)

    // 4. 计算配额、预扣费
    promptTokens := getPromptTokens(textRequest, meta.Mode)
    preConsumedQuota := preConsumeQuota(...)  // 用户配额 > 100x预扣时跳过

    // 5. 获取对应 Adaptor
    adaptor := relay.GetAdaptor(meta.APIType)
    adaptor.Init(meta)

    // 6. 请求转换（OpenAI 格式 → 厂商格式）
    requestBody := getRequestBody(c, meta, textRequest, adaptor)

    // 7. 发送请求到上游
    resp := adaptor.DoRequest(c, meta, requestBody)

    // 8. 响应转换（厂商格式 → OpenAI 格式）
    usage := adaptor.DoResponse(c, resp, meta)

    // 9. 后扣费
    postConsumeQuota(usage, ...)
}
```

#### 请求体透传优化

**文件**: `relay/controller/text.go` 的 `getRequestBody()` 函数

当满足以下所有条件时，**跳过请求转换**，直接透传原始请求体：
- API 类型为 OpenAI
- 模型名未被映射
- 渠道不是百川（百川有特殊处理）
- 无强制系统提示词
- 未启用 include_usage 强制选项

```go
if meta.APIType == apitype.OpenAI &&
    meta.OriginModelName == meta.ActualModelName &&
    meta.ChannelType != channeltype.Baichuan &&
    meta.ForcedSystemPrompt == "" {
    return c.Request.Body, nil  // 直接透传，零开销
}
```

---

## 五、各厂商转换逻辑详解

### 5.1 OpenAI 适配器（基座）

**文件**: `relay/adaptor/openai/` (9 文件)

作为项目的"基座适配器"，不仅处理 OpenAI 自身，还被 18 种 OpenAI 兼容渠道复用。

**请求转换**: 基本不需要格式转换，直接透传 `GeneralOpenAIRequest`。唯一处理：流式模式下自动注入 `stream_options.include_usage = true`。

**URL 构建**: 根据渠道类型有不同逻辑：
- 标准 OpenAI 兼容: `BaseURL + RequestURLPath`
- Azure: `/openai/deployments/{model}/{task}?api-version=xxx`
- Minimax/Doubao/Novita/BaiduV2/AliBailian/GeminiOpenAICompatible: 各有独立 URL 逻辑

**认证方式**:
- 标准渠道: `Authorization: Bearer <api_key>`
- Azure: `api-key: <api_key>`
- OpenRouter: 额外 `HTTP-Referer` 和 `X-Title` 头

**流式处理**: 逐行解析 SSE (`data: {...}`)，提取 usage 信息，支持 Cloudflare AI Gateway URL。

### 5.2 Anthropic Claude 适配器

**文件**: `relay/adaptor/anthropic/` (4 文件, main.go 379 行)

Claude 使用完全不同的 API 格式，需要大量转换工作。

**请求转换** (main.go `ConvertRequest()`):

| OpenAI 字段 | Claude 字段 | 转换说明 |
|---|---|---|
| `messages[].role = "system"` | `system` (顶层字段) | 系统提示词提取到顶层 |
| `messages[].content` (string) | `messages[].content` (Content 数组) | 包装为 `[{type:"text", text:"..."}]` |
| `messages[].role = "tool"` | `messages[].role = "user"` + `type = "tool_result"` | 工具结果转为用户消息 |
| `messages[].tool_calls` | `content.type = "tool_use"` | 工具调用转为 content 块 |
| `tools[].function.parameters` | `tools[].input_schema` | 字段名转换 |
| `tool_choice` | `tool_choice.type + name` | auto/tool/any 格式映射 |
| `max_tokens` | `max_tokens` | 直接映射，默认 4096 |

**认证**: `x-api-key: <api_key>` + `anthropic-version: 2023-06-01`。Claude 3.5 Sonnet 额外添加 `anthropic-beta: max-tokens-3-5-sonnet-2024-07-15`。

**URL**: `{base_url}/v1/messages`

**响应转换**:

| Claude 字段 | OpenAI 字段 |
|---|---|
| `content[].text` | `choices[].message.content` |
| `content[].type = "tool_use"` | `choices[].message.tool_calls[]` |
| `stop_reason: "end_turn"/"stop_sequence"` | `finish_reason: "stop"` |
| `stop_reason: "max_tokens"` | `finish_reason: "length"` |
| `stop_reason: "tool_use"` | `finish_reason: "tool_calls"` |
| `usage.input_tokens/output_tokens` | `usage.prompt_tokens/completion_tokens` |

**流式处理**: Claude 的 SSE 事件类型（`message_start`、`content_block_start`、`content_block_delta`、`message_delta`）逐事件转换为 OpenAI 的 `chat.completion.chunk` 格式。

### 5.3 Google Gemini 适配器

**文件**: `relay/adaptor/gemini/` (4 文件, main.go 437 行)

**请求转换**:

| OpenAI 字段 | Gemini 字段 | 转换说明 |
|---|---|---|
| `messages[]` | `contents[]` | 数组结构转换 |
| `role = "assistant"` | `role = "model"` | 角色名映射 |
| `role = "system"` | `systemInstruction` 或 `role = "user"` | 新模型用 systemInstruction，旧模型转 user |
| `tools[].function` | `tools[].functionDeclarations[]` | 字段名转换 |
| `temperature/top_p/max_tokens` | `generationConfig.{temperature, topP, maxOutputTokens}` | 包装到 generationConfig |
| `response_format.type = "json_object"` | `responseMimeType = "application/json"` | MIME 类型映射 |

**特殊处理**:
- system 消息后自动插入 `model: "Okay"` 虚拟消息（Gemini API 要求角色交替）
- 安全设置设为最低 (`GeminiSafetySetting`，5 个类别)
- 图片数量限制最多 16 张，转为 base64 inlineData
- 支持 system instruction 的模型列表硬编码: `gemini-2.0-flash`, `gemini-2.0-flash-exp`, `gemini-2.0-flash-thinking-exp-01-21`

**URL**: `{base_url}/{version}/models/{model}:{action}`
- 版本选择: `gemini-2.0` 和 `gemini-1.5` 用 `v1beta`；其他用 `config.GeminiVersion`
- 非流式: `generateContent`
- 流式: `streamGenerateContent?alt=sse`
- Embedding: `batchEmbedContents`

**认证**: `x-goog-api-key: <api_key>`

### 5.4 阿里通义千问适配器

**文件**: `relay/adaptor/ali/` (5 文件, main.go 267 行)

使用阿里 DashScope API 格式。

**请求转换**:
- Messages 包装到 `Input.Messages`，参数包装到 `Parameters`（含 `ResultFormat: "message"`, `IncrementalOutput`, `EnableSearch`）
- 模型名后缀 `-internet` 启用联网搜索 (`EnableSearch: true`)
- `top_p` 上限为 0.9999
- 图片生成使用异步模式 (`X-DashScope-Async: enable`)，轮询等待（最多 20 步，2 秒间隔）

**URL**:
- 文本: `/api/v1/services/aigc/text-generation/generation`
- Embedding: `/api/v1/services/embeddings/text-embedding/text-embedding`
- 图片: `/api/v1/services/aigc/text2image/image-synthesis`

**特殊头**: `X-DashScope-SSE: enable` (流式), `X-DashScope-Async: enable` (异步)

### 5.5 百度文心一言适配器

**文件**: `relay/adaptor/baidu/` (4 文件, main.go 312 行)

**认证方式**: 百度不使用 API Key 直接认证，而是先通过 `client_id|client_secret` 获取 `access_token`，然后在 URL 中传递。

**access_token 缓存机制**:
- `baiduTokenStore` 使用 `sync.Map` 存储
- 缓存的 token 在过期前 1 小时触发异步刷新
- API Key 格式: `client_id|client_secret`，通过 OAuth2 端点获取 token

**请求转换**: 系统消息提取到 `System` 字段，`FrequencyPenalty` → `PenaltyScore`

**URL**: `{base_url}/rpc/2.0/ai_custom/v1/wenxinworkshop/{suffix}?access_token={token}`
- URL 中包含模型端点名称（如 `chat/completions_pro`），通过大量 switch-case 映射模型名到端点

### 5.6 智谱 ChatGLM 适配器

**文件**: `relay/adaptor/zhipu/` (4 文件)

**双版本支持**:
- **v4** (`glm-*` 模型): `/api/paas/v4/chat/completions` — **OpenAI 兼容**，直接复用 OpenAI 的 StreamHandler/Handler
- **v3**: `/api/paas/v3/model-api/{model}/{method}` — 自有格式

**认证**: JWT token（API Key 格式 `id.secret`，HMAC-SHA256 签名）

### 5.7 腾讯混元适配器

**文件**: `relay/adaptor/tencent/` (4 文件, main.go 307 行)

- URL: `{baseURL}/` (单一端点)
- 认证: **TC3-HMAC-SHA256** 签名算法（完整实现在 main.go 中）
- API Key 格式: `appId|secretId|secretKey`

### 5.8 讯飞星火适配器

**文件**: `relay/adaptor/xunfei/` (5 文件, main.go 273 行)

- **协议**: WebSocket（唯一非 HTTP 适配器）
- `GetRequestURL()` 返回空字符串，`DoRequest()` 返回 dummy 200
- `DoResponse()` 处理实际 WebSocket 通信
- 认证: HMAC-SHA256 签名的 WebSocket URL
- API Key 格式: `appId|apiSecret|apiKey` (pipe 分隔三部分)
- 流式: 使用 `c.Stream()` + SSE 格式
- 非流式: 累积所有 WebSocket chunk 后返回单次响应

### 5.9 AWS Bedrock Claude 适配器

**文件**: `relay/adaptor/aws/` (5 文件)

- 使用 **AWS SDK v2** `bedrockruntime.Client`，不走 HTTP
- **子适配器模式**: `registry.go` 根据模型名分派到 `aws/claude/` 或 `aws/llama3/`
- `aws/claude/`: 复用 `anthropic.ConvertRequest()` 转换请求，使用 Bedrock `InvokeModel`/`InvokeModelWithResponseStream` 通信
- `aws/llama3/`: Llama3 专用转换

### 5.10 Google Vertex AI 适配器

**文件**: `relay/adaptor/vertexai/` (5 文件)

- URL: `{baseURL}/v1/projects/{project}/locations/{region}/publishers/google/models/{model}:{action}`
- Claude: `rawPredict`/`streamRawPredict?alt=sse`
- Gemini: `generateContent`/`streamGenerateContent?alt=sse`
- **子适配器模式**: `registry.go` 分派到 `vertexai/claude/` 或 `vertexai/gemini/`
- `vertexai/claude/`: 复用 `anthropic.ConvertRequest()`，设置 `anthropic_version: "vertex-2023-10-16"`
- `vertexai/gemini/`: 复用 `gemini.ConvertRequest()`
- 认证: Google Cloud IAM `GenerateAccessToken` (ADC)，Token 缓存 50 分钟 TTL

### 5.11 其他适配器简述

| 适配器 | 文件 | 关键特征 |
|-------|------|---------|
| **Ollama** | `adaptor/ollama/` | 类 OpenAI 格式，`/api/chat` 或 `/api/generate` |
| **Coze** | `adaptor/coze/` | 字节跳动 Coze 平台 |
| **Cohere** | `adaptor/cohere/` | Cohere 自有 API 格式 |
| **Cloudflare** | `adaptor/cloudflare/` | Workers AI，URL 支持 Cloudflare AI Gateway |
| **DeepL** | `adaptor/deepl/` | 翻译 API，非 LLM |
| **Replicate** | `adaptor/replicate/` | 异步任务模式 |
| **PaLM** | `adaptor/palm/` | Google PaLM (旧版) |
| **Proxy** | `adaptor/proxy/` | 通用透传代理，无转换 |

---

## 六、统一数据模型

### 6.1 统一请求模型 (`relay/model/general.go`, 88 行)

```go
type GeneralOpenAIRequest struct {
    Messages            []Message       // 聊天消息
    Model               string          // 模型名
    MaxTokens           int             // 最大生成 token
    MaxCompletionTokens int             // 最大完成 token (o-series)
    Temperature         *float64        // 温度
    TopP                *float64        // Top-P
    TopK                int             // Top-K
    Stream              bool            // 流式
    StreamOptions       *StreamOptions  // 流式选项
    Tools               []Tool          // 工具调用
    ToolChoice          any             // 工具选择
    Stop                any             // 停止词
    ResponseFormat      *ResponseFormat // 响应格式
    ReasoningEffort     string          // 推理强度
    Store               *bool           // 存储标记
    // ... 更多字段
}
```

这是整个项目的"通用语言"——所有厂商的请求都先解析为此格式，再由各 Adaptor 转换为厂商格式。

### 6.2 统一消息模型 (`relay/model/message.go`, 91 行)

```go
type Message struct {
    Role             string  // system / user / assistant / tool / developer
    Content          any     // 字符串 或 多模态内容数组
    ReasoningContent any     // 推理内容 (o1 等模型)
    Name             *string // 消息发送者名称
    ToolCalls        []Tool  // 工具调用结果
    ToolCallId       string  // 工具调用 ID
}
```

`Content` 支持字符串（纯文本）和数组（多模态：text + image_url），通过 `ParseContent()` 解析。

### 6.3 统一 Usage 模型

```go
type Usage struct {
    PromptTokens     int
    CompletionTokens int
    TotalTokens      int
}
```

### 6.4 统一错误模型

所有上游错误统一转换为 OpenAI 错误格式：
```json
{"error": {"message": "...", "type": "...", "param": "...", "code": "..."}}
```

`GeneralErrorResponse` 兼容多种厂商的错误格式（OpenAI 的 `error.message`、通用的 `message`、百度的 `error_msg` 等）。

---

## 七、中转模式 (RelayMode)

**文件**: `relay/relaymode/` (2 文件)

11 种中转模式，根据 URL 路径自动判断：

| 模式 | URL 路径 | 说明 |
|------|---------|------|
| ChatCompletions | `/v1/chat/completions` | Chat 聊天补全 |
| Completions | `/v1/completions` | 文本补全 |
| Embeddings | `/v1/embeddings`, `/v1/engines/:model/embeddings` | 文本嵌入 |
| Moderations | `/v1/moderations` | 内容审核 |
| ImagesGenerations | `/v1/images/generations` | 图片生成 |
| Edits | `/v1/edits` | 文本编辑 |
| AudioSpeech | `/v1/audio/speech` | 语音合成 |
| AudioTranscription | `/v1/audio/transcriptions` | 语音识别 |
| AudioTranslation | `/v1/audio/translations` | 语音翻译 |
| Proxy | `/v1/oneapi/proxy/:channelid/*target` | 通用代理 |

判断逻辑通过 `strings.HasPrefix` 匹配。

---

## 八、关键业务逻辑

### 8.1 配额管理

"预扣费 + 后结算"机制：
1. **预扣费**: 根据 prompt tokens 和模型倍率预先扣除估算配额
2. **后结算**: 根据 usage 的实际 token 数计算费用并调整
3. 信任优化: 用户配额超过预扣费 100 倍时跳过预扣

### 8.2 自动重试

请求失败时 (429/5xx)：
1. 选择另一个不同的渠道（随机负载均衡）
2. 重新设置上下文
3. 从缓存的原始 body 重放请求
4. 最多重试 `RetryTimes` 次
5. 429 返回特殊消息"当前分组上游负载已饱和，请稍后再试"

### 8.3 错误监控

`processChannelRelayError()` 异步记录错误，并通过 `monitor.ShouldDisableChannel()` 自动禁用频繁出错的渠道。

---

## 九、流式 (SSE) 处理架构

### 9.1 统一处理流程

```
上游 SSE 流 → Scanner 逐行扫描 → 解析厂商 JSON → 转换为 OpenAI 格式 → SSE 写回客户端
```

### 9.2 各厂商 SSE 格式对比

| 厂商 | SSE 前缀 | 数据格式 | 结束标记 |
|------|---------|---------|---------|
| OpenAI | `data: ` | `ChatCompletionsStreamResponse` | `data: [DONE]` |
| Anthropic | `data:` | `StreamResponse` (type 字段区分事件) | 无显式标记 |
| Gemini | `data: ` | `ChatResponse` | 无显式标记 |
| 阿里 | `data:` | `ChatResponse` (`\n` 分隔) | 无显式标记 |
| 百度 | `data: ` | `ChatStreamResponse` | `is_end = true` |

### 9.3 OpenAI 兼容渠道的 SSE 优化

OpenAI 兼容渠道的流式数据直接透传给客户端，仅需解析统计 usage 信息，不需要格式转换。

---

## 十、架构总结

### 10.1 核心设计原则

1. **统一入口，适配器分发**: 所有请求通过同一入口，由工厂模式创建对应适配器
2. **OpenAI 格式为"通用语言"**: 内部所有流转使用 OpenAI 格式，仅在"进出"时转换
3. **接口抽象**: 通过 `Adaptor` 接口 (9 方法) 隔离各厂商差异，新增厂商只需实现接口
4. **零拷贝优化**: OpenAI 兼容渠道无特殊处理时直接透传请求体
5. **关注点分离**: 认证、分发、转换、计费、重试各自独立

### 10.2 新增厂商适配步骤

1. 在 `relay/channeltype/define.go` 添加 `ChannelType` 常量
2. 在 `relay/apitype/define.go` 添加 `APIType`（或复用已有）
3. 在 `relay/channeltype/helper.go` 添加 `ToAPIType()` 映射
4. 在 `relay/channeltype/url.go` 添加默认 BaseURL
5. 创建 `relay/adaptor/<vendor>/` 目录实现 `Adaptor` 接口
6. 如果复用 OpenAI 格式，只需在 `compatible.go` 的 `CompatibleChannels` 列表中添加

### 10.3 架构特点

**优点**:
- 接口精简（9 方法），扩展性强
- 18 种 OpenAI 兼容渠道零开销透传
- 自动重试 + 渠道切换 + 错误监控自动禁用
- 统一的计费和错误处理
- 子适配器模式支持 Bedrock/Vertex AI 的多云厂商模型

**局限**:
- 仅支持 OpenAI 格式输入/输出（New-API 已在此基础上扩展了 Claude/Gemini 输入）
- 音频处理未完全走 Adaptor 接口
- 部分适配器 SSE 解析逻辑有重复模式，可抽取公共基类
- 缺少请求/响应中间件钩子的统一注入点
