【开源】整了个LLM API网关——拼好 AI

前言

我做个项目的最初其实是为了把白嫖过来的公益站做一下整合,方便我调用和做一下错误转移(毕竟嫖来的不一定稳),因此找了一些开源的 API 网关来用,比如 New API 和 uni-api。

我最开始用的是 New API,因为好多公益站都在用这个项目。它整个使用下来的体验感觉是不错的,感觉算是大而全。但是成也萧何败也萧何,毕竟我只是个人只用,用不上的功能还是有点太多了。于是寻思有没有更简单一点的项目,最后找到了 uni-api。

如果说 New API 是大而全的话,那么 uni-api 就可以说是小而美了。它没有什么非常复杂的功能,但必要的功能也都有。在遇到 uni-api 之后我就用了它一段时间,感觉除了他那前端因为我是本地部署的,导致给的那个前端站我本地因为 CORS 问题连不上(HTTPS 站点不能有 HTTP 内容跨域请求)之外,感觉挺好的。不过后面还是因为它的前端问题让我萌生了自己撸一个类似的项目的想法。

拼好 AI

拼好 AI是一个采用了前后端分离的架构的 API 网关项目。它的核心基本只围绕“个人”与“简单”这两点的需求来考虑。它基本没有什么配置的地方,只需要在 Docker 中启动,然后打开网站进入管理界面配置 API 供应商信息即可。

部署

这里推荐使用 Docker 来运行拼好 AI:

# 拉取并运行最新版本(自行设置 token)
docker run -d \
-e ENABLE_WEB=true \
-e GITHUB_PROXY=https://hk.gh-proxy.com \
-e API_TOKEN=<业务token> \
-e ADMIN_TOKEN=<管理token> \
ghcr.io/meowsalty/pinai:latest

拼好 AI 内部也内建有一个可选的 Web 管理界面,通过 -e ENABLE_WEB=true 开启,方便本地部署无 HTTPS 的用户访问。如果希望不开启前端功能的话,也可以自己部署前端页面或者是访问前端页面的预览站点(预览站点部署在 HTTPS 上,因此一些现代浏览器会要求后端也具有 HTTPS 连接)。

如果内置的前端因为网络问题无法更新或下载的话,可以在启动时通过环境变量 GITHUB_PROXY=[GitHub 加速地址]配置 GitHub 代理。这样实际请求地址就会变为 [GitHub 加速地址]/https://api.github.com/repos/...

另外项目默认使用 SQLite 作为数据库,因此如果需要持久化数据,请将 PinAI 的数据目录 /app/data 映射到宿主机的目录。如果有需要也可以另外配置其他的数据库服务,项目支持 MySQL 和 PostgreSQL 数据库服务。

而对于业务 token 和管理 token:业务 token 是用于调用 LLM API 的,管理 token 是用于后台管理界面的,但如果只设置了业务 token 的话,那么管理 token 也会使用和业务 token 一样的值。当然也可以都不设置就是了,这样就不会对 API 调用进行鉴权。

镜像因为是 GitHub 的,如果访问不了的话,可以尝试使用类似 ghcr.nju.edu.cn/meowsalty/pinai:latest这样的国内镜像。

如果希望查看更详细的环境变量或启动参数的配置说明,可以访问拼好 AI 的仓库查看。

使用

拼好 AI 的使用非常简单,只需要在浏览器中打开 http://127.0.0.1:3000 就可以进入管理界面。

管理界面的首页设置为仪表盘。不过如果是初次打开的话,并且你在启动时配置了业务 token 或是管理 token 的话,需要进行一下配置:

  • 点击页面顶部的“默认 API 服务器”
  • 在弹出的服务器管理窗口中编辑默认的服务器信息
  • API 密钥如果设置了业务 token 或是管理 token,那就填进去(有管理就填管理,否则填业务)
  • 编辑完成后点击保存

保存后刷新页面就不会再弹出错误信息,此时点击侧边栏中的“供应商”添加 API 供应商信息,就可以开始使用拼好 AI 了。

API 调用

项目目前提供 OpenAI 和 Anthropic 格式的兼容接口。可以通过下列基础路径进行访问:

  • OpenAI:/openai
  • Anthropic:/anthropic

Claude Code

因为项目提供了 Anthropic 格式的兼容接口,因此理论上应该是可以使用的。不过因为 cc 它好像访问的是固定的模型,因此需要使用模型映射功能:

比如说要把 cc 使用的模型 claude-sonnet-4-20250514 映射为平台里有的模型 deepseek-v3,那么在启动时使用环境变量或启动参数进行配置即可:

# 命令行方式
./pinai -model-mapping="claude-sonnet-4-20250514:deepseek-v3"

# 环境变量方式
export MODEL_MAPPING="claude-sonnet-4-20250514:deepseek-v3"
./pinai

# Docker 方式
docker run -d \
-p 3000:3000 \
-e MODEL_MAPPING="claude-sonnet-4-20250514:deepseek-v3" \
ghcr.io/meowsalty/pinai:latest

开启了映射后会在传入请求时直接对请求的名称进行修改。

