自建部署

API 中转站源码怎么选?New API、Sub2API、One API 与 LiteLLM 对比

常见的开源中转站源码有 New API、Sub2API、One API 和 LiteLLM。要带用户、分组和额度后台的多模型中转站,先看 New API;One API 自 2025 年 2 月后没有新版本;Sub2API 面向订阅额度分发,README 明确提示可能违反上游服务条款;LiteLLM 适合团队内部统一网关。下面是对比表、官方 Docker 命令和上线前的核验方法。

API 中转站源码封面,展示协议兼容、许可证、安全计量与维护活跃度四项判断
开源 AI 网关的四项选型依据:协议兼容、许可证、安全计量与维护活跃度。

直接答案:中转站源码选哪个

  • 要带用户、分组、额度和计费后台的多模型中转站:先试 New API。它在 One API 基础上二次开发,仍在频繁发布,许可证是 AGPL-3.0。README 写明:作为面向公众的生成式 AI 服务或 API 转售服务运营前,要先完成备案、内容安全、实名、日志留存、税务、支付和上游授权等合规义务。
  • 老教程里的 One API:MIT 许可证,仓库未归档,Docker Hub 上的镜像也还在,但最近一个正式 Release 停在 2025-02-02 的 v0.6.10。新部署建议和 New API 一起评估。
  • Sub2API:定位是把 AI 产品订阅额度分发成 API Key。README 开头提示:使用它可能违反 Anthropic 等上游服务商的服务条款,项目仅供学习研究,作者未授权任何商业运营。
  • 团队内部统一网关、偏 Python 技术栈:LiteLLM Proxy,主体为 MIT 许可证(enterprise/ 目录另有许可证)。
  • 已有 API 网关或 Kubernetes 平台:在现有网关上加 AI 能力:Apache APISIX 的 ai-proxy 插件、Kong AI Gateway,或在 Envoy Gateway 之上部署 Agent Router(原 Envoy AI Gateway)。见下文已有网关平台的官方入口。

不论选哪个,都先锁定版本,跑一遍协议、计量和安全测试,再接真实流量。想直接动手,看 New API Docker 部署教程。

New API、Sub2API、One API、LiteLLM 对比

下表按各项目的 GitHub 仓库、README 与 Releases 页面整理,不是排名。

项目仓库许可证技术栈与部署适合场景最近发布
New APIQuantumNous/new-apiAGPL-3.0,另有第 7 条附加条款:修改版须保留作者署名和指向原项目的可见链接后端 Go + Gin,控制台 React 19 + TypeScript;Docker 单容器(SQLite),或 Docker Compose(默认 PostgreSQL + Redis),主库也支持 MySQL多用户、多渠道、分组、额度与用量日志的多模型中转站;对外提供 OpenAI Chat Completions / Responses、Anthropic Messages 和 Gemini 接口v1.0.0-rc.42(2026-10-08,GitHub 标记为 Latest)
Sub2APIWei-Shaw/sub2apiLGPL-3.0(或更高版本)后端 Go + Gin + Ent,前端 Vue 3;依赖 PostgreSQL 15+ 与 Redis 7+;安装脚本、Docker Compose 或源码构建把 AI 产品订阅额度分发为 API Key,内置 Token 级计费、并发与速率限制、支付;README 提示可能违反上游服务条款,仅供学习研究v0.2.15(2026-10-09)
One APIsongquanpeng/one-apiMIT;README 另要求在页面底部保留署名和项目链接,不保留需先获授权后端 Go,前端 React;Docker 单容器,默认 SQLite,设置 SQL_DSN 后改用 MySQL 等外部数据库维护存量实例、对照旧教程;它是 New API 的上游项目v0.6.10(2025-02-02);默认分支最近提交在 2025-02-21
LiteLLM ProxyBerriAI/litellmMIT(enterprise/ 目录除外,适用该目录内的许可证)Python;README 用 uv tool install 'litellm[proxy]' 安装,也有官方 Docker 镜像,默认端口 4000;虚拟 Key 需要数据库团队内部用 OpenAI 格式统一调用 100+ 模型提供商;虚拟 Key、花费追踪、负载均衡和管理后台v1.104.2(2026-10-08,GitHub 标记为 Latest)
核验日期

表中许可证、技术栈、部署方式和最近发布于 2026-10-09 对照各项目 GitHub 仓库、README 和 Releases 页面复核。New API、Sub2API、LiteLLM 发布频繁,部署前请重新打开 Releases 页确认,并固定具体版本号,不要长期跟随 latest。

