标题

记录(2026.5.14-5.15)——new-api-main 源码说明

1. 这个项目到底是什么

new-api-main 是一个 AI API 网关平台。它把不同厂商、不同协议格式的大模型接口统一包装成一套对外 API,同时带上用户管理、令牌管理、渠道管理、计费、日志、统计和后台管理页面。

通俗理解:它像一座“模型请求中转站 + 运营后台”。


2. 它解决的是什么问题

直接对接多个上游模型时,常见问题有:

  • 每家 API 格式不同
  • Key 很散,难管理
  • 团队内部要做权限、额度、计费
  • 想让不同模型走不同上游
  • 想看日志、消费、渠道健康度

new-api-main 的作用就是把这些问题集中解决。

通俗理解:它不是只帮你“转发请求”,而是帮你“把模型接入业务化”。


3. 技术栈

后端

  • Go
  • Gin
  • GORM
  • Redis + 内存缓存
  • SQLite / MySQL / PostgreSQL

通俗理解:这是个标准 Go 后端平台项目。

前端

  • React
  • TypeScript
  • web/default 为主前端

通俗理解:后台管理页面也在仓库里,不是另外一个系统。


4. 顶层目录作用

源码:

https://github.com/QuantumNous/new-api.git

目录/文件 作用 通俗理解
main.go 系统启动入口 程序从这里启动
router/ 路由装配 决定什么 URL 交给什么处理器
controller/ 控制器层 真正处理 HTTP 请求的入口层
service/ 业务逻辑层 规则、计费、渠道策略在这里
model/ 数据库模型层 和数据库打交道的地方
middleware/ 中间件层 鉴权、限流、日志、分发
relay/ 上游转发引擎 真正把请求发给模型供应商
common/ 公共基础能力 工具函数、环境变量、缓存等
constant/ 常量定义 各种固定值和标识
dto/ 请求响应结构体 HTTP 数据格式定义
types/ 通用类型 错误、relay 类型等
setting/ 系统配置和规则 价格比率、操作规则等
oauth/ OAuth 相关实现 第三方登录和绑定
i18n/ 后端国际化 后端返回多语言提示
web/ 前端源码和构建产物 后台页面所在目录
.env.example 环境变量示例 部署时先看它配什么

5. 启动流程怎么理解

5.1 main.go

它主要做这些事:

  1. 调用 InitResources()
  2. 初始化数据库、Redis、日志、i18n
  3. 初始化缓存和后台任务
  4. 创建 Gin 服务
  5. 注册中间件
  6. 注册路由
  7. 启动 HTTP 服务

通俗理解:这是整个系统的“总装配入口”。

5.2 InitResources()

它负责把系统底座搭起来:

  • .env
  • 初始化环境变量
  • 初始化日志
  • 初始化数据库
  • 初始化选项缓存
  • 初始化 Redis
  • 初始化 i18n
  • 初始化自定义 OAuth

通俗理解:这一步像“开机自检 + 基础组件上线”。

5.3 后台任务

main.go 还会启动很多周期任务,例如:

  • 渠道缓存同步
  • 渠道自动检测
  • 渠道上游模型更新检测
  • Codex 凭证自动刷新
  • 订阅额度自动重置

通俗理解:这个系统不是只“收请求”,它平时还在后台自动维护很多状态。


6. 分层怎么读

这个项目最适合按下面这条链路理解:

Router -> Middleware -> Controller -> Service -> Model / Relay

通俗理解:先决定“去哪”,再决定“能不能进”,再决定“怎么处理”,最后决定“怎么落库或怎么转发”。

6.1 router/

重点文件:

  • router/main.go
  • router/api-router.go
  • router/relay-router.go

router/main.go

作用:

  • 把 API 路由、Relay 路由、Dashboard 路由、Web 路由挂到 Gin 上

通俗理解:总路由分发台。

router/api-router.go

作用:

  • 用户、令牌、渠道、订阅、支付、日志、配置等后台 API 都在这里注册

通俗理解:这是“管理后台接口总表”。

router/relay-router.go

