3.9 KiB
Generation Job 状态落库决策
这份文档用于回答一个关键技术债问题:DreamWeaver 是否需要为每次 AI 生成单独建立 generation_jobs 表。
当前结论
已新增轻量 generation_jobs 与 generation_job_events 表,但不引入复杂工作流引擎。
原因是当前 MVP 的生成方式仍然以同步请求为主:后端在一次请求中完成主内容保存,再补全封面、绘本插图或语音。用户最关心的是“这个故事现在能不能读、哪些资产可补全”;系统侧则需要有足够的轨迹说明“这次生成做到了哪一步、哪里失败、哪些资产还能重试”。
因此当前采用轻量落库策略:
stories继续承载用户可见结果和当前状态。generation_jobs记录一次生成或资产补全尝试。generation_job_events记录关键步骤事件,例如request_accepted、context_prepared、narrative_generated、story_saved、cover_image_succeeded、storybook_page_image_succeeded、audio_succeeded、provider_call_succeeded、asset_retry_completed。
当前已提供三个查询入口:
GET /api/generations/jobs/{job_id}:查询单次生成/补全任务及其事件流。GET /api/generations/{story_id}/jobs:查询某个故事或绘本的生成与重试历史。GET /api/generations/{story_id}/provider-stats:按故事聚合 Provider 调用成功率、平均耗时、预估成本和 adapter 明细。GET /api/generations/provider-analytics:按当前用户聚合跨故事 Provider 调用、任务数、故事数、成功率、平均耗时和预估成本。
job 响应会返回 progress_percent、progress_label 和 is_terminal,用户端与管理端已经消费这些查询入口,在故事详情页和绘本阅读页展示最近任务、任务历史、事件时间线、进度条和 Provider 聚合指标;当任务未终止时,前端会自动轮询,为后台 worker 进度流预留体验形态。
现有状态模型
当前 stories 表已承载演示所需状态:
generation_status: 主流程状态,例如narrative_ready、partial_ready、assets_generating、completed、degraded_completed、failedtext_status: 主文本或绘本结构状态,当前用于区分主内容是否已经可读image_status: 封面或绘本插图状态audio_status: 语音状态last_error: 最近一次资产失败原因
partial_ready 表示主内容已经可读、但仍有封面、插图或音频可以继续补全;degraded_completed 表示主内容可读但至少一个资产失败。两者的区分能让前端把“正常待补全”和“需要重试失败资源”分开展示。
这些字段足够支撑前端展示、smoke 检查、失败降级、资产重试和生成轨迹解释。
什么时候需要落库 job
如果后续进入真实生产化,需要扩展当前 job/event 模型:
- 生成流程改成真正异步,前端需要轮询后台 worker 的实时进度。
- 单个故事会产生多次生成尝试,需要对比每次任务的 provider 表现、重试原因和资产结果。
- 需要展示比当前事件更细颗粒度的步骤,例如 prompt 构建、provider 选择依据、provider failover 原因、每次调用 token/图片/语音成本。
- 需要按 provider、成本、延迟和失败原因做运营分析。
- 需要断点续跑,避免 Worker 重启后丢失中间状态。
推荐未来扩展
当前已有两层记录,未来可以继续扩展字段和事件颗粒度:
- 将同步生成请求迁移到真正异步 worker 后,继续复用现有 job 查询和前端轮询进度条。
- 将当前跨故事 provider 指标扩展为跨时间窗口、跨用户和失败原因维度的运营分析。
面试表达
我没有一上来引入复杂工作流引擎,而是先用轻量 job/event 表把关键执行轨迹落下来。这样既能回答“生成过程是否可追踪”,又不会为了求职版 MVP 牺牲主链路稳定性。