许可证怎么读:New API 使用 AGPL-3.0,其第 13 条要求:如果你修改了程序,并让用户通过网络与修改版交互,就要向这些用户提供修改版的对应源码。One API 虽是 MIT,README 另加了保留署名的要求。商用前按实际使用和分发方式评估,必要时咨询专业意见。

One API 还能用吗?仓库未归档,Docker Hub 上的镜像也还在,但最近一个正式 Release 是 2025-02-02 的 v0.6.10。之后只有 2025-02-16 的 v0.6.11-preview.7 预览标签;README 命令里不带标签的 justsong/one-api 镜像拉取的是 latest,它对应的正是这个预览版。此后没有新版本,新模型和新接口要靠自己补。New API 的 README 写明它基于 One API 二次开发,新部署一般优先评估 New API;已有 One API 实例要迁移,先备份数据库,在测试环境验证后再切换。

最快跑起来:New API 与 Sub2API 的 Docker 命令

以下命令原样摘自两个项目的官方 README(2026-10-09 版本),适合在本机或测试机上先跑起来看一眼。正式部署的数据库、反向代理、HTTPS 与备份,见 New API Docker 部署教程。

New API:单容器 + SQLite,只监听本机

mkdir -p data
docker run --name new-api -d --restart unless-stopped \
  -p 127.0.0.1:3000:3000 \
  -e TZ=Asia/Shanghai \
  -v "$(pwd)/data:/data" \
  calciumion/new-api:latest

启动后打开 http://localhost:3000,按初始化向导创建管理员账号。命令只监听 127.0.0.1;在远程测试机上运行时,先在本机建 SSH 隧道(如 ssh -L 3000:127.0.0.1:3000 user@服务器IP),再在本机打开 http://localhost:3000。SQLite 数据库存放在挂载的 data 目录,换容器后仍会保留。正式环境用仓库自带的 docker-compose.yml(New API + PostgreSQL + Redis),启动前替换示例密码,并设置固定的随机 SESSION_SECRET。通过 HTTPS 访问控制台时,还要设置 SESSION_COOKIE_SECURE=true,并在 SESSION_COOKIE_TRUSTED_URL 中填写控制台对外的 HTTPS Origin(Secure 模式下必填)。官方文档见 New API 安装说明。

Sub2API:Docker Compose 一键准备脚本

# 创建部署目录
mkdir -p sub2api-deploy && cd sub2api-deploy

# 下载并运行部署准备脚本
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash

# 启动服务
docker compose up -d

# 查看日志
docker compose logs -f sub2api

前置条件是 Docker 20.10+ 和 Docker Compose v2+。脚本会下载 docker-compose.local.yml(本地保存为 docker-compose.yml)和 .env.example,自动生成 JWT_SECRET、TOTP_ENCRYPTION_KEY、POSTGRES_PASSWORD 并写入 .env。启动后访问 http://服务器IP:8080;管理员账号若是自动生成的,在日志里搜索 Generated admin。用管道执行远程脚本前,建议先把脚本下载到本地看一遍。

LiteLLM 的 Docker 启动方式见官方 LiteLLM Proxy Docker 快速开始。跑起来只是第一步,上线前还要过下面的适用边界、选型维度和合同测试。

API 中转站源码的适用边界与请求链路

简单反向代理适合协议几乎不变、租户少且无需复杂账单的团队;开源 AI 网关适合需要统一鉴权、路由、限流和观测且能承担平台工程的团队;带用户、余额、渠道和计量后台的源码则扩大了身份、财务数据与迁移责任。不要把演示后台直接等同于可运营系统。如果只是想让团队调用多个模型、不打算维护网关,也可以直接用托管的 OpenAI 兼容服务,例如 GPTZZZ:Base URL 为 https://gptzzz.ai/v1,Claude Messages 接口为 https://gptzzz.ai/v1/messages,可用模型与价格以GPTZZZ 模型价格页为准。

最小链路应明确为 client → edge/TLS → tenant auth/policy → protocol normalizer → model router → provider adapter → provider,响应再经流式事件规范化、用量记录与审计返回。控制面负责租户、模型目录、密钥和策略版本,数据面不应临时读取未审计配置。更完整的职责拆分可参考自建 API 中转站架构,源码、部署与架构文章汇总在自建 API 中转站专题。

开源 AI API 网关选型维度

