技术教程 · 阅读约 7 分钟

自建 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):