智汇笔记项目实战(三):SSE 流式摘要联调——异步线程池、可取消推送与“伪流式”落地
一、本周任务:把“中台能力”变成“可交互体验”
在前两篇周报中,我已经完成了 AI 中台侧的“输入准备”与“长文处理”基础能力:
- B 站字幕获取与失败降级(无字幕/风控/需登录时回退模拟样例)
- 文本清洗引擎(预编译正则、去时间轴/HTML/口语赘词、标点收敛)
- 语义切片与 Map-Reduce 摘要编排(多块先 Map 摘要,再 Reduce 归并)
但这些能力如果只停留在“后端一次性返回完整字符串”,就很难支撑一个真正好用的笔记工作站:用户会长时间等待、无法中断,也无法做到“边生成边看到”的沉浸式体验。因此第八周我的主线是:
把 AI 摘要能力接入 SSE(Server-Sent Events)长连接,实现流式输出与可取消机制,为前端打字机渲染做接口契约。
这一步属于“工程化交互层”的关键拼图,它不直接提高摘要质量,却决定了系统是否能像 Notion/ChatGPT 那样顺畅交互。
二、选择 SSE:面向长耗时与长文本的最小闭环
大模型摘要属于典型的“长耗时任务”:
- 生成可能持续几十秒;
- 输出经常是几千字甚至更长;
- 中途用户可能想停止或修改输入。
如果用普通 HTTP 请求“等全篇生成完再返回”,那么会出现三个问题:
- 体验差:页面只能转圈,用户看不到进度;
- 失败不可控:网络抖动、网关超时更容易导致整次失败;
- 成本浪费:用户想停止时没办法及时取消,token 与时间都被浪费。
SSE 是一种很适合本项目的折中方案:单向推送、实现简单、浏览器原生支持;配合前端的 ReadableStream 或 EventSource,可做打字机渲染。对我当前角色而言,SSE 更像一个“传输契约”:先把接口形状、事件语义、取消策略定下来,后续即使换成真正的 LLM 流式接口也不会推翻整体结构。
三、本周实现 1:异步线程池
任务书在“高并发与长耗时 AI 请求”部分明确要求后端采用异步非阻塞架构,并建议线程池规模为:
- 核心线程数 20
- 最大线程数 50
这是为了避免 SSE 长连接 + AI 生成把 Tomcat 的请求线程占满,导致其它 API 卡死。
因此本周我在后端新增了专用的 AI 异步线程池(aiTaskExecutor),用于执行摘要与推送任务,使得:
- SSE 连接建立后,真正耗时的工作不占用 Web 请求线程;
- 并发量上来时有上限,避免“无限开线程”引发 OOM;
- 线程名有前缀,便于排查日志与定位性能瓶颈。
这一步虽然看起来“只是配置”,但它决定了系统在中期演示时能不能稳定承受多次摘要触发与多个 SSE 连接。
四、本周实现 2:SSE 流式接口与事件协议(meta / delta / done / error)
为了尽快与前端联调,我新增了一组专门的 SSE Controller:/api/ai/stream/**,核心是一个摘要流式接口:
POST /api/ai/stream/summarize- 请求体:
{"text":"..."}(与之前的纯文本 DTO 一致) - 返回:
SseEmitter长连接
为了让前端实现更清晰,我把推送内容拆成 4 类事件:
- meta:首次返回
streamId用途:前端拿到 streamId 后,可用于显式取消 - delta:持续推送文本片段
- 用途:前端拼接渲染,实现打字机效果
- done:结束标记
- 用途:前端停止渲染、进入“可编辑/可保存”状态
- error:异常信息
- 用途:前端展示错误态与重试按钮
这套协议的好处是:前端不需要理解 Map-Reduce、切片或模型细节,只要按事件语义做 UI 状态机即可。
五、本周实现 3:可取消(中断)机制
“能开始”只是第一步,“能停止”才是一个可用系统的重要细节。本周我同时实现了两种取消方式:
- 前端断开连接取消
- 客户端主动关闭 SSE 连接,后端会在 completion/error 回调中清理任务标记;
- 服务端显式取消接口
POST /api/ai/stream/abort/{streamId}- 后端对该 stream 的取消标志置为 true,推送循环立即停止。
这满足了任务书中“可中断”的工程需求,也能在真实使用中减少无意义 token 消耗(比如用户发现输入粘错了文本,能立刻停止生成)。
六、一个阶段性取舍:“伪流式”依然有价值
目前我这边的 LLM 客户端仍是“非流式调用”(一次请求拿到完整结果)。为了第八周按时交付并完成前端联调,我借鉴了一个工程上常见的过渡方案:
- 先生成完整 Markdown
- 再把 Markdown 按固定粒度切片
- 通过 SSE 逐段推送
这样的“伪流式”不等价于真正的 token-by-token 流式,但它能先解决最关键的工程问题:
- SSE 链路是否通、前端是否能稳定拼接渲染;
- 线程池是否能承载长耗时任务;
- 取消机制是否能正确生效;
- 事件协议是否合理、是否需要扩展(例如 progress、heartbeat)。
等学校下发 API Key 并确认模型网关支持 stream 输出后,我会把“伪流式”的生成部分替换为“真流式”,而 SSE 协议和取消机制可以直接复用,这样迭代成本最低。
七、本周阶段性成果总结
第八周我完成的核心成果可以概括为三点:
- 异步并发基础:按任务书指标提供 AI 专用线程池,避免长耗时任务阻塞 Web 请求线程;
- 流式交互骨架:建立 SSE 长连接接口与事件协议(meta/delta/done/error),为前端打字机渲染提供稳定契约;
- 可取消机制:支持断开即取消与服务端 abort,减少无意义生成与资源浪费。
更多推荐




所有评论(0)