Files
Genarrative/docs/experience/RPG_DRAFT_IMAGE_PARALLEL_GENERATION_2026-04-24.md
2026-04-24 22:25:13 +08:00

3.4 KiB

RPG 底稿图片并行生成说明 2026-04-24

背景

RPG 草稿生成进入底稿素材阶段后,角色主形象与场景幕背景图都依赖同一份结构化底稿,但二者之间没有数据依赖。旧流程先生成所有角色主形象,再生成场景背景图,导致用户需要串行等待两类图片任务。

落地约束

  1. 角色主形象与场景背景图必须在 API 编排层并行发起,且类内每个角色、每一幕背景也必须同时调用生图接口,不能只做到“角色大类”和“背景大类”并行。这里的场景背景图指 sceneChapterBlueprints[*].acts[*] 中每一幕的 backgroundImageSrc,不是世界封面图,也不是只按章节或地点生成一张图。
  2. SpacetimeDB reducer 只负责持久化操作进度和底稿写入,不承载外部 LLM / 图片生成调用。
  3. 生图前必须已经有文本设定:角色主形象使用角色对象的 visualDescription;幕背景图使用对应幕的 backgroundPromptText。缺字段时应中断并暴露底稿质量问题,不能退回 descriptionsummary 或通用兜底词直接生图。
  4. 并行分支各自基于同一份底稿副本写入素材字段,完成后只合并背景图生成产物字段,避免覆盖角色图片字段或其他草稿内容。
  5. 单个大类失败仍按原有失败语义终止底稿写入,保留“生成角色主形象失败”和“生成幕背景图失败”的进度提示。

当前实现

  • server-rs/crates/api-server/src/custom_world.rsspawn_custom_world_draft_foundation_job 中使用 tokio::join! 同时执行:
    • generate_draft_foundation_role_visuals
    • generate_draft_foundation_act_backgrounds
  • 角色分支使用 JoinSet 把所有角色主形象任务一次性投递,返回后再按角色位置写入 imageSrcgeneratedVisualAssetId
  • 背景分支使用 JoinSetsceneChapterBlueprints[*].acts[*] 的每一幕背景任务一次性投递,返回后写入 backgroundImageSrcbackgroundAssetIdgeneratedScenePromptgeneratedSceneModel
  • merge_generated_act_backgrounds 只把背景图字段合并回角色分支副本,再进入后续草稿卡编译和 SpacetimeDB 写入。
  • 幕背景 prompt 同时兼容 backgroundPromptTextscenePromptTextvisualPromptTextpromptTextimagePromptTextbackgroundPromptvisualPrompt,避免 LLM 输出字段别名导致整批背景图被误判缺失。
  • 每个角色主形象、每一幕背景图都必须独立自动重试,单项最多尝试 3 次。任一单项超过 3 次仍失败时,后台任务必须把 operation 标记为 failed 并停止写入草稿卡,避免生成“缺主图 / 缺背景图”的可进入世界档案。
  • 中止前必须持久化已经成功生成的部分底稿到会话 draftProfile,不能因为某个角色或某一幕失败而丢掉其它已生成的 imageSrc / generatedVisualAssetId / backgroundImageSrc / backgroundAssetId
  • 前端 CharacterAnimator 对带 generatedVisualAssetId 但尚无 animationMap 的自定义角色,所有状态优先渲染生成主图;只有真正发布了动作集后才按动作帧播放,避免运行或战斗状态回落到模板 sprite。

后续注意

如果后续图片供应商出现强限流,再在网关层做队列或供应商侧限流;不要在 RPG 底稿编排层恢复逐张串行,否则会重新退化成多张图片总耗时累加。