维度必须核验的证据淘汰信号
API 网关协议兼容性普通、流式、工具调用、结构化输出、取消、错误码和用量字段回归仅 README curl 或静默丢字段
安全与租户密钥存储/轮换/撤销、最小权限、管理面隔离、日志脱敏与审计默认凭据、明文 Secret、跨租户查询
计量请求级输入/输出/缓存用量、重试分录、价格版本与对账只保留汇总余额,无法复算
AI 网关许可证仓库许可证原文、依赖清单、镜像与修改/分发方式的义务清单许可证不明或依赖来源不可追溯
开源 API 网关维护稳定发布、安全公告、升级说明、贡献者集中度、依赖更新和恢复演练关键漏洞无人响应或迁移不可回滚
退出能力配置、模型映射、用量与审计可导出,内部客户端可切换专有数据格式且无迁移验证

协议核验可直接套用API 中转站协议测试指南;安全基线见API Key 安全指南。每条结论标注“官方声明、代码可见、当前版本已验证”中的哪一类,不把 README 声明当测试结论。

已有网关平台:APISIX、Envoy Gateway、Kong

已经在用 API 网关或 Kubernetes 的团队,可以在现有网关上加 AI 能力,而不是另起一套带用户后台的中转站。Envoy 这一侧的 AI 路由由单独的项目 Agent Router(原 Envoy AI Gateway)提供,在 Kubernetes 上与 Envoy Gateway 一起部署。下面只列官方入口,不是排名;开始 PoC 时记录具体版本,并再次打开官方页面核对。

候选先从官方资料核验什么适配前必须实测
Apache APISIX ai-proxy 插件支持的提供商、认证、路由与配置方式插件与网关版本组合、流式与失败语义
Envoy Gateway 限流文档本地与全局限流、策略作用范围限流策略与网关版本组合;需要 AI 路由时配合下一行的 Agent Router
Agent Router(原 Envoy AI Gateway)文档支持的 AI 提供商、在 Envoy Gateway 上的部署方式、Apache 2.0 许可证与 Envoy Gateway 的版本组合、流式、用量统计与失败语义
Kong AI GatewayAI Gateway 能力、插件与版本、发行形态所需能力对应的版本与请求回归

API 中转站源码选型如何评分与估算三年成本

只对通过硬门槛的候选计算 weighted_score = Σ(weight_i × verified_score_i)。weight_i 是团队为协议、安全、运维、退出等维度设置且合计为 1 的权重;verified_score_i 是锁定版本经过测试后的得分,未测试项不得按满分处理。示例变量可以是协议 0.30、安全 0.30、运维 0.25、退出 0.15,而不是预设某项目胜出。

长期成本使用 3-year_tco = infra + operations + migration + incident_cost:infra 为计算、存储、网络和观测资源;operations 为升级、值班、对账与安全维护工时;migration 为数据/客户端迁移与回归;incident_cost 为故障演练设定的期望事故成本变量。全部由团队填入自己的可审计假设,不在文章中硬编码金额。

可复现:在 localhost 运行 API 中转站源码合同测试

下面的零依赖 fixture 只监听 127.0.0.1:18080,不会访问上游。它把鉴权、字段、正文大小、模型、流式和 429 行为固定下来,既可独立验证校验器,也可把 BASE 改为已锁定版本的候选网关。密钥只从 LAB_API_KEY 环境变量读取。

1. 固定仓库与提交,并复制工作配置

: "${COMMIT:?先设置已审计的 40 位提交 SHA}"
printf '%s' "$COMMIT" | grep -Eq '^[0-9a-f]{40}$'
export REPO_URL=https://github.com/BerriAI/litellm.git
git clone --filter=blob:none "$REPO_URL" candidate.work
git -C candidate.work checkout --detach "$COMMIT"
test "$(git -C candidate.work rev-parse HEAD)" = "$COMMIT"
printf 'listen: 127.0.0.1\nport: 18080\n' > candidate.work/config.baseline.yaml
cp candidate.work/config.baseline.yaml candidate.work/config.work.yaml
git -C candidate.work status --short

候选项目的真实启动参数以该提交的官方文档为准;不要自动跟随 latest。先用下面 fixture 建立合同基线,再将校验器的 BASE 改成候选的 localhost 端口。

2. 启动本地候选 fixture

#!/usr/bin/env python3
import json, os
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

KEY = os.environ["LAB_API_KEY"]
MAX_BODY = 4096
ALLOWED = {"model", "messages", "max_tokens", "stream"}