不过我平时也不用它,所以遇到有报告问题时再修修吧(x

User-Agent 配置

User-Agent 配置用于控制向上游 AI 服务发送请求时的 User-Agent 头部。支持三种模式:

  1. 透传模式(默认):不设置或设置为空字符串时,将透传客户端请求的 User-Agent

  2. 默认模式:设置为 “default” 时,不添加 User-Agent 头部,使用 fasthttp 库的默认值

  3. 自定义模式:设置为其他任意字符串时,使用该字符串作为 User-Agent

项目目前对 User-Agent 默认采用的是透传策略,如果用户希望禁止透传使用程序默认的 User-Agent 或者是自定义 User-Agent,可以通过设置 USER_AGENT 环境变量来控制。

WEB 管理界面

管理界面分为 3 个区域:仪表盘、供应商、使用日志。

仪表盘

仪表盘主要展示系统的概括界面,其实最开始连这个都不想弄的,不过既然数据都记录到数据库里面了那还是弄一个吧。

它主要分为三个部分:实时状态、统计概览还有排行信息。

实时状态

实时状态会展示当前平台最近 1 分钟内的被调用情况,以及目前的活动连接数。

统计概览

统计概览默认展示最近 24 小时内平台发起的模型请求次数、请求成功率、流式请求的平均首字时间(不包含故障转移时间)及 Tokens 用量。

排行信息

会默认展示最近 24 小时内平台被调用的模型、平台的调用、用量排行数据(前 5)

供应商

供应商就是基本的 CRUD 实现,不过另外加了个批量导入、从 API 获取模型和自动重命名模型的功能。

批量导入供应商

导入格式为 [类型],[名称],[端点],[密钥]。他们使用英文逗号进行分隔。

类型有 2 种:OpenAI,Gemini。因为目前嫖到的 API 站大多是支持 OpenAI 格式的,还有一些用的是哈基米的格式。

端点的话比如说 API 的调用路径是 https://domein.com/api/v1/chat/completions,那么这里填写的是 https://domein.com/api,拼好 AI 的前端或者后端会根据使用时的需求在 base_url 的后面拼接 /v1/chat/completions/v1/models 来使用

获取模型

在供应商的编辑界面可以通过“获取模型”按钮来获取当前供应商的模型列表,不过先决条件是需要配置好类型、端点和密钥。并且如果模型列表种已经存在模型的情况下也可以获取,并根据和目前列表的差异来选择更新。

对于供应商不再支持的模型会删除,但对于新增的模型可以选择是否添加进去。

自动重命名

在供应商的编辑界面可以通过“自动重命名”按钮来进入自动重命名界面。它支持 4 种重命名方式:

  • 插入
  • 替换
  • 正则
  • 大小写转换

规则的执行顺序是从上往下,可以通过鼠标拖拽改变规则排序和通过复选框来选择是否启用该规则。前端会默认加载 6 条规则,用于将模型名称统一为:

  • 小写
  • 没有分组标识
  • 使用 - 作为连接符
  • 去除日期

的模型名称,有需要的话可以自行添加其他的规则。

这里正则规则的实现基于标准的 JavaScript String.prototype.replace() 方法,因此也可以实现一些例如捕获组或者是反向引用之类的功能。
例如我自己是添加了这样的规则来统一一下 claude 模型的命名:

  • 正则:^claude-(.+?)-(opus|sonnet|haiku)$ 替换:claude-$2-$1
  • 正则:-(\d+)-(\d+)$ 替换:-$1.$2

添加了这两个规则后,模型名称就会从原来的 claude-3-7-sonnet 这样版本号在中间的格式变成 claude-sonnet-3.7

批量更新模型

该功能允许用户在供应商列表中选择一个或多个的供应商,并批量更新其模型列表。

批量更新时,可以选择开启自动同意变更和自动重命名功能。

使用日志

使用日志主要展示 API 的调用情况:调用时间、模型名称(不是别名)、供应商、请求类型、状态、请求总耗时、Tokens 用量情况、首字耗时和错误信息。

写在最后

因为拼好 AI 目前其实是还没出到正式版的,基本上是一边用一边修修补补,因此功能和特性估计都不是很稳定,凑合着用吧(x

90 个赞

挺实用的 下来部署一个 刚好有需求

收藏备用!

大佬牛啊

1 个赞

T佬 :saluting_face: :saluting_face:

拼!都可以拼!

这个功能好哦,new-api 是不是还没有

厉害 又可以改改了

1 个赞

挺好的~我之前也想弄一个,一直没时间~

联想到智谱拼好模

我是针对gptload→newapi做了个pyhon单机中转 看楼主这个基本都实现了

自动重命名靠字符串处理的话其实当时我测试,感觉对某些调换顺序的处理很麻烦
比如claude-4-sonnet调换成了claude-sonnet-4,靠正则很难处理

所以我自己的项目是采用的计算两个模型名的相似度,达到阈值就进行匹配,这样的效果要好很多,不过其实也有一定的局限性(主要是openai命名太不当人了

大佬 辛苦了牛掰

直接加了对应就行 相似度也不是很完美 会把短的乱认

我docker映射到别的端口 打开网页显示 Cannot GET / docker里面status是404

1 个赞

支持cc的拼接嘛?

2 个赞

哦 我明白了 等会儿有下载并解压前端文件失败:下载文件失败

docker拼接

cc能拼吗 :tieba_001:

这个一般是GitHub连接超时了,如果没法改善连接的话可以先用ghcr.io/meowsalty/pinai:ci-latest。最新的代码里面有加到GitHub代理的功能,可以通过环境变量 GITHUB_PROXY 来设置例如 https://hk.gh-proxy.com 这样的GitHub加速服务域名。