
前面七课让功能「能跑」。上线以后要面对的是另一类问题:一个月花多少钱?用户多了会不会被限流?上游偶尔出错怎么办?Key 会不会泄露?
成本:先算清楚再上线

费用 = 输入 token × 输入单价 + 输出 token × 输出单价。估算一个功能的月成本:
每次调用的平均 token(看 usage) × 每天调用次数 × 30 × 单价每次调用的实际花费在 HiveGPT 的「使用记录」里能看到,先在测试阶段跑几十次,取平均值再估算,比拍脑袋准得多。
省钱的几个方向,按效果排序:
- 控制上下文长度:多轮对话只带最近几轮(A2),RAG 只带最相关的几段(A5)。输入通常是大头。
- 限制输出:设置
max_completion_tokens,提示词里要求「简洁」「不超过 200 字」。 - 缓存:同样的问题(FAQ、固定说明)直接返回上次的结果,不调模型。
- 固定的前缀放前面:system 提示词和固定资料放在消息开头且保持不变,便于上游做提示词缓存。
- 按任务选模型:分类、抽取这类简单任务,不一定要用最强的模型。
错误:哪些该重试
| 状态码 | 含义 | 处理 |
|---|---|---|
| 400 | 请求本身有问题(参数、内容太长) | 不重试,修代码或提示用户 |
| 401 / 403 | Key 无效、停用或没有权限 | 不重试,检查 Key 和分组 |
| 429 | 请求太频繁 | 等一会儿再重试 |
| 余额不足 / 额度用完 | 按量分组余额用完,或 Key 设置的额度到了 | 不重试,充值或调高额度后再试(看返回的 message) |
| 500 / 502 / 503 / 504 | 上游临时故障 | 重试,间隔逐渐拉长 |
| 超时 / 连接断开 | 网络问题 | 重试 |
指数退避重试

每次失败后等待时间翻倍,再加一点随机数,避免大量客户端在同一时刻一起重试:
python
import os, random, time
from openai import OpenAI, APIStatusError, APIConnectionError, APITimeoutError
client = OpenAI(
base_url="https://hivegpt.cn/v1",
api_key=os.environ["HIVEGPT_API_KEY"],
timeout=60, # 单次请求最多等 60 秒
max_retries=0, # 关掉 SDK 自带重试,下面自己控制
)
RETRY_STATUS = {429, 500, 502, 503, 504} # 余额不足这类错误重试也没用,看 e.message 提示用户
def chat(messages, attempts=4):
for i in range(attempts):
try:
return client.chat.completions.create(model="gpt-5.5", messages=messages, max_completion_tokens=800)
except (APIConnectionError, APITimeoutError):
if i == attempts - 1:
raise
except APIStatusError as e:
if e.status_code not in RETRY_STATUS or i == attempts - 1:
raise
time.sleep(min(2 ** i, 20) + random.random()) # 1s、2s、4s… 再加 0–1 秒随机OpenAI SDK 自带重试
OpenAI(max_retries=2) 默认就会对连接错误、429 和 5xx 做退避重试。想要更细的控制(记录日志、区分余额不足)时,才像上面这样自己写。
保护 Key 和你的钱包
- Key 只放在服务端:浏览器、App 安装包里的 Key 一定会被人拿到。网页通过你自己的后端调用模型。
- 一个应用一个 Key:在「API 密钥」页给每个项目单独建 Key,出问题只停这一个;可以给 Key 设置额度上限,超了自动停。
- 给你的用户限流:每个用户每分钟、每天能调多少次,在你的后端控制,防止被人刷接口。
- 限制输入长度:用户发来几万字也照单全收,账单会很难看。
结业项目:网页聊天机器人
把前面学的串起来:一个有流式输出、能多轮对话的网页聊天机器人。结构是浏览器 → 你的后端 → HiveGPT,Key 只在后端。
python
# app.py —— pip install fastapi uvicorn openai
import os
from fastapi import FastAPI
from fastapi.responses import FileResponse, StreamingResponse
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI(base_url="https://hivegpt.cn/v1", api_key=os.environ["HIVEGPT_API_KEY"], timeout=60)
app = FastAPI()
class Chat(BaseModel):
messages: list[dict]
@app.post("/api/chat")
def chat(body: Chat):
history = [m for m in body.messages if m.get("role") in ("user", "assistant")][-10:] # 只带最近 10 条
messages = [{"role": "system", "content": "你是一个友好、简洁的助手。"}] + history
def stream():
resp = client.chat.completions.create(model="gpt-5.5", messages=messages, stream=True, max_completion_tokens=800)
for chunk in resp:
if chunk.choices and chunk.choices[0].delta.content:
yield chunk.choices[0].delta.content
return StreamingResponse(stream(), media_type="text/plain; charset=utf-8")
@app.get("/")
def index():
return FileResponse("index.html")html
<!-- index.html -->
<div id="log"></div>
<form id="f"><input id="q" placeholder="说点什么…" autocomplete="off"><button>发送</button></form>
<script type="module">
const messages = []
const log = document.getElementById('log')
document.getElementById('f').onsubmit = async (e) => {
e.preventDefault()
const q = document.getElementById('q')
messages.push({ role: 'user', content: q.value })
log.insertAdjacentHTML('beforeend', '<p><b>我:</b></p>')
log.lastElementChild.append(q.value)
q.value = ''
const p = document.createElement('p')
log.append(p)
const res = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages }) })
const reader = res.body.getReader()
const decoder = new TextDecoder()
let text = ''
for (;;) {
const { done, value } = await reader.read()
if (done) break
text += decoder.decode(value, { stream: true })
p.textContent = text // 用 textContent,不要把模型输出当 HTML 插入
}
messages.push({ role: 'assistant', content: text })
}
</script>本地运行:export HIVEGPT_API_KEY=sk-...,然后 uvicorn app:app --reload,打开 http://localhost:8000。
在这个基础上,可以把 A5 的 RAG 接进来做成「某某问答机器人」,或者把 A6 的工具加进去。做完以后:
- 把代码推到 GitHub 或 Gitee(不要提交 Key,用
.gitignore排除.env),把仓库链接作为结业项目; - 也可以把后端部署到你的服务器上,提交可访问的网址。
静态网页托管放不了后端
HiveGPT「我的网站」托管的是静态网页(HTML / CSS / JS),没有后端,不能放 Key。可以用它发布项目介绍页或演示截图,聊天功能要放在你自己的后端上。
小结
- 上线前用「使用记录」里的真实数据估算成本;上下文长度和输出长度是最大的两个开关。
- 429 和 5xx 用指数退避重试,400 / 401 不重试;每个请求都要有超时。
- Key 只放后端,一个应用一个 Key,对自己的用户限流。
这是 A 路线的最后一课。完成全部测验和检查点、提交结业项目后,就可以到路线页领取结业证书。