拓冰建站拓冰建站
首页 / 资讯中心 / 正文

43.流式输出SSE是什么聊天应用为什么要实时返回

流式输出 SSE 是什么聊天应用为什么要实时返回码海寻道 · 大模型、智能体与 RAG 工程组件系列第 43 篇大模型生成长答案需要时间。如果接口等到完整文本生成后才一次性返回用户会看到长时间空白。SSEServer-Sent Events允许服务端通过一个长连接持续向浏览器发送事件让答案逐步显示。一、SSE 的基本特点SSE 是基于 HTTP 的单向事件流浏览器建立连接服务端持续推送客户端通过EventSource接收。浏览器 ──请求──→ API 浏览器 ←─事件流─ API它适合模型 Token、任务进度和日志通知等“服务端持续推送、客户端主要接收”的场景。需要客户端频繁向服务端发送消息时应评估 WebSocket 或普通 API。二、事件格式event: token id: 17 data: {text:你好} event: done id: 18 data: {run_id:run-001}事件之间用空行分隔响应类型是text/event-stream。事件可以包含event、data、id和retry等字段。三、FastAPI 最小示例importasyncioimportjsonfromfastapiimportAPIRouterfromfastapi.responsesimportStreamingResponse routerAPIRouter()defsse(event:str,data:dict,event_id:int|NoneNone)-str:lines[fevent:{event}]ifevent_idisnotNone:lines.append(fid:{event_id})lines.append(fdata:{json.dumps(data,ensure_asciiFalse)})return\n.join(lines)\n\nrouter.get(/chat/stream)asyncdefchat_stream():asyncdefgenerate():yieldsse(message_start,{run_id:run-001},1)forindex,tokeninenumerate([你好,,这是,流式回答],start2):yieldsse(token,{text:token},index)awaitasyncio.sleep(0.05)yieldsse(done,{run_id:run-001},6)returnStreamingResponse(generate(),media_typetext/event-stream,headers{Cache-Control:no-cache,Connection:keep-alive},)真实实现还需要接入模型流、鉴权、取消、错误事件和最终结果持久化。四、浏览器端接收constsourcenewEventSource(/api/v1/chat/stream?run_idrun-001)source.addEventListener(token,(event){constpayloadJSON.parse(event.data)appendAssistantText(payload.text)})source.addEventListener(done,(){source.close()markCompleted()})source.onerror(){source.close()loadFinalRunState()}如果需要携带复杂请求体、Authorization Header 或 POST 提交的问题可以先用普通 API 创建run_id再用 SSE GET 订阅这个运行。五、为什么要有 run_id 和 event_idrun_id标识一次问答执行关联用户、会话、模型调用、检索结果和最终答案。event_id标识流中的事件序号。断线重连时可以用Last-Event-ID或自定义游标请求缺失事件避免重复或丢失。不要把“连接存在”当作任务状态。连接可能断开但服务端任务仍在运行。如果需要可靠重连服务端应保存短期事件记录或最终结果并支持Last-Event-ID、since_event_id或run_id查询。事件日志可以过期但最终答案、引用和运行状态应进入持久化存储不能只存在 SSE 连接内存中。六、心跳和断线重连长时间没有 Token 时代理和负载均衡器可能认为连接空闲。服务端可以发送注释心跳: heartbeat前端断线后应关闭旧连接查询 run_id 当前状态根据最后事件 ID 继续订阅或加载最终结果避免重复触发一次模型调用。重连要设置退避和最大次数避免网络故障时所有客户端同时打满接口。心跳只能证明连接仍在不代表模型或任务仍在运行前端恢复后还应查询服务端状态。服务端要限制单个用户、租户和 IP 的长连接数量。七、错误事件和取消event: error data: {code:MODEL_TIMEOUT,retryable:true} event: cancelled data: {run_id:run-001}用户点击停止时前端调用取消接口服务端应取消模型流、工具调用和下游任务并发送最终状态。只关闭浏览器连接不能停止后台成本。八、SSE 与反向代理生产环境要检查代理是否缓存响应是否关闭响应缓冲是否正确传递text/event-stream读取超时是否覆盖模型最长生成时间是否支持负载均衡、连接数限制和客户端断开通知。这些配置必须通过真实代理链路测试不能只在本地直连 FastAPI 时判断 SSE 正常。空闲超时是否足够是否支持 HTTP/2是否正确透传text/event-stream多实例时事件是否能路由到正确任务。多实例服务通常需要 Redis Pub/Sub、消息队列或持久化事件表把后台 Worker 的事件转给持有 SSE 连接的 API 实例。九、不要只返回 Token建议定义事件协议message_start retrieval_started retrieval_completed tool_call token citation usage done error这样前端可以展示“正在检索”“正在调用工具”和引用来源而不是只能显示一段逐字出现的文本。结语SSE 适合把服务端生成过程持续推送到浏览器能够改善大模型应用的等待体验。但可靠的流式系统还必须设计 run_id、事件序号、心跳、重连、取消、最终状态和代理配置。下一篇将把文件上传、任务队列和知识库管理整合起来设计一套完整 API。参考资料MDNUsing server-sent eventsWHATWGServer-sent eventsFastAPI 官方文档Custom Response本文为“码海寻道”原创技术文章。SSE 的代理、浏览器连接和重连行为需要结合实际网络环境测试。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门