一次流式循环的可靠性,藏在事件处理与收尾之间
流式请求把一次等待拆成持续到达的事件
聊天窗口里的文字逐步出现,看起来像模型正在打字,实际是客户端不断接收服务器发送的事件。普通请求通常等结果完整后再返回;流式请求则允许程序提前处理已经到达的内容。它主要缩短用户看到首段内容的等待时间,并不保证整个任务更快完成。
一个 OpenAI SDK 流式循环可以理解为四个连续动作:发出请求、等待事件、处理增量、确认结束。SDK 通常负责解析底层传输格式,应用负责决定哪些内容显示给用户,以及遇到异常时采取什么措施。网络数据块、SDK 事件和屏幕上的文字片段,并不是一一对应的。
循环读取的是事件而不是完整的回答句子
建立请求时,程序需要选择支持流式输出的接口并启用流式模式,随后遍历返回的流对象。同步写法会等待下一项,异步写法则允许等待期间执行其他任务。两者的核心思路相同:每收到一个事件,就检查类型,再更新应用状态。
这里最容易犯的错误,是把每个事件都当作可显示的文字。部分事件只携带角色信息、工具调用片段或结束状态,也可能没有正文。Chat Completions 与 Responses 的事件结构不同,不能把一套字段读取方式直接套到另一套接口上。应先确定所用接口,再按对应结构处理。
文本增量只是回答的一小部分,不一定是一句话、一个词,甚至不对应一个完整的显示单位。应用通常一边累积正文,一边更新界面。工具调用的参数则应单独累积,在确认完整并通过校验后再执行,不能因为收到一段参数就立即触发操作。
可靠的收尾必须区分回答结束与连接中断
循环停止不一定意味着回答成功完成。模型可能正常结束,也可能因输出限制而停下;连接还可能因为超时、网络故障或主动取消而中断。应用应结合接口提供的结束信息判断状态,避免把半段回答当作完整结果保存。
异常处理应覆盖整个读取过程,而不只是创建请求的那一刻。发生故障时,保留已收到的文字并标注未完成,通常比直接清空更友好。自动重试也要谨慎:重新发送请求可能再次生成内容并产生费用,直接追加还会让用户看到重复文字。
用户点击停止时,应通过 SDK 支持的机制取消请求或关闭流,并释放相关资源。仅停止刷新界面,不代表后台请求已经终止。用量信息也未必跟随每个文本片段出现;部分接口需要额外请求用量事件,中断后还可能收不到最终统计。
接入中继之后仍需验证事件语义与用量统计
本文由 BestRelay 发布。它以质量为先,将每个请求转发给其中指定的官方模型,不做模型替换,覆盖 Claude、GPT、Gemini、DeepSeek、Kimi、GLM、Qwen、Grok 等系列,并支持 Claude Code、Codex、Gemini CLI 及各类 OpenAI SDK。接口兼容能减少接入改动,但不代表不同模型的事件、工具调用和用量字段完全相同,仍应逐项验证。
BestRelay 按提供方报告的令牌数量按量计费,缓存读取与写入分别计价。因此,界面上的字符数不能直接当作账单依据,本地累积的正文也不能代表全部消耗。会员邀请他人充值可获得推荐佣金,这与流式循环本身的处理逻辑无关。
欢迎创建 BestRelay 账户,试着观察一次完整的流式请求。测试时,不妨分别检查正常结束、空文本事件、主动取消和中途断线;真正可靠的循环,不只是让文字出现,还要让应用明确知道哪些内容已收到、请求是否完成,以及最终用量是否可核对。
想亲自试试文中提到的模型? 注册