Appearance
Server-Sent Events——服务器向客户端单向推送文本事件的 HTTP 流式协议,LLM 逐 token 输出的标准传输方式。
为什么需要 SSE
LLM 生成文本是逐 token 的,如果等全部生成完毕再返回,用户需要等待几十秒。SSE 让服务器每生成一个 token 就立即推送给客户端,实现"打字机"效果。
核心原理
HTTP 响应头:
Content-Type: text/event-stream
Cache-Control: no-cache
SSE 数据格式(每个事件以双换行分隔):
data: {"id":"chatcmpl-xxx","choices":[{"delta":{"content":"你"}}]}\n\n
data: {"id":"chatcmpl-xxx","choices":[{"delta":{"content":"好"}}]}\n\n
data: [DONE]\n\nSSE vs WebSocket:
- SSE 是单向的(服务器 → 客户端),协议简单
- WebSocket 是双向的,LLM 场景不需要双向通信
- SSE 基于 HTTP,任何 HTTP 客户端都支持
在 ds4.c 中的实现
sse_chunk()(ds4_server.c 约 3119 行)每生成一个 token 立即推送 SSE 事件。内部维护 UTF-8 解码状态,处理中文字符跨越多次 recv 的情况,保证每个 chunk 都是合法 UTF-8。
SSE Keepalive
长 prompt 的 prefill 可能持续数十秒,期间 SSE 流没有新数据。ds4_server 在 prefill 期间每 5 秒发送 SSE 注释行 : prefill\n\n 作为心跳。SSE 规范中 : 开头的行是注释,客户端会忽略,但足以保持 TCP 连接活跃,防止代理/负载均衡器超时断开。