第32期 | OpenAI API接入实战 今天你将学会从零搭建 OpenAI API 调用环境SDK 安装 Key 管理实现完整的后端代理接口非流式 流式两种模式射装可复用的 API 调用层——不是写一次就丢的临时代码处理所有常见错误网络超时、token 超限、格式异常、rate limit 核心知识从零开始环境搭建Step 1注册 OpenAI API访问 https://platform.openai.com/signup 注册账号进入 https://platform.openai.com/api-keys 创建 API Key复制 Key存到环境变量绝不写进代码Step 2环境变量管理# .env.local前端项目Next.js 会自动加载OPENAI_API_KEYsk-xxxxxxxxxxxx# .env后端项目Node.js 用 dotenv 加载OPENAI_API_KEYsk-xxxxxxxxxxxx⚠️.env文件绝不提交到 Git——在.gitignore中加上.env*。Step 3安装 SDK# 前端项目Next.jspnpmaddopenai# 纯后端项目Expressnpminstallopenai dotenv为什么用官方 SDK 而不是直接 fetch方式优点缺点直接 fetch最简单几行代码要自己处理认证、超时、重试、类型openai SDK类型完整、自动重试、流式支持多一个依赖生产环境用 SDK——它帮你处理了 90% 的边界情况。后端代理完整实现非流式接口简单场景// app/api/ai/completion/route.ts (Next.js App Router)importOpenAIfromopenai;import{NextRequest,NextResponse}fromnext/server;constopenainewOpenAI({apiKey:process.env.OPENAI_API_KEY,// 从环境变量读取});exportasyncfunctionPOST(req:NextRequest){try{const{prompt,systemPrompt}awaitreq.json();// 参数校验if(!prompt||prompt.trim().length0){returnNextResponse.json({error:Prompt 不能为空},{status:400});}if(prompt.length4000){returnNextResponse.json({error:Prompt 太长请缩减到 4000 字以内},{status:400});}constcompletionawaitopenai.chat.completions.create({model:gpt-4o-mini,// 用 mini 版降低成本messages:[{role:system,content:systemPrompt||你是一个技术助手。},{role:user,content:prompt},],temperature:0.7,// 0-2越高越随机技术回答建议 0.3-0.7max_tokens:2000,// 控制成本});returnNextResponse.json({content:completion.choices[0].message.content,usage:completion.usage,// token 使用量方便监控成本});}catch(error){// 统一错误处理if(errorinstanceofOpenAI.APIError){returnNextResponse.json({error:API Error:${error.message},code:error.code},{status:error.status||500});}returnNextResponse.json({error:Internal server error},{status:500});}}流式接口聊天场景// app/api/ai/chat/route.tsimportOpenAIfromopenai;import{NextRequest}fromnext/server;constopenainewOpenAI({apiKey:process.env.OPENAI_API_KEY,});exportasyncfunctionPOST(req:NextRequest){const{messages,systemPrompt}awaitreq.json();// 流式响应必须用 StreamTextResponse 或手动设置 SSE headersconststreamawaitopenai.chat.completions.create({model:gpt-4o-mini,messages:[{role:system,content:systemPrompt||你是一个技术助手。},...messages,// 多轮对话传入完整消息历史],stream:true,// ← 开启流式temperature:0.7,});// 创建 SSE 流式响应constencodernewTextEncoder();constreadableStreamnewReadableStream({asyncstart(controller){try{forawait(constchunkofstream){constcontentchunk.choices[0]?.delta?.content||;if(content){// SSE 格式data: {json}\n\ncontroller.enqueue(encoder.encode(data:${JSON.stringify({content})}\n\n));}}// 流结束标记controller.enqueue(encoder.encode(data: [DONE]\n\n));controller.close();}catch(error){controller.error(error);}},});returnnewResponse(readableStream,{headers:{Content-Type:text/event-stream,Cache-Control:no-cache,Connection:keep-alive,},});}前端调用层封装可复用的 API 客户端不要在每个组件里直接 fetch——封装一个统一的 API 客户端处理认证、重试、错误。// lib/ai-client.tsinterfaceCompletionRequest{prompt:string;systemPrompt?:string;}interfaceCompletionResponse{content:string;usage?:{prompt_tokens:number;completion_tokens:number;total_tokens:number};}interfaceChatRequest{messages:{role:user|assistant|system;content:string}[];systemPrompt?:string;}classAIClient{privatebaseUrl:string;constructor(baseUrl/api/ai){this.baseUrlbaseUrl;}// 非流式调用asynccompletion(req:CompletionRequest):PromiseCompletionResponse{constresponseawaitthis.fetchWithRetry(${this.baseUrl}/completion,{method:POST,headers:{Content-Type:application/json},body:JSON.stringify(req),});if(!response.ok){consterrorawaitresponse.json();thrownewAIError(error.error,response.status,error.code);}returnresponse.json();}// 流式调用asyncchatStream(req:ChatRequest):PromiseReadableStreamstring{constresponseawaitthis.fetchWithRetry(${this.baseUrl}/chat,{method:POST,headers:{Content-Type:application/json},body:JSON.stringify(req),});if(!response.ok){consterrorawaitresponse.json();thrownewAIError(error.error,response.status,error.code);}returnthis.parseSSEStream(response.body!);}// SSE 流解析privateparseSSEStream(rawStream:ReadableStreamUint8Array):ReadableStreamstring{constdecodernewTextDecoder();letbuffer;returnnewReadableStream({asyncstart(controller){constreaderrawStream.getReader();try{while(true){const{done,value}awaitreader.read();if(done){controller.close();break;}bufferdecoder.decode(value,{stream:true});constlinesbuffer.split(\n);bufferlines.pop()||;for(constlineoflines){if(line.startsWith(data: )){constdataline.slice(6);if(data[DONE]){controller.close();return;}try{constparsedJSON.parse(data);if(parsed.content){controller.enqueue(parsed.content);}}catch{// 忽略无法解析的行}}}}}catch(error){controller.error(error);}},});}// 带重试的 fetchprivateasyncfetchWithRetry(url:string,options:RequestInit,maxRetries3):PromiseResponse{for(letattempt0;attemptmaxRetries;attempt){try{constresponseawaitfetch(url,options);// Rate limit — 等待后重试if(response.status429){constretryAfterparseInt(response.headers.get(retry-after)||5);awaitnewPromise(resolvesetTimeout(resolve,retryAfter*1000));continue;}returnresponse;}catch(error){if(attemptmaxRetries-1)throwerror;awaitnewPromise(resolvesetTimeout(resolve,1000*(attempt1)));}}thrownewAIError(Max retries exceeded,500);}}// 自定义错误类classAIErrorextendsError{status:number;code?:string;constructor(message:string,status:number,code?:string){super(message);this.statusstatus;this.codecode;}}exportconstaiClientnewAIClient();export{AIError};成本控制你必须知道的事OpenAI API 按 token 计费。不了解成本模型你的应用可能一个月烧掉几千块。GPT 模型定价2026年参考模型输入价格输出价格适用场景gpt-4o-mini$0.15/1M tokens$0.60/1M tokens聊天、摘要、分类gpt-4o$2.50/1M tokens$10/1M tokens复杂推理、代码生成gpt-4-turbo$10/1M tokens$30/1M tokens最复杂任务token 是什么大约 1 个英文单词 1 token1 个中文字 ≈ 2 tokens。一篇 500 字的中文文章约 1000 tokens。成本控制策略策略做法节省效果模型降级日常用 gpt-4o-mini复杂任务才用 gpt-4o80% 成本节省max_tokens 控制设 max_tokens500 防止 AI 写太长50% 输出成本缓存相似问题相同/相似问题缓存答案不重复调用30-50% 节省压缩 promptsystem prompt 精简不要写长篇大论20% 输入成本批量请求需要多个结果时用 batch API50% 成本节省错误处理完整的错误类型覆盖// lib/ai-errors.tsexportfunctionhandleAIError(error:unknown):{message:string;action:string}{if(errorinstanceofAIError){switch(error.status){case401:return{message:API Key 无效,action:检查环境变量中的 OPENAI_API_KEY};case429:return{message:请求过多请稍后再试,action:等待后重试或升级 API 限额};case500:return{message:OpenAI 服务暂时不可用,action:稍后重试};case400:if(error.codecontext_length_exceeded){return{message:输入内容太长,action:缩减 prompt 长度或切换到更大模型};}return{message:请求格式错误,action:检查请求参数};default:return{message:未知错误:${error.message},action:联系管理员};}}if(errorinstanceofTypeErrorerror.message.includes(fetch)){return{message:网络连接失败,action:检查网络连接};}return{message:未知错误,action:请稍后重试};}常见误区误区1直接从前端调用 OpenAI APIAPI Key 暴露在前端 任何人都能盗用。必须后端代理。误区2不用 SDK自己拼 HTTP 请求SDK 帮你处理了类型、重试、流式解析。自己拼 HTTP 请求需要处理大量边界情况容易出错。误区3不做成本控制一个用户连续聊 30 分钟可能消耗 10 万 tokens $0.06gpt-4o-mini。如果 1000 个用户每天聊 30 分钟 $60/天 $1800/月。必须设限。 AI协作实战实战场景封装完整的 AI 调用层我给 AI 的 promptlib/ai-client.ts 帮我优化这个 AI 调用层添加以下功能 1. 请求超时处理30秒非流式流式不设超时 2. Token 使用量追踪每次调用记录 usage 3. 请求取消AbortController 支持 4. 流式响应的中断处理用户手动停止生成 遵循项目 .cursorrules 规范。AI 补充的关键代码// 超时处理privateasyncfetchWithTimeout(url:string,options:RequestInit,timeout30000):PromiseResponse{constcontrollernewAbortController();consttimeoutIdsetTimeout(()controller.abort(),timeout);try{constresponseawaitfetch(url,{...options,signal:controller.signal,});clearTimeout(timeoutId);returnresponse;}catch(error){clearTimeout(timeoutId);if(errorinstanceofDOMExceptionerror.nameAbortError){thrownewAIError(Request timeout,408);}throwerror;}}// Token 使用量追踪interfaceTokenUsage{totalRequests:number;totalTokens:number;totalCost:number;lastRequestAt:string;}constusageTracker{data:{totalRequests:0,totalTokens:0,totalCost:0,lastRequestAt:}asTokenUsage,track(usage:{prompt_tokens:number;completion_tokens:number;total_tokens:number}){this.data.totalRequests;this.data.totalTokensusage.total_tokens;// gpt-4o-mini 成本估算this.data.totalCost(usage.prompt_tokens*0.00015usage.completion_tokens*0.0006)/1000;this.data.lastRequestAtnewDate().toISOString();// 持久化到 localStoragelocalStorage.setItem(ai_usage,JSON.stringify(this.data));},getReport():TokenUsage{returnthis.data;},};我的审查✅ 超时处理合理——非流式 30s流式不限✅ Token 追踪实用——方便监控成本❌ 成本估算硬编码了 gpt-4o-mini 的价格——应该做成可配置的因为可能切换模型✅ AbortController 支持完整学到了什么AI 帮你补齐了你自己不容易想到的功能超时、取消、追踪。但模型价格硬编码需要你根据实际使用的模型来调整。 动手练习练习1简单搭建后端代理接口用 Next.js API Routes 或 Express 实现一个最简单的/api/ai/completion接口接收 prompt 参数调用 OpenAI API返回结果API Key 存在环境变量中练习2中等封装完整的 AI 客户端根据本期的AIClient代码实现一个完整的前端调用层包含非流式 流式两种模式重试机制最多 3 次错误处理覆盖 4 种常见错误Token 使用量追踪练习3挑战实现流式聊天接口 前端渲染完整实现后端 SSE 流式 前端逐字渲染后端流式转发 OpenAI 响应前端ReadableStream 读取 逐字追加到 UI支持中断用户点击停止按钮中止流式传输显示 token 使用量统计 本期要点API Key 安全环境变量存储后端代理转发绝不暴露在前端代码官方 SDK 自己拼 HTTP类型完整、自动重试、流式支持省大量边界处理流式响应实现SSE 格式 ReadableStream 解析 逐 token 推送到前端成本控制模型降级gpt-4o-mini 日常用 max_tokens 限制 缓存 token 追踪错误处理全覆盖401(Key无效) 429(限流) 500(服务不可用) context_length_exceeded(太长) 网络超时 下期预告下一期我们进入聊天界面开发——消息列表、流式打字效果、Markdown 渲染。你将用 shadcn/ui react-markdown 实现一个完整的 ChatGPT 风格聊天界面。如果你没有苹果电脑需要上传ios到APPStore可以访问以下网站iPA上传工具 - IPA解析与AppStore提交