一个计算机技术爱好者与学习者

0%

One API 开发环境配置

1. 前言

有些情况下,我们需要基于 One API 进行二次开发,以满足特定的需求。

本文中,我们会学习 One API 的开发环境配置。

相关文档:

2. 获取 One API 代码

2.1. 方法一:直接从源仓库获取代码

1
git clone https://github.com/songquanpeng/one-api.git

2.2. 方法二:fork后再获取代码(推荐)

fork后再获取代码的优点,是更加容易维护。每次修改后提交到自己的仓库进行存档,还可以往源仓库中提交PR。

  1. fork oneapi 代码
    浏览器访问 github - one-api ,fork oneapi 到自己的 github 仓库。

  2. 克隆 oneapi 代码

    1
    git clone https://github.com/voidking/one-api.git
  3. 配置多个远程仓库(可选)

    1
    2
    cd one-api
    git remote add upstream https://github.com/songquanpeng/one-api.git

3. 本地运行 One API

3.1. 安装依赖

  1. 安装前端依赖(node版本 v20.10.0)

    1
    2
    3
    cd one-api/web/default
    npm install
    npm run build
  2. 安装后端依赖

    1
    2
    3
    cd one-api
    # export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890
    go mod tidy

3.2. 运行代码

  1. 运行代码

    1
    go run main.go

    运行成功的话,控制台会输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [INFO] 2025/04/08 - 17:36:38 | main.go:32 [main] One API v0.0.0 started
    [INFO] 2025/04/08 - 17:36:38 | model/main.go:103 [openSQLite] SQL_DSN not set, using SQLite as database
    [INFO] 2025/04/08 - 17:36:38 | model/main.go:129 [InitDB] database migration started
    [INFO] 2025/04/08 - 17:36:38 | model/main.go:134 [InitDB] database migrated

    2025/04/08 17:36:38 /path/to/one-api/model/main.go:27 record not found
    [0.437ms] [rows:0] SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1
    [INFO] 2025/04/08 - 17:36:38 | model/main.go:28 [CreateRootAccountIfNeed] no user exists, creating a root user for you: username is root, password is 123456
    [INFO] 2025/04/08 - 17:36:39 | common/redis.go:20 [InitRedisClient] REDIS_CONN_STRING not set, Redis is not enabled
    [INFO] 2025/04/08 - 17:36:39 | main.go:65 [main] using theme default
    [INFO] 2025/04/08 - 17:36:39 | relay/adaptor/openai/token.go:23 [InitTokenEncoders] initializing token encoders
    [INFO] 2025/04/08 - 17:36:40 | relay/adaptor/openai/token.go:49 [InitTokenEncoders] token encoders initialized
    [INFO] 2025/04/08 - 17:36:40 | main.go:119 [main] server started on http://localhost:3000
  2. 测试访问
    浏览器访问 http://localhost:3000
    测试登录,默认用户名为root,密码为 123456

若登录成功,则证明One API本地运行环境配置完成了。

4. VSCode中配置调试环境

参考文档:《好好学Golang:VSCode配置Golang Debug》

5. One API核心逻辑

One-API 的核心功能是将客户端的 OpenAI 格式请求转发到不同的大模型服务商,其处理流程如下:

  1. 客户端请求:客户端发送符合 OpenAI API 格式的请求到 One-API 端点

  2. 认证与鉴权:通过中间件验证 API Key 的有效性和权限

  3. 模型映射:根据请求中的模型名称确定要使用的渠道

  4. 请求转换:将 OpenAI 格式的请求转换为目标服务商的API格式

  5. 转发请求:将转换后的请求发送到目标服务商

  6. 响应转换:将服务商的响应转换回 OpenAI 格式

  7. 返回客户端:将标准化响应返回给客户端

6. 支持新的大模型

6.1. 实现思路

新出现的大模型,One API并不能保证可以在第一时间支持。如果比较着急使用,那么我们可以自己进行二次开发。

实现思路如下:

  1. 获取模型的API Key,并且通过curl验证可以正常访问该模型的API

  2. One API 新增渠道,配置该模型的API和Key

  3. 测试新增的渠道,根据报错搜索代码,定位到报错的位置

  4. 报错的代码,打断点;请求和响应的代码,打断点;可疑的代码,打断点

  5. 测试新增的渠道,触发调试模式,跳转到断点,单步调试

  6. 修改代码以支持新的大模型,同时输出更多日志

  7. 重复4-6,直到调通整个流程

6.2. 支持新的Gemini模型

以支持新的 gemini-2.5-pro-exp-03-25 模型为例,整个实现过程遵循实现思路,需要特别说明的是curl验证方法和获取关键信息的方法。

6.2.1. curl验证

One API 渠道可用,最基础的前提是模型的API可用,gemini-2.5-pro-exp-03-25 模型的API验证方法如下:

1
2
3
4
5
6
7
8
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro-exp-03-25:generateContent?key=xxx" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contents": [{
"parts":[{"text": "hello"}]
}]
}'

6.2.2. 获取关键信息

以发送请求并获得响应为分界点,整个系统可以分为三个部分:请求头和请求体处理,发送请求并获得响应,响应内容处理。

如果有了请求相关的关键信息,那么就可以定位解决很多问题了。举个例子,假设获取到的响应不符合预期,那么我们可以直接定位到请求头和请求体处理部分有问题。
因此,在开发调试过程中,必须要获取到四个请求相关的关键信息:请求的URL、请求头、请求体、响应的内容。

经过单步调试,我们会发现,在 relay/adaptor/common.go 中的DoRequestHelperDoRequest 函数中,我们可以获取到请求相关的关键信息。

打印请求体的方法:

1
2
3
4
5
// req 类型为 http.Request
requestBody, err := io.ReadAll(req.Body)
fmt.Println("Request Body:", string(requestBody))
// 读取Body会消耗掉Body,如果需要后续使用,需要重新赋值
req.Body = io.NopCloser(bytes.NewBuffer(body))

打印响应内容的方法:

1
2
3
// resp 类型为 http.Response 
responseBody, err := io.ReadAll(resp.Body)
fmt.Println("Response Body:", string(responseBody))

获取到请求的URL、请求头、请求体后,就可以通过curl直接发送请求了。
正确的curl与不正确的curl进行对比,就可以定位到问题出现在系统的哪一部分。

同样的道理,One API系统的三个部分还可以根据其他关键信息进一步细分,这样就可以达到类似于二分法定位问题的效果。