OpenAPI-AI 是一个高性能的 AI 模型 API 转发系统,提供统一的 API 接口,支持多种 AI 模型服务提供商的接入和管理。
OpenAPI-AI
| 组件 | 版本要求 | 说明 |
|---|---|---|
| Go | 1.25+ | 编程语言 |
| Redis | 6.0+ | 缓存和状态存储 |
| MongoDB | 5.0+ | 模型配置和用户数据存储 |
| MySQL | 5.7+ | 日志存储(可选) |
Windows (PowerShell):
.\run.ps1
Linux/macOS:
chmod +x run.sh
./run.sh
启动脚本会自动:
# 设置环境变量
export MONGODBURL="mongodb://localhost:27017"
export DATABASE="openapi"
export REDISURL="localhost:6379"
export MYSQLDSN="user:password@tcp(localhost:3306)/openapi_ai"
# 启动服务
go run cmd/server/main.go -port 8080
所有环境变量均以 OPENAPI_AI_ 为前缀,同时支持简化的环境变量名称:
| 环境变量 | 默认值 | 说明 |
|---|---|---|
OPENAPI_AI_SYSTEM_NAME | OpenAPI-AI | 系统名称 |
OPENAPI_AI_LOG_LEVEL | 1 | 日志级别(0=Debug, 1=Info, 2=Warn, 3=Error) |
| 环境变量 | 简化变量 | 默认值 | 说明 |
|---|---|---|---|
OPENAPI_AI_REDIS_ADDR | REDISURL | localhost:6379 | Redis 地址 |
OPENAPI_AI_REDIS_PASSWORD | REDISPASSWORD | "" | Redis 密码 |
OPENAPI_AI_REDIS_DB | REDISDB | 0 | Redis 数据库索引 |
OPENAPI_AI_REDIS_TIMEOUT_MS | REDIS_TIMEOUT_MS | 500 | Redis 操作超时时间(毫秒) |
| 环境变量 | 简化变量 | 默认值 | 说明 |
|---|---|---|---|
OPENAPI_AI_MONGO_URI | MONGODBURL | mongodb://localhost:27017 | MongoDB 连接 URI |
OPENAPI_AI_MONGO_DATABASE | DATABASE | openapi | MongoDB 数据库名称 |
OPENAPI_AI_MONGO_TIMEOUT_MS | MONGO_TIMEOUT_MS | 5000 | MongoDB 操作超时时间(毫秒) |
| 环境变量 | 简化变量 | 默认值 | 说明 |
|---|---|---|---|
OPENAPI_AI_MYSQL_DSN | MYSQLDSN | "" | MySQL 完整 DSN(优先使用) |
OPENAPI_AI_MYSQL_HOST | MYSQL_HOST | localhost | MySQL 主机地址 |
OPENAPI_AI_MYSQL_PORT | MYSQL_PORT | 3306 | MySQL 端口 |
OPENAPI_AI_MYSQL_USER | MYSQL_USER | root | MySQL 用户名 |
OPENAPI_AI_MYSQL_PASSWORD | MYSQL_PASSWORD | "" | MySQL 密码 |
OPENAPI_AI_MYSQL_DATABASE | MYSQL_DATABASE | openapi_ai | MySQL 数据库名称 |
| 环境变量 | 默认值 | 说明 |
|---|---|---|
OPENAPI_AI_HTTP_TIMEOUT_MS | 300000 | HTTP 请求总超时(毫秒) |
OPENAPI_AI_HTTP_RESPONSE_TIMEOUT_MS | 30000 | HTTP 响应头超时(毫秒) |
OPENAPI_AI_HTTP_IDLE_TIMEOUT_MS | 90000 | HTTP 空闲连接超时(毫秒) |
| 环境变量 | 默认值 | 说明 |
|---|---|---|
OPENAPI_AI_KEY_COOLDOWN_SECONDS | 60 | 密钥限流冷却时间(秒) |
OPENAPI_AI_KEY_AFFINITY_TTL_SECONDS | 600 | 密钥亲和绑定 TTL(秒) |
OPENAPI_AI_KEY_HEALTH_TTL_SECONDS | 1800 | 密钥健康度 TTL(秒) |
| 环境变量 | 默认值 | 说明 |
|---|---|---|
OPENAPI_AI_CONSECUTIVE_ERROR_THRESHOLD | 5 | 连续错误阈值 |
OPENAPI_AI_RECOVERY_CHECK_INTERVAL_SECONDS | 120 | 恢复检测间隔(秒) |
OPENAPI_AI_HEALTH_CHECK_WINDOW_SECONDS | 600 | 健康检查窗口期(秒) |
OPENAPI_AI_LATENCY_WINDOW_SECONDS | 600 | 延迟统计窗口期(秒) |
OPENAPI_AI_MODEL_GROUP_STATUS_TTL_SECONDS | 1800 | 模型组状态缓存 TTL(秒) |
所有 API 请求需要在 Header 中携带 Bearer Token:
Authorization: Bearer YOUR_TOKEN
端点: /v1/chat/completions
请求示例:
curl -X POST "http://localhost:8080/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"model": "gpt-4",
"messages": [
{"role": "user", "content": "Hello, how are you?"}
],
"stream": false
}'
流式请求示例:
curl -X POST "http://localhost:8080/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"model": "gpt-4",
"messages": [
{"role": "user", "content": "Hello, how are you?"}
],
"stream": true
}'
端点: /v1/messages
请求示例:
curl -X POST "http://localhost:8080/v1/messages" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-3-opus",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello, how are you?"}
]
}'
端点: /health
curl http://localhost:8080/health
响应:
{
"status": "ok",
"time": "2024-01-01T12:00:00Z"
}
{
"error": {
"message": "错误描述",
"type": "错误类型",
"code": "错误代码"
}
}
当请求的模型属于模型组时,系统会自动进行智能选择:
选择策略:
请求 → Token解析 → 用户查询 → 实名认证检查 → 资源包验证 → 处理请求
认证失败响应:
| 错误代码 | HTTP状态码 | 说明 |
|---|---|---|
unauthorized | 401 | Token 无效或缺失 |
token_not_found | 401 | Token 不存在 |
realname_not_true | 401 | 未完成实名认证 |
resource_not_purchased | 429 | 未购买资源包 |
resource_exhausted | 429 | 资源包已用尽 |
OpenAPI-AI/ ├── openapi_ai.go # 主入口文件,提供 Init() 和 Close() 函数 ├── cmd/server/main.go # HTTP 服务器入口 ├── internal/ # 内部模块(不对外暴露) │ ├── mongodb/ # MongoDB 客户端封装 │ │ └── mongodb.go # 数据库连接和集合操作 │ ├── mysql/ # MySQL 客户端封装 │ │ └── mysql.go # 数据库连接和操作 │ └── redis/ # Redis 客户端封装 │ └── redis.go # 缓存操作封装 ├── pkg/ # 公共模块(可对外暴露) │ ├── billing/ # 计费模块 │ │ └── billing.go # 模型配置查询、资源扣费、用户认证中间件 │ ├── config/ # 配置管理 │ │ └── config.go # 环境变量加载、配置定义、Redis键前缀 │ ├── errdetect/ # 错误检测 │ │ └── errdetect.go # 上游响应错误检测 │ ├── failover/ # 故障转移 │ │ └── failover.go # 健康状态管理、智能选择策略、延迟统计 │ ├── forward/ # API 转发 │ │ └── forward.go # OpenAI 和 Anthropic 格式转发核心逻辑 │ ├── key/ # 密钥管理 │ │ └── key.go # 亲和策略、健康度管理、优先级排序 │ ├── logger/ # 日志模块 │ │ └── logger.go # 异步日志记录、AI进度追踪 │ ├── stream/ # 流式处理 │ │ └── stream.go # SSE 流式响应处理 │ ├── testutils/ # 测试工具 │ │ ├── fixtures.go # 测试数据固定装置 │ │ ├── helpers.go # 测试辅助函数 │ │ └── mocks.go # Mock 对象 │ ├── token/ # Token 计算 │ │ └── token.go # tiktoken 精算和智能估算 │ └── types/ # 类型定义 │ └── types.go # 核心数据结构定义 ├── run.ps1 # Windows 启动脚本 ├── run.sh # Linux/macOS 启动脚本 └── README.md # 项目文档
| 模块 | 功能描述 |
|---|---|
billing | 模型配置查询、接入商配置查询、用户资源扣费、用户认证中间件 |
config | 从环境变量加载系统配置,支持 Redis 键前缀常量 |
errdetect | 检测上游响应是否为错误,支持 MiniMax 等非标准格式规范化 |
failover | 模型组健康状态管理、延迟检测、智能选择策略、故障恢复 |
forward | OpenAI 和 Anthropic 格式的 API 转发核心逻辑,包含模型组选择缓存 |
key | 密钥亲和策略、健康度管理、优先级排序、状态更新 |
logger | 异步日志记录,支持 MySQL 存储,AI 进度追踪 |
stream | SSE 流式响应的扫描和处理 |
token | Token 计算,支持 OpenAI tiktoken 精算和非 OpenAI 模型估算 |
types | 核心数据结构定义,包括模型配置、接入商配置、健康状态等 |
| 键前缀 | 用途 | TTL |
|---|---|---|
openapi_ai:key_affinity: | 密钥亲和绑定 | 10分钟 |
openapi_ai:key_health: | 密钥健康度 | 30分钟 |
openapi_ai:model_group_status: | 模型组健康状态 | 30分钟 |
openapi_ai:model_group_latency: | 模型组延迟指标 | 10分钟 |
openapi_ai:model_data: | 模型配置缓存 | 永久 |
openapi_ai:model_group: | 模型组配置缓存 | 永久 |
openapi_ai:model_isp: | 接入商配置缓存 | 永久 |
openapi_ai:user_model_group: | 用户模型组分配 | 永久 |
openapi_ai:user_model_selection: | 用户模型组选择缓存 | 30分钟 |
package main
import (
"openapi-ai"
"gorm.io/gorm"
)
func main() {
// 初始化 MySQL 连接(可选,用于日志存储)
var db *gorm.DB
// db = 初始化 GORM 连接...
// 初始化 OpenAPI-AI 系统
if err := openapi_ai.Init(db, false); err != nil {
panic("初始化失败: " + err.Error())
}
defer openapi_ai.Close()
// 系统已就绪,可以开始处理请求...
}
package main
import (
"io"
"github.com/gin-gonic/gin"
"openapi-ai"
"openapi-ai/pkg/billing"
"openapi-ai/pkg/forward"
)
func main() {
// 初始化系统
openapi_ai.Init(nil, true)
defer openapi_ai.Close()
r := gin.Default()
// OpenAI 格式 API(需要用户认证)
v1 := r.Group("/v1")
v1.Use(billing.UserMiddleware())
{
v1.POST("/chat/completions", func(c *gin.Context) {
bodyBytes, _ := io.ReadAll(c.Request.Body)
forward.OpenAI(c, bodyBytes)
})
}
// Anthropic 格式 API(需要用户认证)
v1Anthropic := r.Group("/v1")
v1Anthropic.Use(billing.UserMiddleware())
{
v1Anthropic.POST("/messages", func(c *gin.Context) {
bodyBytes, _ := io.ReadAll(c.Request.Body)
forward.Anthropic(c, bodyBytes)
})
}
r.Run(":8080")
}
package main
import (
"openapi-ai/pkg/billing"
)
func main() {
// 获取单个模型配置
modelData, err := billing.GetModel("gpt-4")
if err != nil {
panic(err)
}
println("模型名称:", modelData.Name)
// 获取模型组配置
modelGroup, err := billing.GetModelGroup("gpt-4-group")
if err != nil {
panic(err)
}
if modelGroup != nil {
println("模型组数量:", len(*modelGroup))
}
}
症状: 启动时报错 Redis初始化失败
排查步骤:
redis-cli pingREDISURL 是否正确症状: 启动时报错 MongoDB初始化失败
排查步骤:
MONGODBURL 是否正确症状: 日志显示 用户调用大模型时搜索模型失败 error=模型不存在
排查步骤:
openapi)model_data 集合中是否存在该模型name 字段是否与请求中的模型名匹配症状: 配置未按预期加载
解决方案:
症状: 所有请求返回 429 错误
解决方案:
OPENAPI_AI_KEY_COOLDOWN_SECONDS 增加冷却时间症状: 模型组中某个模型故障后未自动切换
解决方案:
group 字段)OPENAPI_AI_CONSECUTIVE_ERROR_THRESHOLD 阈值设置failover.GetHealthInfo() 检查模型组健康状态症状: 请求返回 401 错误
解决方案:
Bearer <token>)tokens 数组中realname 字段为 true)MIT License