CCX - 高性能多上游AI API代理与协议转换网关

1 阅读4分钟

CCX:多上游AI API代理与协议转换网关

CCX 是一个高性能的 AI API 代理与协议转换网关,支持 Claude、OpenAI Chat、OpenAI Images、Codex Responses 与 Gemini。它提供统一入口、内置 Web 管理界面、渠道编排、故障转移、多密钥管理和模型路由能力。

功能特性

  • 一体化架构 - 后端与前端一体化,单端口部署,前端构建产物嵌入 Go 二进制文件
  • 双密钥认证 - PROXY_ACCESS_KEY 用于代理访问,可选 ADMIN_ACCESS_KEY 用于管理接口
  • 内置管理面板 - Web 管理控制台,支持渠道管理、测试、日志和监控
  • 多协议支持 - 同时支持 Claude Messages、OpenAI Chat Completions、OpenAI Images、Codex Responses、Gemini API
  • 智能调度 - 优先级排序、促销期、健康检查、故障转移与熔断恢复
  • 渠道级配置 - 每个渠道支持多 API Key 轮换、代理、自定义请求头、模型白名单和路由前缀
  • 会话跟踪 - Responses API 支持多轮会话跟踪与 Trace 亲和性
  • 协议转换 - 支持 Claude ↔ OpenAI Chat ↔ Responses ↔ Gemini 之间的双向协议转换

架构概览

CCX 对外提供一个统一后端入口:

