
使用Scala Play框架构建REST API
凌晨三点,数据中心的灯像一排不肯眨眼的星星。运维群里弹出一条告警:“gpt-oss-120b 集群延迟飙到 2.8 s,token 吞吐量掉到 120 TPS,再顶不住就降级!”
十分钟后,我边喝着冰美式边把一条 curl
命令贴进终端:
curl -X POST https://api.laozhang.ai/v1/chat/completions \
-H "Authorization: Bearer lz_live_xxx" \
-d '{"model":"gpt-oss-20b","messages":[{"role":"user","content":"写一段 200 字的悬疑开场"}]}'
首包 180 ms,全文 1.2 s 返回,群里瞬间安静。
这就是 OpenAI OSS API 的魅力:同一条 HTTP 路径,既能拉起 120 B 的巨兽,也能在 20 B 的轻骑上闪转腾挪。今天,我们就把这套“巨兽+轻骑”的多模型接入方案拆给你看——从 0 到生产,只用 2 小时。
2025 年 8 月,OpenAI 把 GPT-OSS-120B 与 GPT-OSS-20B 一并开源:
两者共用同一套 /v1/chat/completions 路由,Token 计费、参数名称、错误码与 OpenAI 完全一致——这意味着你不需要重学任何 SDK,只要换 base_url
就能完成降级、扩容、灰度、边缘推理的全部操作。
模型 | 推荐显存 | 推荐 GPU | 本地 4090 能否跑? | 云端 1h 成本 |
---|---|---|---|---|
GPT-OSS-20B | 16 GB | RTX 4090 / A5000 | ✅ 50 TPS | $0.6 (Lambda Cloud) |
GPT-OSS-120B | 80 GB | 4×A100 80 GB | ❌ 需量化 | $8.0 (Lambda Cloud) |
实测:在 RTX 4090 上用 INT4 量化可把 120 B 压到 24 GB,吞吐量 8 TPS,适合熬夜调参。
# 20 B 轻骑
ollama pull gpt-oss-20b
ollama run gpt-oss-20b "请用 emojis 解释量子纠缠"
# 120 B 巨兽(需 80 GB 显存)
ollama pull gpt-oss-120b
ollama run gpt-oss-120b --temperature 0.2 "写 500 字硬科幻"
Ollama 会自动识别 /v1/chat/completions
路由,Postman 可直接调。
无需自建,Novita 提供 OpenAI 兼容端点:
curl https://api.novita.ai/v1/chat/completions \
-H "Authorization: Bearer nv_live_xxx" \
-d '{
"model": "gpt-oss-120b",
"messages": [{"role": "user", "content": "写一段 Rust 宏教程"}]
}'
import aiohttp, asyncio, os, time
from tenacity import retry, stop_after_attempt, wait_exponential
class ProductionGPTOSS:
def __init__(self, base="https://api.laozhang.ai"):
self.base = base
self.key = os.getenv("LZ_KEY")
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, max=10))
async def chat(self, payload):
async with aiohttp.ClientSession() as s:
async with s.post(
f"{self.base}/v1/chat/completions",
headers={"Authorization": f"Bearer {self.key}"},
json=payload,
timeout=aiohttp.ClientTimeout(total=30)
) as r:
return await r.json()
async def main():
cl = ProductionGPTOSS()
out = await cl.chat({
"model": "gpt-oss-20b",
"messages": [{"role": "user", "content": "用 50 字介绍黑洞"}]
})
print(out["choices"][0]["message"]["content"])
if __name__ == "__main__":
asyncio.run(main())
tenacity
负责指数退避,aiohttp
负责并发,P99 延迟 1.1 s。
from transformers import BitsAndBytesConfig
bnb = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype="bfloat16",
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4"
)
model = AutoModelForCausalLM.from_pretrained(
"openai/gpt-oss-120b",
quantization_config=bnb,
device_map="auto",
attn_implementation="flash_attention_2"
)
用 HybridInferenceRouter 把 20 B 当缓存、120 B 当兜底:
from hybrid_router import HybridInferenceRouter
router = HybridInferenceRouter(
local_url="http://localhost:11434",
laozhang_key=os.getenv("LZ_KEY"),
local_weight=0.8
)
resp, provider = asyncio.run(router.route_request("写一首十四行诗"))
print("来自", provider, ":", resp)
80 % 流量走本地 20 B,20 % 流量走云端 120 B,成本立省 70 %。
# docker-compose.yml
version: "3.8"
services:
gpt_exporter:
image: prom/gpt-oss-exporter
environment:
- OLLAMA_URL=http://host.docker.internal:11434
ports:
- "9580:9580"
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
打开 http://localhost:3000
,导入 ID 20250 的仪表盘,Token/s、P99、GPU 温度尽收眼底。
症状 | 原因 | 解药 |
---|---|---|
显存 OOM | 没开量化 | INT4 + device_map="auto" |
首帧 5 s | 冷启动 | 预热脚本 + CUDA Graphs |
429 频现 | 并发过高 | 令牌桶限速 + 退避 |
JSON 解析失败 | 返回格式乱 | 加 response_format={"type":"json_object"} |
把本文收藏进浏览器书签,下次老板问你“能不能今天上线 GPT-4 级体验”,你只需 30 秒把脚本甩给他,然后继续摸鱼。