Files
dreamweaver/docs/technical/generation-job-state.md

69 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Generation Job 状态落库决策
这份文档用于回答一个关键技术债问题DreamWeaver 是否需要为每次 AI 生成单独建立 `generation_jobs` 表。
## 当前结论
已新增轻量 `generation_jobs``generation_job_events` 表,但不引入复杂工作流引擎。
原因是当前 MVP 已经进入“请求接收与后台执行分离”的阶段:`POST /api/generations` 先接受请求并返回 `generation_job_id`,再由 Celery worker 完成主内容保存和后续资产补全。用户最关心的是“这个故事现在能不能读、任务跑到哪一步、哪些资产可补全”;系统侧则需要有足够的轨迹说明“这次生成做到了哪一步、哪里失败、是否被取消、哪些资产还能重试”。
因此当前采用轻量落库策略:
- `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 调用、任务数、故事数、成功率、平均耗时和预估成本,并支持 `days` / `capability` 筛选。
- `GET /api/generations/ops-summary`:按当前用户聚合最近任务健康度,包括运行中数量、超时阈值、卡住任务数和最近失败摘要。
job 响应会返回 `progress_percent``progress_label``is_terminal`,用户端与管理端已经消费这些查询入口,在故事详情页和绘本阅读页展示最近任务、任务历史、事件时间线、进度条和 Provider 聚合指标;当任务未终止时,前端会自动轮询,为后台 worker 进度流预留体验形态。当前 analytics 还会聚合失败原因便于快速解释“最近为什么失败”ops summary 会额外把“哪些任务卡住了、最近哪些任务失败了”压缩成故事库首页能直接看的摘要。
## 现有状态模型
当前 `stories` 表已承载演示所需状态:
- `generation_status`: 主流程状态,例如 `narrative_ready``partial_ready``assets_generating``completed``degraded_completed``failed`
- `text_status`: 主文本或绘本结构状态,当前用于区分主内容是否已经可读
- `image_status`: 封面或绘本插图状态
- `audio_status`: 语音状态
- `last_error`: 最近一次资产失败原因
`partial_ready` 表示主内容已经可读、但仍有封面、插图或音频可以继续补全;`degraded_completed` 表示主内容可读但至少一个资产失败。两者的区分能让前端把“正常待补全”和“需要重试失败资源”分开展示。
这些字段足够支撑前端展示、smoke 检查、失败降级、资产重试和生成轨迹解释。
## 当前维护策略
- 音频缓存由 `STORY_AUDIO_CACHE_TTL_DAYS` 控制过期时间Celery beat 会每日清理。
- 生成任务由 `GENERATION_JOB_STALE_MINUTES` 控制卡住阈值Celery beat 会每 30 分钟扫描一次,将超时运行中的任务标记为 `generation_stale_failed`
- 当某个故事已经有运行中的 job 时,封面补全、音频生成和统一资产重试会直接拒绝重复请求,避免用户连点造成重复成本。
- 统一生成请求已由 Celery worker 执行,前端会先拿到 `generation_job_id`,再轮询 job 详情直到主记录落库或任务终止。
- 当前已支持首版任务控制:队列中的任务可直接取消,运行中的任务可在安全检查点取消,失败或已取消任务可重新排队。
## 为什么当前仍然需要扩展 job 模型
虽然 worker 化已经完成,但如果继续进入真实生产化,仍然需要扩展当前 job/event 模型:
- 单个故事会产生多次生成尝试,需要对比每次任务的 provider 表现、取消原因、重试原因和资产结果。
- 需要展示比当前事件更细颗粒度的步骤,例如 prompt 构建、provider 选择依据、provider failover 原因、每次调用 token/图片/语音成本。
- 需要按 provider、成本、延迟和失败原因做运营分析。
- 需要继续扩展取消与重试队列的颗粒度,例如更细的中断点、任务依赖和断点续跑策略。
- 需要断点续跑,避免 Worker 重启后丢失中间状态。
## 推荐未来扩展
当前已有两层记录,未来可以继续扩展字段和事件颗粒度:
- 继续复用现有 job 查询和前端轮询进度条,为取消请求、重新排队和长任务通知提供统一入口。
- 将当前跨故事 provider 指标扩展为跨用户、跨环境和更细颗粒度的失败原因维度分析。
## 面试表达
我没有一上来引入复杂工作流引擎,而是先用轻量 job/event 表把关键执行轨迹落下来。这样既能回答“生成过程是否可追踪”,又不会为了求职版 MVP 牺牲主链路稳定性。