class Handler(BaseHTTPRequestHandler):
    def send_json(self, status, value):
        body = json.dumps(value, ensure_ascii=False, separators=(",", ":")).encode()
        self.send_response(status)
        self.send_header("content-type", "application/json; charset=utf-8")
        self.send_header("content-length", str(len(body)))
        self.end_headers(); self.wfile.write(body)

    def do_POST(self):
        if self.path != "/v1/chat/completions":
            return self.send_json(404, {"error":{"type":"not_found"}})
        if self.headers.get("Authorization") != f"Bearer {KEY}":
            return self.send_json(401, {"error":{"type":"invalid_api_key"}})
        try: length = int(self.headers.get("Content-Length", "0"))
        except ValueError: return self.send_json(400, {"error":{"type":"bad_length"}})
        if length < 2 or length > MAX_BODY:
            return self.send_json(413, {"error":{"type":"request_too_large","max_bytes":MAX_BODY}})
        try: req = json.loads(self.rfile.read(length))
        except Exception: return self.send_json(400, {"error":{"type":"invalid_json"}})
        if not isinstance(req, dict):
            return self.send_json(400, {"error":{"type":"request_must_be_object"}})
        unknown = sorted(set(req) - ALLOWED)
        if unknown: return self.send_json(400, {"error":{"type":"unknown_field","fields":unknown}})
        if req.get("model") != "lab-model":
            return self.send_json(404, {"error":{"type":"model_not_found"}})
        messages, limit = req.get("messages"), req.get("max_tokens", 8)
        if not isinstance(messages, list) or not 1 <= len(messages) <= 16:
            return self.send_json(422, {"error":{"type":"messages_out_of_range"}})
        if not isinstance(limit, int) or not 1 <= limit <= 32:
            return self.send_json(422, {"error":{"type":"max_tokens_out_of_range","min":1,"max":32}})
        if "stream" in req and not isinstance(req["stream"], bool):
            return self.send_json(422, {"error":{"type":"stream_must_be_boolean"}})
        content = str(messages[-1].get("content", "")) if isinstance(messages[-1], dict) else ""
        if content == "force_429":
            return self.send_json(429, {"error":{"type":"rate_limit","retryable":True}})
        if req.get("stream") is True:
            chunks = 'data: {"choices":[{"delta":{"content":"pong"}}]}\n\ndata: [DONE]\n\n'.encode()
            self.send_response(200); self.send_header("content-type", "text/event-stream")
            self.send_header("content-length", str(len(chunks))); self.end_headers(); self.wfile.write(chunks); return
        self.send_json(200, {"id":"lab-1","model":"lab-model","choices":[{"message":{"role":"assistant","content":"pong"}}],"usage":{"prompt_tokens":3,"completion_tokens":2,"total_tokens":5}})

    def log_message(self, fmt, *args): pass

ThreadingHTTPServer(("127.0.0.1", 18080), Handler).serve_forever()
export LAB_API_KEY="$(python -c 'import secrets; print(secrets.token_urlsafe(24))')"
python gateway_contract_fixture.py
# 另开终端,并设置同一个 LAB_API_KEY 后执行校验器

3. 运行合同校验器

#!/usr/bin/env python3
import json, os, urllib.error, urllib.request
BASE = "http://127.0.0.1:18080/v1/chat/completions"
KEY = os.environ["LAB_API_KEY"]

def call(payload, key=KEY):
    req = urllib.request.Request(BASE, data=json.dumps(payload).encode(), method="POST",
        headers={"content-type":"application/json","authorization":f"Bearer {key}"})
    try:
        with urllib.request.urlopen(req, timeout=2) as r: return r.status, r.headers.get("content-type"), r.read().decode()
    except urllib.error.HTTPError as e: return e.code, e.headers.get("content-type"), e.read().decode()

base = {"model":"lab-model","messages":[{"role":"user","content":"ping"}],"max_tokens":8}
cases = [
 ("success", call(base)[0] == 200),
 ("bad_auth", call(base, "wrong")[0] == 401),
 ("bad_limit", call({**base,"max_tokens":33})[0] == 422),
 ("bad_shape", call([])[0] == 400),
 ("bad_stream_type", call({**base,"stream":"true"})[0] == 422),
 ("unknown_model", call({**base,"model":"missing"})[0] == 404),
 ("rate_limit", call({**base,"messages":[{"role":"user","content":"force_429"}]})[0] == 429),
 ("stream", call({**base,"stream":True})[1].startswith("text/event-stream")),
]
passed = sum(ok for _, ok in cases); rate = passed / len(cases)
print(json.dumps({"cases":cases,"passed":passed,"total":len(cases),"contract_pass_rate":rate}, ensure_ascii=False))
raise SystemExit(0 if rate == 1.0 else 1)
python validate_contract.py