作用:

  • 对外暴露模型转发接口
  • 例如 /v1/chat/completions/v1/responses/v1/embeddings/mj/*/suno/*

通俗理解:这是“真正给模型客户端访问的网关入口”。


6.2 middleware/

重点文件:

  • middleware/auth.go
  • middleware/rate-limit.go
  • middleware/request-id.go
  • middleware/logger.go
  • middleware/distributor.go

middleware/distributor.go

这是最关键的中间件之一。

它负责:

  • 从请求里提取模型名
  • 检查 token 有没有权限访问这个模型
  • 根据 group、模型、亲和性、优先级选出可用渠道
  • 把选中的渠道信息写入上下文

通俗理解:这是“发车前的调度员”,它先决定这次请求该坐哪辆车。


6.3 controller/

重点文件:

  • controller/relay.go

controller/relay.go 负责:

  • 解析请求
  • 生成 relay 信息
  • 敏感词检查
  • 预估 token
  • 预扣费
  • 调用具体 relay 处理器
  • 失败时退款、记录错误、决定是否重试和自动禁用渠道

通俗理解:这是“网关总控室”,一笔请求到了这里,才真正进入业务处理。


6.4 service/

这是规则层。

重点文件:

  • service/channel_select.go
  • service/channel.go
  • service/pre_consume_quota.go
  • service/subscription_reset_task.go

service/channel_select.go

作用:

  • 根据 group、模型、重试次数和自动分组规则挑渠道

通俗理解:这是“真正做渠道选择算法”的地方。

service/channel.go

作用:

  • 判断某个渠道要不要自动禁用
  • 处理禁用后通知

通俗理解:这是“渠道健康规则中心”。

其它 service

文件/模块 作用 通俗理解
pre_consume_quota.go 预扣费 请求发出去前先扣一部分额度
task*.go 任务型平台逻辑 Midjourney、Suno 这类任务请求处理
codex_credential_refresh_task.go Codex 凭证刷新 让某些凭证别过期
subscription_reset_task.go 订阅额度重置 定时给订阅用户恢复额度

6.5 model/

重点文件:

  • model/main.go
  • model/channel.go
  • model/token.go
  • model/user.go
  • model/log.go

model/main.go

作用:

  • 选数据库类型
  • 建连接
  • 自动迁移
  • 兼容 SQLite / MySQL / PostgreSQL
  • 首次初始化 root / setup

通俗理解:这是数据库“总入口和总管家”。


6.6 relay/

重点目录/文件:

  • relay/claude_handler.go
  • relay/gemini_handler.go
  • relay/image_handler.go
  • relay/embedding_handler.go
  • relay/audio_handler.go
  • relay/responses_handler.go

作用:

  • 适配不同上游协议
  • 构造上游请求
  • 转换响应格式
  • 处理流式输出和错误

通俗理解:这里就是“真正和模型供应商说话”的地方。


6.7 web/

这个目录下有两个主题:

  • web/default
  • web/classic

其中 web/default 是主前端。

作用:

  • 提供后台管理页面
  • 展示用户、渠道、日志、统计、设置等

通俗理解:你在浏览器里看到的后台页面,基本就来自这里。


7. 关键文件为什么重要

文件 为什么重要 通俗理解
main.go 系统启动总入口 开机总控
router/main.go 路由总装配 决定请求去哪
router/relay-router.go 模型转发接口入口 客户端主要打这里
router/api-router.go 管理后台接口入口 管理员主要走这里
middleware/distributor.go 渠道选择前置逻辑 发请求前先决定走哪条线
controller/relay.go relay 总控制器 请求真正进入业务处理的地方
service/channel_select.go 选渠道核心逻辑 挑上游的算法中心
service/channel.go 渠道禁用/启用逻辑 渠道健康度管理
model/main.go 数据库初始化与迁移 数据底座
web/default/package.json 前端技术栈入口 识别前端最省时间的入口

8. 核心流程重新讲清楚

8.1 流程一:一次 /v1/chat/completions 请求怎么走

  1. 客户端请求进入 Gin。
  2. 命中 router/relay-router.go
  3. 经过鉴权、限流、性能检查和 Distribute()
  4. Distribute() 按模型和 group 选出一个渠道。
  5. 进入 controller/relay.go
  6. 控制器做参数检查、敏感词检查、token 估算、预扣费。
  7. 控制器调用 relay/ 中对应处理器。
  8. 请求被发往真实上游。
  9. 返回后记录日志、做结算、统计用量。
  10. 如果出错,可能重试,也可能自动禁用渠道。

通俗理解:一条请求不是“收到就转发”,而是“先审、先选路、再发车、再记账”。

8.2 流程二:渠道是怎么选出来的

代码主线:

  1. 中间件先读出模型名。
  2. 看 token 是否允许访问这个模型。
  3. 如果有亲和渠道,先尝试之前稳定成功的渠道。
  4. 如果没有,再走 CacheGetRandomSatisfiedChannel(...)
  5. 结合 group、模型、重试次数选一个渠道。
  6. 把渠道的 key、base URL、类型等写进上下文。

通俗理解:它像“智能接线员”,不是随机乱发,而是按规则挑最合适的一条线。

8.3 流程三:失败后怎么处理

代码主线:

  1. 上游报错。
  2. 控制器判断是否可重试。
  3. 如果能重试,就换一个可用渠道。
  4. 如果错误符合规则,就自动禁用这个坏渠道。
  5. 记录错误日志。
  6. 如果之前做过预扣费,就退款或补偿。

通俗理解:它不是一条线挂了就直接报废,而是会尽量“换线继续打”。

8.4 流程四:管理员在后台看渠道列表怎么走

  1. 请求进入 /api/channel/...
  2. 命中 router/api-router.go
  3. 先过 AdminAuth()
  4. 进入对应 controller
  5. controller 调 model/service 取数据
  6. 返回给前端页面

通俗理解:后台 CRUD 这条线比模型转发简单很多,主要就是权限控制加查库。


9. 为什么原流程难懂

因为这个项目其实同时在做两件大事:

  1. 模型 API 网关
  2. 平台管理后台

再叠加渠道、计费、日志、前端、任务平台适配,信息量就会很大。

通俗理解:它不是“单一接口项目”,而是“半个平台”。


10. 推荐阅读顺序

  1. README.zh_CN.md
  2. main.go
  3. router/main.go
  4. router/relay-router.go
  5. middleware/distributor.go
  6. controller/relay.go
  7. service/channel_select.go
  8. service/channel.go
  9. model/main.go
  10. router/api-router.go
  11. web/default/package.json

通俗理解:先把“请求主链路”读懂,再补后台和前端。


11. 一句话总结

new-api-main 本质上是一套“多上游模型统一接入、统一鉴权、统一计费、统一后台管理”的 AI 网关平台。

通俗理解:它不是只帮你“转一下 API”,而是帮你“把 API 中转站做成一个可运营的平台”。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