从原型到生产:让流式聊天逐字响应、稳定上线
§1 流式回复先改善等待体验
聊天原型通常很简单:用户提问,程序调用模型,最后显示整段答案。真正上线后,几秒钟的空白就可能让用户以为页面卡住。流式聊天把答案拆成连续到达的小片段,让用户边等边读,也能随时停止生成。
这里的令牌是模型处理文本的基本单位,不一定对应一个汉字或一个完整词语。接口传来的片段也不一定只有一个令牌。前端需要做的是按顺序拼接内容,而不是假设每次都会收到完整句子。流式输出主要缩短感知等待,并不保证整段答案生成得更快。
§2 用服务端中转保护聊天密钥
适合新手的结构是:浏览器把问题发给自己的服务端,服务端调用模型,再把收到的片段转给浏览器。不要把模型接口密钥放进网页代码,否则别人可以复制密钥,消耗你的额度。
希望减少接入工作的团队可以考虑 Fluxio。它是以流式响应为优先、按令牌计费的人工智能接口中转服务,一个密钥即可访问多个模型。例如,可以根据任务需要测试 Claude Haiku 4.5 或 Gemini 2.5 Flash,并以实际效果决定选择。
Fluxio 支持 OpenAI 风格的客户端,其接口基础地址为 https://api.fluxioapi.com,这类客户端通常需要加上 /v1。接入时还应核对模型标识、流式参数和返回字段,不能仅凭接口风格相似就省略测试。
§3 让 SSE 数据真正抵达页面
SSE 是服务端向浏览器持续发送事件的一种方式,很适合以服务端输出为主的聊天回复。如果提问请求需要携带正文和身份凭证,可以通过浏览器的流式读取能力处理响应,不必局限于原生事件订阅接口。
服务端应声明正确的事件流响应类型,并按照事件边界输出数据。前端则要保留尚未收完整的数据,避免把一次网络读取误当成一个完整事件。中文字符也可能跨数据块到达,需要使用支持连续解码的文本解码器。
上线环境还有一个常见陷阱:应用已经逐段输出,代理服务器却把内容攒起来再发送。需要检查反向代理、网关和部署平台的缓冲设置与超时限制,并在真实访问链路中验证,而不只是本地测试。
§4 为停止生成和断流设计明确状态
聊天页面至少应区分等待首段内容、正在输出、正常结束、用户停止和请求失败。停止按钮不仅要停止页面更新,还应把取消信号传到服务端,并尽可能终止上游请求,否则后台可能继续生成并计费。
- – 断流时保留已经显示的内容,并明确提示回复尚未完成。
- – 重新生成时创建新的请求记录,避免把两次输出混成同一条答案。
- – 限制重复点击和并发请求,避免用户误触造成多次付费调用。
- – 明确区分正常结束与连接关闭,不把网络中断显示为完整回答。
不要在已经输出内容后盲目自动重试。新的调用可能产生不同答案,也可能重复收费。对于初期产品,提供清楚的手动重试入口,通常比实现复杂的断点续传更稳妥。
§5 把聊天预算和内容安全一起上线
流式显示不会消除模型调用成本。历史消息越长,重复发送的输入就可能越多。应为单次输出长度、会话上下文和用户使用额度设置上限,并以接口最终返回的用量信息核算,而不是按页面显示的字数估算费用。
内容安全同样需要提前设计。流式内容一旦展示,就无法真正收回用户已经看到的信息。敏感场景可以先检查输入,再按业务风险选择分段审核或完整审核后展示。渲染模型输出时,也不要把生成内容直接当成可信的网页代码。
§6 用真实网络完成上线验收
上线前,应模拟弱网、长回复、用户离开页面、额度耗尽和上游报错。重点记录首段内容到达时间、完整回复耗时、断流比例和每次会话成本。日志尽量使用请求编号关联问题,避免默认保存完整聊天内容和敏感凭证。
先向少量用户开放,再逐步增加流量;同时准备关闭流式功能或暂时停用服务的开关。可靠的实时聊天不只是文字不断出现,还包括故障时说清发生了什么,以及用户接下来能做什么。
注册 Fluxio,开始构建流式聊天。