ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

30天从零开始学AI应用开发(Day 12):像产品一样稳:流式输出、报错重试、花钱控制

2026/9/29 10:33:27 拓冰建站 浏览量
30天从零开始学AI应用开发(Day 12):像产品一样稳:流式输出、报错重试、花钱控制 这是系列的第 12 篇。整个系列写给零基础、想入行 AI 的朋友每天一篇30 天后你会做出 3 个能写进简历的项目。这篇解决什么问题昨天加工具那个作业交上来的代码我已经看了功能基本都对。但有个共性问题代码太脆了。举几个真实场景。用户问一句话转圈七八秒什么都不显示以为程序卡死了网络抖一下程序直接崩用户一脸懵跑了几天想看花了多少钱完全不知道。功能能用只是及格能稳稳地交付出去才是合格。今天讲三件事流式输出解决“等太久”、重试机制解决“太脆弱”、成本控制解决“不知道在烧多少钱”。这三件事做完你的程序才像个正经产品。明天开工的项目一会全程用上。一、流式输出让字一个个蹦出来你现在用的写法是等 AI 把整段话想完了再一次性给你。回答长了用户要干等好几秒。看看网页版大模型的体验字是一个个往外蹦的。这不是特效是流式输出streamAI 生成一个字就传一个字。原理很好理解。像点外卖非流式是把整桌菜做好了端上来流式是开放式厨房做一道上一道。后者等待感明显更小。代码只改一个地方加 streamTrueresponseclient.chat.completions.create(modeldeepseek-chat,messages[{role:user,content:讲个笑话}],streamTrue# 关键开启流式)forchunkinresponse:# 一段一段地接收piecechunk.choices[0].delta.contentifpiece:# 有些片段是空的跳过print(piece,end,flushTrue)# end 不换行flush 立刻输出注意几个变化返回值从“一个完整的响应”变成了“一段可以遍历的流”取内容从 message.content 变成了 delta.content。有个坑要提前说开了流式之后你拿不到完整的结果文本了因为它是碎片式给你的。所以要把碎片拼起来full_textforchunkinresponse:piecechunk.choices[0].delta.contentifpiece:full_textpiece# 一边显示一边拼接print(piece,end,flushTrue)# 循环结束后full_text 才是完整回答后面要用就用它二、报错重试别让程序死在网络抖动上调 API 是网络请求网络请求就一定会失败。三类最常见的错误网络抖动、超时一时的问题重试就好限流请求太频繁等一会儿重试余额不足、密钥错误重试一万次也没用第三类要直接告诉用户前两类应该自动重试。这是个通用套路值得记住importtimedefcall_with_retry(messages,max_try3):foriinrange(max_try):try:responseclient.chat.completions.create(modeldeepseek-chat,messagesmessages)returnresponse.choices[0].message.content# 成功就返回exceptExceptionase:print(f第{i1}次失败了{e})ifimax_try-1:time.sleep(2)# 等两秒再试给服务器缓一缓else:return抱歉服务暂时不可用请稍后再试# 三次都不行兜底关键在最后那句兜底程序不能因为一次网络问题就崩给用户看。错误要能被接住并且翻译成人话。三、成本控制知道你花了多少钱Day 6 说过API 按 token 计费。但很多人跑了一个月都不知道自己花了多少直到收到账单。好消息是每次 API 返回里都带着账单信息就藏在响应对象里responseclient.chat.completions.create(modeldeepseek-chat,messages[{role:user,content:你好}])usageresponse.usageprint(输入 token,usage.prompt_tokens)# 你发过去的内容print(输出 token,usage.completion_tokens)# AI 回给你的内容print(总计,usage.total_tokens)三件事顺手就能做第一记日志。把每次调用的 token 数写进文件月底一看就知道花在哪了。第二砍浪费。Day 10 讲的滑动窗口就是最简单的节流手段别把几百轮对话全都发过去。第三主次分明。便宜的模型干粗活分类、提取关键词贵的模型干细活写作、复杂推理。这是行业里的普遍做法成本能差出好几倍。四、把三件事装在一起实际项目里这三件事是叠着用的。给你一个可以复用的骨架importtimedefchat_safe(messages,max_try3):带重试和成本记录的对话函数foriinrange(max_try):try:responseclient.chat.completions.create(modeldeepseek-chat,messagesmessages,streamTrue# 流式输出)full_textforchunkinresponse:piecechunk.choices[0].delta.contentifpiece:print(piece,end,flushTrue)full_textpieceprint()# 结束后换行returnfull_textexceptExceptionase:print(f\n第{i1}次失败{e})ifimax_try-1:time.sleep(2)else:return服务暂时不可用请稍后再试以后写任何 AI 程序直接从这段改能省下很多重复工作。常见报错排查报错一开了 stream 之后取 content 报错或拿到 None。流式要取 delta.content 而不是 message.content并且要判断空值有些片段没有内容。报错二重试了三次还是失败。先看报错原文。如果是余额或密钥问题重试是无效的要直接去控制台处理。报错三流式输出在 VSCode 里看着正常打包成程序就不显示。输出缓冲的问题确认用了 flushTrue。有些环境需要手动刷新缓冲区。报错四response.usage 是 None。开了 stream 之后部分平台的 usage 需要额外设置才会返回。想统计成本又用流式可以自己用字符数粗略估算或者不开流式单独计数。今天的作业把 chat_safe 这段拿去跑打印一句话观察两件事字是不是一个个出来的每次调用用了多少 token。把 token 数字贴到评论区看看大家问同一句话谁的花费高。明天预告Day 13《项目一开工AI 文件整理助手几百个乱文件一键归类》。铺垫了十二天明天正式开始做简历上的第一个项目。上午搭骨架下午就能看到它真的帮你整理文件。我会把完整代码拆成几段讲你跟着敲就行。————————————————*系列目录30天从零开始学AI应用 开发