Skip to main content

SSE 流式对话

MimirQ 的对话接口支持 Server-Sent Events(SSE)流式输出,实现逐字输出的交互体验。

基本概念

SSE(Server-Sent Events)是基于 HTTP 的单向流式协议,服务端通过 text/event-stream 格式向客户端推送事件。

curl 示例

curl -N "$BASE_URL/api/v1/chat/completions" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "什么是 RAG?"}],
"dataset_ids": ["'"$DATASET_ID"'"],
"stream": true
}'

-N 参数禁用 curl 的输出缓冲,以便实时看到 chunk。

客户端实现

JavaScript EventSource

const response = await fetch(`${BASE_URL}/api/v1/chat/completions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messages: [{ role: 'user', content: query }],
dataset_ids: [datasetId],
stream: true,
}),
signal: abortController.signal, // 支持取消
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
// 解析 SSE data 行
}
AbortController

必须实现 AbortController 取消机制。用户切换页面或取消发送时,及时关闭连接,避免幽灵流式占用服务端资源。

重连策略

策略说明
自动重连记录 last event id(如服务端支持),重连时发送 Last-Event-ID
新建会话服务端不支持断点续传时,创建新对话并重新发送
退避间隔首次 1s,逐步增加到 30s,避免重连风暴

代理层配置

必须禁用缓冲

反向代理如果启用了响应缓冲,会导致所有 chunk 在流式结束后才一次性发送到客户端,表现为"半天不出字,然后一次全出来"。

Nginx 配置

location /api/v1/chat/ {
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
}

常见代理配置要点

代理关键配置
Nginxproxy_buffering off
CloudFlare禁用 Auto Minify、启用 HTTP/2
AWS ALB默认支持 SSE,注意超时设置

排障

现象原因解决方案
长时间无 chunk代理缓冲未关闭检查 Nginx/代理配置
断线后收到重复内容重连未处理 offset实现 last event id 或幂等重连
连接被提前关闭代理超时设置过短增加 proxy_read_timeout
页面切换后仍有请求未实现取消机制添加 AbortController

相关链接