成功输出示例:{"passed":8,"total":8,"contract_pass_rate":1.0}。只要进程退出码非零,候选就不能进入下一阶段。

4. 直接请求与成功/失败响应样例

curl -i http://127.0.0.1:18080/v1/chat/completions \
  -H "Authorization: Bearer $LAB_API_KEY" -H "Content-Type: application/json" \
  -d '{"model":"lab-model","messages":[{"role":"user","content":"ping"}],"max_tokens":8}'
curl -i http://localhost:18080/v1/chat/completions \
  -H "Authorization: Bearer wrong" -H "Content-Type: application/json" \
  -d '{"model":"lab-model","messages":[{"role":"user","content":"ping"}]}'
curl -N http://127.0.0.1:18080/v1/chat/completions \
  -H "Authorization: Bearer $LAB_API_KEY" -H "Content-Type: application/json" \
  -d '{"model":"lab-model","messages":[{"role":"user","content":"ping"}],"stream":true}'

成功响应样例: HTTP/1.0 200,正文含 {"id":"lab-1","model":"lab-model","choices":[{"message":{"role":"assistant","content":"pong"}}],"usage":{"prompt_tokens":3,"completion_tokens":2,"total_tokens":5}}。

失败响应样例: 错误密钥返回 HTTP/1.0 401 与 {"error":{"type":"invalid_api_key"}};超过 4096 字节返回 413;max_tokens=33 返回 422;内容为 force_429 返回 429 且标记可重试。

参数边界、拒绝行为与失败模式

输入/故障边界或预期拒绝/观察
Authorization必须精确匹配环境变量密钥401 invalid_api_key,不得访问路由层
请求体2–4096 字节;JSON 可解析;只允许四个顶层字段400 或 413,并列出未知字段
messages / max_tokens消息 1–16 条;max_tokens 1–32422,不进行静默截断
模型/协议仅 lab-model;stream 必须是布尔值404;真实候选另加错误语义断言
429/5xx/断流只按幂等性和剩余截止时间有限重试记录 attempt ID;已输出 SSE 后不得拼接新响应
计量缺失每次尝试都应有来源明确的用量进入待对账,不猜测或默认为零

可计算指标与验收阈值

  • contract_pass_rate = passed_required / required,八个必选合同阈值为 1.00。
  • unknown_field_rejection_rate = rejected_unknown / tested_unknown,阈值为 1.00,作为真实候选的扩展测试。
  • usage_delta = abs(reported_total - (prompt + completion)),阈值为 0,作为真实候选的扩展计量测试。
  • secret_leak_count:扫描 stdout、错误正文与日志中的测试密钥,阈值为 0,作为真实候选的扩展日志测试。

逐步故障排查

  1. 用 Get-NetTCPConnection -LocalPort 18080 或 ss -ltnp 确认只监听 127.0.0.1。
  2. 若连接失败,检查 fixture 进程与端口冲突;若 401,确认两个终端使用相同环境变量而不是把密钥写进文件。
  3. 若 JSON 合同失败,保存状态码、content-type 和原始响应,再比较锁定提交前后的字段差异。
  4. 若仅 SSE 失败,用 curl -N 检查事件边界、[DONE]、代理缓冲和取消传播。
  5. 若计量不一致,按 request ID 展开每个 attempt,确认重试没有被重复或遗漏汇总。

明确回滚 runbook

# 1) 停止当前 localhost 候选进程(前台运行时 Ctrl-C)
# 2) 恢复工作配置,原 baseline 不动
cp candidate.work/config.baseline.yaml candidate.work/config.work.yaml
# 3) 回到上一条已通过合同测试的提交
: "${LAST_GOOD_COMMIT:?设置上一条已验证的 40 位 SHA}"
git -C candidate.work checkout --detach "$LAST_GOOD_COMMIT"
# 4) 重启后再次执行,只有 8/8 才恢复流量
python validate_contract.py
# 5) 失败则保持流量为零并保留响应、提交 SHA 与日志证据

部署与运维检查表

  • 固定源码版本、依赖锁文件与镜像摘要,保存可重复构建证据。
  • 分离管理面和调用面;启用最小权限、密钥轮换、撤销与管理操作审计。
  • 执行协议、限流、熔断、断流、账单复算、备份恢复和回滚演练。
  • 设置按租户/模型/上游的容量、SLO、告警与请求 ID,下钻时默认脱敏。
  • 建立版本观察窗口、安全公告责任人、升级节奏和替代网关退出演练。

