5.5 KiB
5.5 KiB
RPG 底稿图片并行生成说明 2026-04-24
背景
RPG 草稿生成进入底稿素材阶段后,角色主形象与场景幕背景图都依赖同一份结构化底稿,但二者之间没有数据依赖。旧流程先生成所有角色主形象,再生成场景背景图,导致用户需要串行等待两类图片任务。
落地约束
- 角色主形象与场景背景图必须在 API 编排层并行发起,且类内每个角色、每一幕背景也必须同时调用生图接口,不能只做到“角色大类”和“背景大类”并行。这里的场景背景图指
sceneChapterBlueprints[*].acts[*]中每一幕的backgroundImageSrc,不是世界封面图,也不是只按章节或地点生成一张图。 - SpacetimeDB reducer 只负责持久化操作进度和底稿写入,不承载外部 LLM / 图片生成调用。
- 生图前必须已经有文本设定:角色主形象使用角色对象的
visualDescription;幕背景图使用对应幕的backgroundPromptText。缺字段时应中断并暴露底稿质量问题,不能退回description、summary或通用兜底词直接生图。 - 并行分支各自基于同一份底稿副本写入素材字段,完成后只合并背景图生成产物字段,避免覆盖角色图片字段或其他草稿内容。
- 单个大类失败仍按原有失败语义终止底稿写入,保留“生成角色主形象失败”和“生成幕背景图失败”的进度提示。
当前实现
server-rs/crates/api-server/src/custom_world.rs在spawn_custom_world_draft_foundation_job中使用tokio::join!同时执行:generate_draft_foundation_role_visualsgenerate_draft_foundation_act_backgrounds
- 角色分支使用
JoinSet把所有角色主形象任务一次性投递,返回后再按角色位置写入imageSrc与generatedVisualAssetId。 - 背景分支使用
JoinSet把sceneChapterBlueprints[*].acts[*]的每一幕背景任务一次性投递,返回后写入backgroundImageSrc、backgroundAssetId、generatedScenePrompt、generatedSceneModel。 merge_generated_act_backgrounds只把背景图字段合并回角色分支副本,再进入后续草稿卡编译和 SpacetimeDB 写入。- 幕背景 prompt 同时兼容
backgroundPromptText、scenePromptText、visualPromptText、promptText、imagePromptText、backgroundPrompt、visualPrompt,避免 LLM 输出字段别名导致整批背景图被误判缺失。 - 每个角色主形象、每一幕背景图都必须独立自动重试,单项最多尝试 3 次。幕背景图允许部分成功:只要至少一幕成功,就必须保留已成功写入的
backgroundImageSrc并继续生成草稿卡;全部幕都失败时才把素材阶段标记为“生成幕背景图失败”。 - 图片任务仍然一次性投递,保证角色与幕背景两类任务不回退到串行编排;但真正请求上游生图服务时必须共用并发闸门。并发数由
GENARRATIVE_DRAFT_ASSET_GENERATION_MAX_CONCURRENT_REQUESTS或DRAFT_ASSET_GENERATION_MAX_CONCURRENT_REQUESTS配置,默认 4,避免固定为 2 导致多角色、多幕草稿总耗时过长。 - 幕背景图失败文案必须带第几章、第几幕和幕标题,不能只显示“第1幕 / 第2幕 / 第3幕”,否则多章节同名幕会被用户误认为同一失败项重复上报。
- 中止或部分失败前必须持久化已经成功生成的部分底稿到会话
draftProfile,不能因为某个角色或某一幕失败而丢掉其它已生成的imageSrc / generatedVisualAssetId / backgroundImageSrc / backgroundAssetId。 - 每一幕自动生图必须记录 operation、session、第几章、第几幕、sceneId、sceneName、attempt、elapsedMs 与供应商真实错误,避免再次出现只看到“生成幕背景图失败”但无法定位哪张图、哪次请求、哪个上游原因的问题。
- 前端看到
draft_foundationoperation completed 后,不能只延迟一次就读取resultPreview;SpacetimeDB 写入、API 读模型和前端状态同步之间可能有短暂时差,必须短轮询等待结果页 profile 可用后再自动跳转到草稿页,避免卡在“底稿已整理”。 - 前端
CharacterAnimator对带generatedVisualAssetId但尚无animationMap的自定义角色,所有状态优先渲染生成主图;只有真正发布了动作集后才按动作帧播放,避免运行或战斗状态回落到模板 sprite。
后续注意
如果后续图片供应商出现强限流,再在网关层做队列或供应商侧限流;不要在 RPG 底稿编排层恢复逐张串行,否则会重新退化成多张图片总耗时累加。
2026-04-25 补充:开局场景也必须逐幕生成背景图
本次排查发现旧草稿合成只从 landmarks 编译 sceneChapterBlueprints,导致 camp 开局场景只有 camp.imageSrc,没有进入 sceneChapterBlueprints[*].acts[*] 的幕背景生成队列。后续实现必须遵守:
camp开局场景必须作为sceneChapterBlueprints[0]写入,sceneId默认使用camp.id,缺失时使用camp-1。camp.actBackgroundPromptTexts必须包含 3 条逐幕画面描述,并和普通场景一样生成acts[*].backgroundImageSrc。- 结果页场景目录可用场景图兜底展示旧草稿的幕缩略图,但新草稿不能只依赖兜底,必须让开局场景真实进入幕背景图生成链路。
- 手动同步场景资产时,必须同时更新
sceneChapterBlueprints与兼容字段sceneChapters,当前主链以sceneChapterBlueprints为准。