服务端调用模型
服务端调用模型 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
读完本课你能在 Next.js 的 Route Handler 里,用 OpenAI 兼容接口完成一次真实的模型调用:密钥安全存放、错误显式处理、模型标识有据可查。
问题场景
你把调用代码写进了 React 组件,apiKey 就写在变量里,本地跑得好好的。代码推到仓库当晚,密钥被自动化脚本扫走,第二天账单多了几千块。问题不在「调用」本身,在「调用发生在哪」。
核心解释
本站的调用架构(对应 lib/ai/config.ts 与 lib/ai/adapter.ts)分两步。第一步,配置只放服务端环境文件:
# .env.local(在 .gitignore 里,绝不提交)
AI_BASE_URL=https://xxx/v1 # OpenAI 兼容服务地址
AI_API_KEY=sk-xxxxxxxx # 密钥,只存在于服务端进程
AI_MODEL=glm-4.7 # 明确记录所用模型标识
第二步,Route Handler 在服务端读取配置并发起调用:
// app/api/ai/simple/route.ts(教学简化版)
import { getAiConfig } from "@/lib/ai/config";
export async function POST(req: Request) {
const { baseUrl, apiKey, model } = getAiConfig();
const res = await fetch(`${baseUrl.replace(/\/+$/, "")}/chat/completions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`, // 密钥只出现在这一行,永不返回给浏览器
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "用一句话介绍 SSE" }],
}),
});
if (!res.ok) {
return Response.json({ error: `上游返回 ${res.status}` }, { status: 502 });
}
const data = await res.json();
const reply = data.choices?.[0]?.message?.content ?? "";
return Response.json({ reply, model }); // 把模型标识带回,方便排查
}
浏览器只跟自己的 /api/ai/simple 说话,密钥物理上到不了前端。响应形状是 OpenAI 兼容约定:choices[0].message.content 是回答正文。
「必要的请求配置」至少记录三样:model(行为突变时先确认是不是模型换了)、接口地址、是否流式。本站更进一步:每次调用都写一行 ai_call 记录(模型、token 用量、耗时、状态),排查问题时这是唯一的真相来源。
示例拆解
先用 curl 验证通路,再写业务代码——调通接口是最省时间的顺序:
curl -s "$AI_BASE_URL/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AI_API_KEY" \
-d '{"model":"'"$AI_MODEL"'","messages":[{"role":"user","content":"回复两个字:在线"}]}'
关键点:
- 401/403 是密钥问题,429 是频率或额度受限,超时是地址或网络不对——分类看待比笼统「失败」有用(A12 课展开错误分类)。
.env.local改动后必须重启 dev server 才生效,这是「我明明配了」的第一大来源。res.ok必须检查:上游失败时 HTTP 状态不是 200,跳过检查就会在res.json()处炸出一个不知所云的解析错误。
动手任务
- 本机配好
.env.local三项,用 curl 跑通一次调用,确认拿到正文。 - 把教学版路由跑起来,在浏览器 Network 里确认:请求发给你自己的
/api/ai/simple,响应里搜不到任何密钥片段。 - 故意把
AI_API_KEY改错一个字符重启,观察返回的状态码类别,再改回来。
常见错误
- 密钥写进组件或提交进仓库:前端一切代码皆公开。密钥只活在
.env.local和服务端环境里。 - 不检查
res.ok直接解析:上游报错时先炸在 JSON 解析,真实原因被掩盖。 - 不记录模型标识:换了模型或提供方后行为变化,没有记录就无从对证。
- 把
.env.local提交了:它专为本机私密配置设计,务必留在.gitignore;泄露后第一件事是作废密钥。
检查与复盘
自查清单:
- 能说出密钥的完整路径:
.env.local→ 服务端进程 → 上游请求头,任何一环不经过浏览器 - 能默写 OpenAI 兼容调用的三要素:服务地址、
Authorization: Bearer头、messages数组 - 知道去哪里查「上次调用用的什么模型、花了多少 token」
参考资料
- OpenAI 文档:API Reference - Chat ——
/chat/completions的请求与响应形状,兼容接口的事实标准 - Next.js 文档:Route Handlers —— 服务端接口的写法
- MDN:fetch —— 状态码检查与错误处理
- 下一课 A04 讲
messages数组里每个角色该装什么、不该装什么。
读完这一课了?
标记完成后,工作台会安排接下来的学习。