客户端 -> backend :3000 ->
  |- /                            -> Web 管理界面
  |- /api/*                       -> 管理 API
  |- /v1/messages                 -> Claude Messages 代理
  |- /v1/chat/completions         -> OpenAI Chat 代理
  |- /v1/responses                -> Codex Responses 代理
  |- /v1/images/generations       -> OpenAI Images 生成
  |- /v1/images/edits             -> OpenAI Images 编辑
  |- /v1/images/variations        -> OpenAI Images 变体
  |- /v1/models                   -> Models API
  `- /v1beta/models/*             -> Gemini 代理

安装指南

方式一:直接运行二进制

  1. Releases 下载最新可执行文件
  2. 在可执行文件同目录创建 .env
PROXY_ACCESS_KEY=your-proxy-access-key
PORT=3000
ENABLE_WEB_UI=true
APP_UI_LANGUAGE=zh-CN
  1. 启动后访问 http://localhost:3000

方式二:Docker

docker run -d \
  --name ccx \
  -p 3000:3000 \
  -e PROXY_ACCESS_KEY=your-proxy-access-key \
  -e APP_UI_LANGUAGE=zh-CN \
  -v $(pwd)/.config:/app/.config \
  crpi-i19l8zl0ugidq97v.cn-hangzhou.personal.cr.aliyuncs.com/bene/ccx:latest

使用 Docker Compose 后台运行:

docker compose up -d

方式三:源码构建

git clone https://github.com/BenedictKing/ccx
cd ccx
cp backend-go/.env.example backend-go/.env
make run

常用命令:

make dev      # 同时启动前端开发服务器和后端热重载
make run      # 构建前端并运行 Go 后端
make build    # 构建前端并编译 Go 后端

使用说明

环境变量配置

变量默认值说明
PORT3000服务器端口
ENVproduction运行环境
ENABLE_WEB_UItrue启用 Web 管理界面
PROXY_ACCESS_KEY-代理访问密钥(必填)
ADMIN_ACCESS_KEY-可选管理密钥
APP_UI_LANGUAGEen-US界面语言(zh-CN/en-US)
LOG_LEVELinfo日志级别
REQUEST_TIMEOUT300000请求超时(毫秒)
QUIET_POLLING_LOGStrue静默轮询日志

API 端点

代理入口
# Claude Messages
POST /v1/messages
POST /v1/messages/count_tokens

# OpenAI Chat Completions
POST /v1/chat/completions

# Codex Responses
POST /v1/responses
POST /v1/responses/compact

# OpenAI Images
POST /v1/images/generations
POST /v1/images/edits
POST /v1/images/variations

# Gemini
POST /v1beta/models/{model}:generateContent

# 模型列表
GET /v1/models
GET /v1/models/:model

# 健康检查
GET /health
管理 API
/api/messages/channels/*
/api/chat/channels/*
/api/responses/channels/*
/api/gemini/channels/*
/api/images/channels/*

使用示例

# 通过代理调用 Claude API
curl -X POST http://localhost:3000/v1/messages \
  -H "x-api-key: your-proxy-access-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "messages": [{"role": "user", "content": "Hello"}],
    "max_tokens": 1024
  }'

# 通过代理调用 OpenAI Chat API
curl -X POST http://localhost:3000/v1/chat/completions \
  -H "x-api-key: your-proxy-access-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

核心代码

调度器核心逻辑

// scheduler.go - 多渠道调度器
type ChannelScheduler struct {
    mu                       sync.RWMutex
    configManager            *config.ConfigManager
    messagesMetricsManager   *metrics.MetricsManager
    responsesMetricsManager  *metrics.MetricsManager
    geminiMetricsManager     *metrics.MetricsManager
    chatMetricsManager       *metrics.MetricsManager
    imagesMetricsManager     *metrics.MetricsManager
    traceAffinity            *session.TraceAffinityManager
    conversationTracker      *conversation.ConversationTracker
    overrideManager          *conversation.OverrideManager
}

// 选择渠道的核心方法
func (s *ChannelScheduler) SelectChannel(...) (*config.UpstreamConfig, error) {
    // 1. 检查渠道覆盖
    // 2. 检查促销期渠道
    // 3. 检查 Trace 亲和性
    // 4. 按优先级排序
    // 5. 健康检查和熔断过滤
}

Provider 接口定义

// provider.go - 上游提供商接口
type Provider interface {
    // 将请求转换为目标上游格式
    ConvertToProviderRequest(c *gin.Context, upstream *config.UpstreamConfig, apiKey string) (*http.Request, []byte, error)
    
    // 将提供商响应转换为 Claude 格式
    ConvertToClaudeResponse(providerResp *types.ProviderResponse) (*types.ClaudeResponse, error)
    
    // 处理流式响应
    HandleStreamResponse(body io.ReadCloser) (<-chan string, <-chan error, error)
}

// 支持的提供商:OpenAI、Gemini、Claude、Responses
func GetProvider(serviceType string) Provider {
    switch serviceType {
    case "openai": return &OpenAIProvider{}
    case "gemini": return &GeminiProvider{}
    case "claude": return &ClaudeProvider{}
    case "responses": return &ResponsesProvider{}
    default: return nil
    }
}

熔断器状态管理

// metrics.go - 熔断器状态
type CircuitState uint8

const (
    CircuitStateClosed CircuitState = iota   // 正常状态
    CircuitStateOpen                         // 熔断打开
    CircuitStateHalfOpen                     // 半开状态
)

// Key 级别指标管理
type KeyMetrics struct {
    MetricsKey          string
    BaseURL             string
    KeyMask             string
    CircuitState        CircuitState
    CircuitOpenedAt     *time.Time
    ConsecutiveFailures int64
}

协议转换核心

// converters.go - Responses 协议转换器接口
type ResponsesConverter interface {
    ToProviderRequest(sess *session.Session, req *types.ResponsesRequest) (interface{}, error)
    FromProviderResponse(resp map[string]interface{}, sessionID string) (*types.ResponsesResponse, error)
    GetProviderName() string
}

// 转换器工厂
func NewConverter(serviceType string) ResponsesConverter {
    switch serviceType {
    case "openai": return &OpenAIChatConverter{}
    case "claude": return &ClaudeConverter{}
    case "gemini": return &GeminiResponsesConverter{}
    case "responses": return &ResponsesPassthroughConverter{}
    default: return &OpenAIChatConverter{}
    }
}

1Z5R1dkCK4RKCL7aKVd+uA==