自从 Pandora-Next 的作者 pengzhile (始皇)宣布 Pandora-Next 停止运营,愉快的享受免费不限量高并发的 ChatGPT 3.5 API 的日子也就结束了。虽然现在很多第三方 API 提供商也提供很多免费额度使用,甚至多的不一定用得完,但是这究其根本在中国大陆的法律上应该是违法行为,也不一定能保证这些第三方提供商的服务就一直稳定,就像始皇停止运营来的那么突然一样。靠谁都不如靠自己,自己部署一个 server 才更靠谱。
经过我的一段时间探索和使用,目前总算是找到了一套差不多算是可以平替的方案,使用到了三个开源仓库:
ninja ninja 用于和 OpenAI 进行中转,把 chat 的接口转换 api 的接口,不过由于 ninja 作者开发 ninja 的理念是服务端不存储用户数据,所以 ninja 的 ChatGPT-to-API 接口需要使用 access_Token 做 API Keys ,受限于 access_Token 的有效时间太短以及 access_Token 过长的问题,并不能很愉快的使用。但是 ninja 有使用 refresh_token 获取 access_Token 的接口,因为 refresh_token 的长度很短,且永久有效,所以我在 ninja 的 issue 中 提议,使用 refresh_token 当做 API Keys 进行请求,但是被作者因为与其不存储用户数据的理念相悖而被否决。
refresh-gpt-chat refresh-gpt-chat 用于把 ninja 的 api 接口转换成使用 refresh_token 作为 API Keys 进行请求。实际上是 refresh-gpt-chat 先使用 refresh_token 请求 access_Token ,再使用获取到的 access_Token 请求 API ,并把这个 access_Token 存储下来,反复使用。当 access_Token 过期时,再重新使用 refresh_token 请求 access_Token 。
one-api one-api 用于存储多个 refresh_token ,提高并发量。因为 ninja 提供的 API 功能还是基于 OpenAI 的 chat 的 web ,而 web 又无法并发,必须等一句话说完,才能响应下一次请求,所以对于某些需要高并发的使用场景来讲, ninja 配合 refresh-gpt-chat 是不够的。但是在 one-api 内新建多个渠道,每个都存放一个 refresh_token ,用于请求 refresh-gpt-chat ,再使用 one-api 提供的接口,就能解决高并发的问题,愉快使用。而且 refresh_token 如果泄露也不好, one-api 二次分发就能避免 refresh_token 泄露的问题,让我无后顾之忧的把自己的 API Keys 提供给他人使用。
部署
部署上述服务,需要准备: 1、一台在 OpenAI 封锁之外的 VPS ; 2、一定的智慧和解决问题的能力。
部署步骤也并不复杂,特别是 ninja 和 one-api ,几乎是开箱即用,refresh-gpt-chat只要部署好了 Java 环境,运行也很简单。当然如果 VPS 能够支持 Docker ,甚至只需要 docker-compose.yaml
直接跑就行了。
Docker compose 以下是我写的,把上述三个仓库的服务一口气跑起来的docker-compose.yaml
,只需要修改最末 refresh-gpt-chat 部分的 getAccessTokenUrl
和chatUrl
两个参数配置即可直接 docker compose up -d
使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 version: '3.4' services: ninja: image: gngpp/ninja:latest container_name: ninja restart: unless-stopped environment: - TZ=Asia/Shanghai command: run ports: - "8080:7999" watchtower: container_name: watchtower image: containrrr/watchtower volumes: - /var/run/docker.sock:/var/run/docker.sock command: --interval 3600 --cleanup restart: unless-stopped one-api: image: justsong/one-api:latest container_name: one-api restart: always command: --log-dir /app/logs ports: - "3000:3000" volumes: - /project/sandbox/data/oneapi:/data - /project/sandbox/logs:/app/logs environment: - SQL_DSN=oneapi:123456@tcp(db:3306)/one-api - REDIS_CONN_STRING=redis://redis - SESSION_SECRET=random_string - TZ=Asia/Shanghai depends_on: - redis - db healthcheck: test: [ "CMD-SHELL" , "wget -q -O - http://localhost:3000/api/status | grep -o '\"success\":\\s*true' | awk -F: '{print $2}'" ] interval: 30s timeout: 10s retries: 3 redis: image: redis:latest container_name: redis restart: always db: image: mysql:8.2.0 restart: always container_name: mysql volumes: - /project/sandbox/data/mysql:/var/lib/mysql ports: - '3306:3306' environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: 'OneAPI@justsong' MYSQL_USER: oneapi MYSQL_PASSWORD: '123456' MYSQL_DATABASE: one-api refresh-gpt-chat: image: yangclivia/refresh-gpt-chat:latest environment: - JAVA_OPTS=-XX:+UseParallelGC -Xms64m -Xmx64m -XX:MaxMetaspaceSize=64m container_name: refresh-gpt-chat restart: always user: root ports: - "8082:8082" command: - --log=info - --server.port=8082 - --getAccessTokenUrl=http(s)://ninja的外部访问地址/auth/refresh_token - --chatUrl=http(s)://ninja的外部访问地址/v1/chat/completions
手动部署 ninja 和 one-api 都可以直接下载可执行文件直接启动,无需配置其他环境,这里不做过多介绍,仅仅记录一下启动的命令。
ninja: 在仓库中直接下载对应自己的 VPS 系统的可执行二进制文件即可。
1 2 3 4 5 6 7 8 9 10 chmod +x ninja./ninja run ./ninja start ./ninja stop pm2 start ./ninja --name ninja -- run
one-api 在仓库中直接下载对应自己的 VPS 系统的可执行二进制文件即可。
1 2 3 4 5 6 7 8 chmod u+x one-apiexport TIKTOKEN_CACHE_DIR="$PWD " ./one-api --port PORT --logs-dir ./logs pm2 start ./one-api --name one-api -- --port PORT --logs-dir ./logs
refresh-gpt-chat 需要配置 OpenJDK , 前文在 hax 的免费主机上已经安装过 OpenJDK ,这里不再赘述。在仓库中下载 .jar
结尾的 fat jar 包即可直接启动:
1 2 3 4 java -jar refresh-gpt-chat-0.0.1-SNAPSHOT.jar --server.port=PORT --server.servlet.context-path=/ --getAccessTokenUrl=http(s)://ninja的访问地址/url/auth/refresh_token --chatUrl=http(s)://ninja的访问地址/v1/chat/completions pm2 start java --name refresh-gpt-chat -- -jar refresh-gpt-chat-0.0.1-SNAPSHOT.jar --server.port=PORT --server.servlet.context-path=/ --getAccessTokenUrl=http(s)://ninja的访问地址/url/auth/refresh_token --chatUrl=http(s)://ninja的访问地址/v1/chat/completions
使用 进入 one-api 渠道选项卡中,添加新的渠道,类型选择自定义渠道, Base URL
填写 refresh-gpt-chat 的地址,模型选择 gpt-3.5 相关的全部模型。模型重定向中填入以下内容:
1 2 3 4 5 6 7 8 { "gpt-3.5-turbo-0301" : "gpt-3.5-turbo" , "gpt-3.5-turbo-0613" : "gpt-3.5-turbo" , "gpt-3.5-turbo-16k" : "gpt-3.5-turbo" , "gpt-3.5-turbo-16k-0613" : "gpt-3.5-turbo" , "gpt-3.5-turbo-1106" : "gpt-3.5-turbo" , "gpt-3.5-turbo-instruct" : "gpt-3.5-turbo" }
勾选中秘钥下方的批量创建,然后在秘钥中填入 refresh_token ,一行一个,最后点击提交。再去令牌选项卡中添加新的令牌,按照自己的喜好填写并提交即可。
再使用 one-api 生成的令牌作为 API Keys , one-api 的地址作为端点即可。
有多高并发取决于有多少 refresh_token 被存储在 one-api 中,如果需要使用沉浸式翻译这样的高并发应用,建议存入 20-100 个 refresh_token 进行请求。
获取 refresh_token 的网址:xyhelper 、freegpts (这两个都是第三方服务,不能保证账号数据安全,也不能保证其服务一直有效,酌情使用,后果自负)
亦或者可以使用 Apple 设备抓包获取 refresh_token ,具体可以自己搜索。不过这种方式容易导致 Apple 设备被 OpenAI 封禁,请酌情使用。