Academic Figure Generator 实时进度指南:SSE 流式推送与异步后台任务实现
【免费下载链接】academic-figure-generatorAI 驱动的学术论文配图生成平台。上传论文 → AI 分析内容生成 Prompt → 一键生成高质量科研配图,还有配套的skill可在主流agent中使用项目地址: https://gitcode.com/gh_mirrors/ac/academic-figure-generator
Academic Figure Generator是一个 AI 驱动的学术论文配图生成平台:上传论文 → AI 分析内容生成 Prompt → 一键生成高质量科研配图。配图生成通常需要几十秒,为了让你在等待时实时看到生成进度,项目用"异步后台任务 + SSE 流式推送"解决了长任务卡住页面、反复刷新页面的体验问题。本文带你快速搞懂这套机制的原理与实现。
为什么实时刷新进度很重要?
科研配图调用外部图像模型,耗时普遍远超普通 HTTP 请求。如果采用"同步等待"的方式,页面会一直转圈,用户不知道后台是在排队、已经开始生成、还是彻底卡死;而传统的"过几秒手动刷新一次"又会造成大量无效请求。
Academic Figure Generator 的方案是前后分离:
- 提交生成请求后立即返回 202 状态码和任务 ID,接口不阻塞;
- 真正的生成工作在异步后台任务中执行,状态持续写入数据库;
- 前端通过SSE(Server-Sent Events,服务器发送事件)打开一条长连接,状态一变,服务端就主动推送,页面即时刷新。
整体流程:提交、生成、推送三步走
🚀 一次完整的配图生成流程如下:
前端提交 Prompt │ POST /prompts/{id}/images/generate ▼ 后端创建 Image 记录(status = pending),立即返回 202 + image_id │ ├──► 异步后台任务:调图像模型 → 状态 generating → completed / failed │ └──► 前端订阅 SSE 流:状态变化时实时推送,页面即时刷新关键设计:接口响应速度与生成耗时彻底解耦,用户点完按钮瞬间就能继续操作,进度条却仍在"自己动"。
异步后台任务实现:不阻塞、独立会话
核心代码位于 images.py,流程拆解:
- 先落库:创建一条
generation_status = "pending"的图片记录并写入数据库,这是后续所有进度查询的依据(模型定义见 image.py); - 秒回响应:接口立刻返回 202 和
image_id,不等待任何生成逻辑; - 后台执行:通过
asyncio.create_task()在事件循环中启动协程(images.py),项目注释里特意标注了"Launch background task (no Celery)"—— 单机场景下不引入 Celery/RabbitMQ,用原生异步任务即可,部署更轻; - 独立数据库会话:后台任务通过工厂新建自己的会话(images.py),不复用请求作用域的 session,避免请求结束后会话失效;
- 线程池执行耗时调用:图像 API 是同步阻塞调用,代码用
run_in_executor把它丢进线程池,不卡住整个事件循环(images.py); - 异常即落库:生成失败时捕获异常,把错误信息写入
generation_error并置为failed,用户端能看到具体原因。
状态机非常简洁:
| 状态 | 含义 |
|---|---|
pending | 已提交,等待后台任务启动 |
generating | 正在调用图像模型 |
completed | 成功,storage_path已写入,可下载 |
failed | 失败,generation_error记录原因 |
💡 除"按 Prompt 生成"外,"直接生成"与"图片编辑"接口(images.py、images.py)也复用同一套后台任务,保证所有长任务行为一致。
SSE 流式推送实现:服务端主动"喊话"
SSE 端点定义在 stream_image_status,前端只需对GET /images/{image_id}/stream发起一次请求,浏览器即可通过标准EventSourceAPI 持续接收事件。实现上有 4 个值得学习的细节:
1️⃣ 独立会话轮询状态
推送器每 2 秒打开一个新会话查询数据库中的最新状态,而不是把状态缓存在内存里——多副本部署时依然准确。
2️⃣ 状态去重推送
用last_status记录上次推送值,只有状态真正变化时才 yield 事件(pending → generating → completed),避免每 2 秒重复推送同一条消息,大幅降低带宽与前端渲染开销。
3️⃣ 结构化事件流
一次连接中会收到三类事件:
| 事件 | 触发时机 | data 内容 |
|---|---|---|
status | 状态每次变化 | id、status、storage_path、耗时 |
done | 到达completed或failed终态 | 最终状态,随后连接关闭 |
error | 图片记录不存在 | 错误说明 |
4️⃣ 自然终止
到达终态后 yielddone并break,生成器结束、连接优雅关闭,前端收到done即可渲染最终图片或展示失败原因,无需再发任何请求。
// 前端消费方式(示意) const es = new EventSource(`/api/v1/images/${id}/stream`); es.addEventListener("status", (e) => updateProgress(JSON.parse(e.data))); es.addEventListener("done", () => es.close());配合前端的请求封装 api.ts 与生成页面 Generate.tsx,用户在界面上看到的就是"提交 → 实时进度 → 图片出现"的流畅体验,全程零手动刷新。
一张图看懂最终效果
经过上面的流水线,AI 会为论文生成论文风格的专业配图,例如信号处理示意图(docs/images/example-signal.png即为平台生成效果的展示图):
关键模块速查表
| 模块 | 路径 | 作用 |
|---|---|---|
| SSE 端点 + 后台任务 | images.py | 202 快速响应、asyncio.create_task、/stream推送 |
| 图片数据模型 | image.py | generation_status等进度字段 |
| 图像生成服务 | image_service.py | 调用外部图像模型 API |
| 本地存储服务 | local_storage_service.py | 生成图片落盘与下载 |
| 前端 API 封装 | api.ts | 统一 baseURL 与超时配置 |
| 生成页 | Generate.tsx | 触发生成并刷新结果 |
总结
Academic Figure Generator 用一套轻量但完整的实时进度方案,证明了长耗时 AI 任务不必依赖重型消息队列:
asyncio.create_task后台任务:提交即返回,生成不阻塞、不占连接;- 数据库状态机:
pending → generating → completed / failed,进度单一可信来源; - SSE 流式推送:状态变化即推送、去重降载、
done事件自然收尾; - 结果:用户获得"零刷新"的实时进度体验,而架构只比"同步等待"多了一个异步任务和一个流式端点。
如果你正在为 AI 绘图、报告导出等长任务设计接口,这套"202 + 后台任务 + SSE"组合拳非常值得直接借鉴。
【免费下载链接】academic-figure-generatorAI 驱动的学术论文配图生成平台。上传论文 → AI 分析内容生成 Prompt → 一键生成高质量科研配图,还有配套的skill可在主流agent中使用项目地址: https://gitcode.com/gh_mirrors/ac/academic-figure-generator
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考