上线前的日志和排障字段可对照API 中转站可观测性指南,并把每次升级的相同测试结果作为验收附件。

许可证、数据与合规风险排查

风险面排查问题证据/动作
许可证主项目、依赖、前端资产和镜像分别适用什么条款?使用、修改、分发方式触发哪些义务?保存版本对应许可证与依赖清单,交由合适人员按实际使用方式评估
数据提示词、附件、身份、用量进入哪些日志、缓存、数据库和备份?数据流图、字段清单、保留/删除测试与脱敏样本
供应链构建是否可复现,依赖与镜像来源是否锁定,更新是否经过审查?SBOM、签名/摘要、扫描报告与回滚记录
运营责任谁响应安全公告、密钥泄露、账单差异和上游协议变更?责任矩阵、值班手册与演练记录

这是一份技术排查清单,不构成法律结论;不同地区、组织和分发方式需要结合最新官方条款与专业意见判断。

API 中转站源码常见问题

API 中转站源码怎么选,第一步是什么?

先写清适用边界和硬门槛:所需模型能力、协议、数据地域、许可证接受范围、租户隔离与维护资源。只有通过硬门槛的候选,才进入固定版本的回归测试和加权评分。

API 中转站 GitHub Star 多就更可靠吗?

不一定。Star 反映关注度,不证明当前版本的安全、协议兼容、计量准确或维护响应。应核验官方发布、安全公告、依赖更新,并用自己的测试证据确认。

如何测试 API 网关协议兼容性?

用同一套请求覆盖普通响应、SSE、取消、工具调用、结构化输出、未知字段、429、5xx 和用量,再比较语义与错误;README 的支持声明不能替代锁定版本的回归结果。

AI 网关许可证核验只看仓库根目录够吗?

不够。还要记录依赖、镜像、前端资产和修改或分发方式,并按对应版本保存许可证材料;义务判断应结合实际使用方式和合适的专业意见。

什么时候不适合自建开源 AI 网关?

团队无法持续承担密钥轮换、安全补丁、容量、监控、账单对账、备份恢复和事故响应时,不适合把关键流量交给自建方案。

开源 AI 网关有哪些项目值得进入候选池?

常见的开源中转站源码有 New API、Sub2API、One API 和 LiteLLM;已有网关平台的团队还可以看 Apache APISIX(ai-proxy 插件)、Kong AI Gateway,或在 Envoy Gateway 之上部署 Agent Router(原 Envoy AI Gateway)。能否进入短名单,取决于锁定版本的协议、安全、计量、许可证和运维测试结果。

New API 和 One API 有什么区别?

New API 基于 One API(MIT)二次开发,许可证为 AGPL-3.0,目前仍在频繁发布;One API 最近一次发布是 2025-02-02 的 v0.6.10。新部署一般优先评估 New API;已有 One API 实例迁移前先备份数据库,并在测试环境验证。

Sub2API 可以拿来做公开的中转站吗?

Sub2API 的 README 写明:使用它可能违反 Anthropic 等上游服务商的服务条款,项目仅供技术学习与研究,作者从未授权任何个人或组织基于它开展商业运营。用于任何场景前,先读清上游条款和当地法规。

用 Docker 搭建中转站最少要准备什么?

一台能跑 Docker 的服务器、持久化的数据目录或数据库、合法取得的上游 API Key,以及反向代理和 HTTPS。New API 单容器默认用 SQLite,仓库自带的 Compose 默认启动 New API + PostgreSQL + Redis;Sub2API 需要 PostgreSQL 15+ 和 Redis 7+。分步操作见 New API Docker 部署教程。

API 中转站源码是否支持请求级用量计量?

不能只看 README 中是否写有计费功能。应对锁定提交发送成功、失败、重试、流式取消和缓存请求,验证每个 attempt 的 Token 来源、价格版本、请求 ID 与最终结算是否可复算。

如何判断开源 API 网关维护是否活跃?

同时核对近期发布、已知安全问题响应、兼容性回归、升级说明、维护者数量和破坏性变更处理;Star 与最后提交时间只能作为线索,不能替代版本化测试和退出演练。

提示

项目功能、许可证、版本与维护状态会变化;上线判断以锁定版本、官方资料和可重复测试为准。