自建 GPT 共享 API 网关:让同学白嫖你的 OpenAI,你还能省钱
自建 GPT 共享 API 网关:让同学白嫖你的 OpenAI,你还能省钱
一个 V2EX 帖子让我意识到,很多人用 sub2api 共享 GPT 订阅,但绕了一大圈,其实有更简单的方案。
先说痛点
室友找你要 ChatGPT 账号,你把密码给他,结果:
- 对话历史全混在一起
- 他用完你的 GPT-4o 配额
- 某天他不小心改了你的 System Prompt
- 你们同时登录,账号被风控
于是你开始研究 sub2api、共享订阅、拼车……折腾半天,不如自己起一个 API 转发网关,给同学发一个独立 API Key,隔离干净,用量全透明。
思路拆解
同学的客户端
↓ 你发给他的 key
你的转发网关(本机 or 服务器)
↓ 你自己的 key 或第三方 API
OpenAI / Claude / Gemini
网关做三件事:
1. 验证同学的 key(鉴权)
2. 转发请求到上游
3. 记录用量,可以限速/限额
完整实现:50 行 Python
依赖只有 fastapi 和 httpx,部署到本机或任意 VPS 都行。
# gateway.py
import os, httpx
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import StreamingResponse
app = FastAPI()
# 你发给同学的 key 白名单(可以加数据库)
ALLOWED_KEYS = {
"sk-roommate-alice": "alice",
"sk-roommate-bob": "bob",
}
# 上游 API 配置
UPSTREAM_BASE = "https://api2everything.xyz/v1" # 国内直连,不需要代理
UPSTREAM_KEY = os.environ["UPSTREAM_API_KEY"] # 你自己的上游 key
@app.post("/v1/{path:path}")
async def proxy(path: str, request: Request):
# 1. 鉴权
auth = request.headers.get("Authorization", "")
token = auth.removeprefix("Bearer ").strip()
if token not in ALLOWED_KEYS:
raise HTTPException(status_code=401, detail="Invalid key")
user = ALLOWED_KEYS[token]
body = await request.body()
# 2. 转发到上游
headers = {
"Authorization": f"Bearer {UPSTREAM_KEY}",
"Content-Type": "application/json",
}
async def stream():
async with httpx.AsyncClient(timeout=120) as client:
async with client.stream(
"POST",
f"{UPSTREAM_BASE}/{path}",
headers=headers,
content=body,
) as resp:
print(f"[{user}] {path} -> {resp.status_code}")
async for chunk in resp.aiter_bytes():
yield chunk
return StreamingResponse(stream(), media_type="text/event-stream")
启动:
pip install fastapi httpx uvicorn
UPSTREAM_API_KEY=sk-xxx uvicorn gateway:app --host 0.0.0.0 --port 8000
同学的配置只需要改两行:
from openai import OpenAI
client = OpenAI(
base_url="http://你的IP:8000/v1", # 指向你的网关
api_key="sk-roommate-alice", # 你发给他的专属 key
)
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "你好"}]
)
print(resp.choices[0].message.content)
加上用量统计(可选,10 行)
在 stream() 里用完整响应替代流式,可以拿到 token 用量写入文件或 SQLite:
# 非流式版本,方便计费
async with httpx.AsyncClient(timeout=120) as client:
resp = await client.post(
f"{UPSTREAM_BASE}/{path}",
headers=headers,
content=body,
)
data = resp.json()
usage = data.get("usage", {})
print(f"[{user}] tokens: {usage.get('total_tokens', '?')}")
return data
改成这个之后你就有每个人的用量日志,月底想让室友 AA 也有据可查。
关于上游选哪家
如果你是国内用户,直接调 api.openai.com 需要代理,延迟高还不稳定。我现在用的上游是无量 Api(api2everything.xyz),几个实际用下来的优点:
- 国内直连,代码里不用配置任何代理,
UPSTREAM_BASE = "https://api2everything.xyz/v1"就够了 - 支持 GPT-4o、Claude Sonnet/Opus、Gemini、DeepSeek 等 300+ 模型,上游换模型不用改网关代码
- 价格比官方便宜约 65%,SVIP 还有 7.7 折,给室友用不心疼
- 注册就送 ¥1 余额,测一下零成本
对于这个共享网关场景,上游便宜意味着你分摊给室友的成本也更低,或者干脆自己贴一点也无所谓。
进阶:限速 + 按模型计费
如果你想控制某个同学只能用 gpt-4o-mini 不能用 gpt-4o,在鉴权后加一段:
import json
body_json = json.loads(body)
model = body_json.get("model", "")
if user == "bob" and model.startswith("gpt-4o") and model != "gpt-4o-mini":
raise HTTPException(status_code=403, detail=f"{user} not allowed to use {model}")
按 key 配置允许的模型列表,精确控制成本。
小结
| 方案 | 隔离性 | 用量可见 | 部署难度 |
|------|--------|----------|----------|
| 直接共享账号 | ❌ | ❌ | 零 |
| sub2api 拼车 | 部分 | 部分 | 低 |
| 自建网关(本文) | ✅ | ✅ | 中 |
50 行代码解决账号共享的所有痛点,上游直接对接无量 Api,国内不需要代理,成本直降 60%+。
有问题欢迎评论区留言,比如想加 Web 控制台、限额自动断流、多上游负载均衡,都可以继续聊。觉得有用的话点个赞,后续会继续更实战向的 API 工程内容。
上游 API 注册(新用户送 ¥1):