一、什么是流式输出?为什么需要它?
传统的API交互是同步阻塞的:客户端发送请求,服务端处理完成后,一次性将完整的结果返回。这对于生成一段较长文本的大语言模型(如MiMo)来说,会造成显著的等待时间(Time to First Token, TTFT)。用户发送一个问题,可能要等上好几秒甚至十几秒,才能看到屏幕上“唰”地一下出现一大段回答,体验并不流畅。
流式输出(Streaming) 则是一种更友好的交互模式。它允许服务端在生成内容的过程中,就持续地、一块一块地将部分结果推送给客户端。对于用户而言,文字会像打字一样逐字或逐句地出现在屏幕上,大大提升了交互的即时感和体验。这对于聊天机器人、实时内容生成等场景至关重要。本质上,流式输出是将一个大的、延迟的请求,拆解成了一系列小的、即时的响应片段。
二、SSE:实现流式输出的轻量级协议
要实现流式输出,我们需要一个能够由服务端向客户端单向持续推送数据的通信机制。虽然 WebSocket 是一个强大的全双工通信协议,但对于服务端主动推送、客户端无需频繁发送数据的场景,它显得有些“重”了。SSE(Server-Sent Events) 协议正是为解决这类问题而设计的。
SSE基于标准的 HTTP/HTTPS 协议。客户端通过普通的HTTP请求连接到服务端,服务端通过设置 Content-Type: text/event-stream 来声明这是一个事件流。此后,服务端就可以持续地向这个保持打开的连接写入格式化的文本数据。SSE协议格式简单,具有自动重连、文本流解析等内置特性,非常适合用于大模型结果的实时推送。
三、SSE协议的消息格式解析
SSE协议的消息格式非常直观,由一系列用 \n\n 分隔的事件(event) 组成。每个事件由多个字段构成,每个字段格式为 字段名: 值\n。我们最常接触的字段有: