44import torch
55
66from ...configuration_utils import FrozenDict
7- from ...models .autoencoders .autoencoder_kl_wan import AutoencoderKLWan
87from ...models .transformers .transformer_cosmos3 import Cosmos3OmniTransformer
98from ...pipelines .cosmos .pipeline_cosmos3_omni import _EMBODIMENT_TO_DOMAIN_ID , CosmosActionCondition
109from ...schedulers import UniPCMultistepScheduler
@@ -1129,113 +1128,65 @@ class Cosmos3TransferPrepareLatentsStep(ModularPipelineBlocks):
11291128 @property
11301129 def description (self ) -> str :
11311130 return (
1132- "Per-chunk transfer latent prep: slice + pad the chunk's control maps, seed the target's conditioning "
1133- "frames (first chunk from the input video, later chunks from the previous chunk's tail), encode the "
1134- "controls as clean latents and build the noisy target latents, velocity mask and condition latents ."
1131+ "Per-chunk transfer latent prep: takes the clean target latents encoded by "
1132+ "Cosmos3TransferChunkVaeEncoderStep and builds the noisy target latents, velocity mask, condition latents "
1133+ "and conditioned-frame indexes for this chunk ."
11351134 )
11361135
11371136 @property
11381137 def expected_components (self ) -> list [ComponentSpec ]:
1139- return [
1140- ComponentSpec ("transformer" , Cosmos3OmniTransformer ),
1141- ComponentSpec ("vae" , AutoencoderKLWan ),
1142- ComponentSpec (
1143- "video_processor" ,
1144- VideoProcessor ,
1145- config = FrozenDict ({"vae_scale_factor" : 16 , "resample" : "bilinear" }),
1146- default_creation_method = "from_config" ,
1147- ),
1148- ]
1138+ return [ComponentSpec ("transformer" , Cosmos3OmniTransformer )]
11491139
11501140 @property
11511141 def inputs (self ) -> list [InputParam ]:
11521142 return [
1153- # Loop carry (set by the chunk-loop wrapper):
1154- InputParam (name = "chunk_id" , type_hint = int , default = 0 ),
1155- InputParam (name = "previous_output" , default = None ),
1156- # Setup artifacts the loop can't cheaply re-derive (preprocessed controls + chunk geometry):
1157- InputParam (name = "control_frames" , required = True ),
1158- InputParam (name = "chunk_frames" , required = True ),
1159- InputParam (name = "total_frames" , required = True ),
1160- InputParam (name = "stride" , required = True ),
1161- # User inputs (mirrors how the other prepare-latents steps declare height/width/generator/etc.):
1162- InputParam (name = "height" , required = True ),
1163- InputParam (name = "width" , required = True ),
1164- InputParam (name = "video" , default = None ),
1165- InputParam (name = "num_first_chunk_conditional_frames" , type_hint = int , default = 0 ),
1166- InputParam (name = "num_conditional_frames" , type_hint = int , default = 1 ),
1167- InputParam (name = "generator" , default = None ),
1143+ InputParam (
1144+ name = "x0_tokens_vision" ,
1145+ type_hint = torch .Tensor ,
1146+ required = True ,
1147+ description = "Clean target vision latents encoded from the seeded target frames." ,
1148+ ),
1149+ InputParam (
1150+ name = "current_conditional_frames" ,
1151+ type_hint = int ,
1152+ required = True ,
1153+ description = "Number of pixel frames used to seed this chunk's target." ,
1154+ ),
1155+ InputParam .template ("generator" ),
11681156 ]
11691157
11701158 @property
11711159 def intermediate_outputs (self ) -> list [OutputParam ]:
11721160 return [
1173- OutputParam ("latents" ),
1174- OutputParam ("control_latents" ),
1175- OutputParam ("velocity_mask" ),
1176- OutputParam ("condition_latents" ),
1177- OutputParam ("target_condition_indexes" ),
1178- OutputParam ("current_conditional_frames" ),
1161+ OutputParam ("latents" , type_hint = torch .Tensor , description = "Noisy target latents for this chunk." ),
1162+ OutputParam (
1163+ "velocity_mask" ,
1164+ type_hint = torch .Tensor ,
1165+ description = "Mask that zeroes the velocity on conditioned (clean) latent frames." ,
1166+ ),
1167+ OutputParam (
1168+ "condition_latents" ,
1169+ type_hint = torch .Tensor ,
1170+ description = "Clean target latents on the conditioned frames (the autoregressive seed)." ,
1171+ ),
1172+ OutputParam (
1173+ "target_condition_indexes" ,
1174+ type_hint = list [int ],
1175+ description = "Latent-frame indexes fixed by the chunk's conditioning." ,
1176+ ),
11791177 ]
11801178
11811179 @torch .no_grad ()
11821180 def __call__ (self , components : Cosmos3OmniModularPipeline , state : PipelineState ) -> PipelineState :
11831181 block_state = self .get_block_state (state )
11841182 device = components ._execution_device
11851183 dtype = components .transformer .dtype
1186-
1187- chunk_id = block_state .chunk_id
1188- chunk_frames = block_state .chunk_frames
1189- height = block_state .height
1190- width = block_state .width
11911184 tcf = components .vae_scale_factor_temporal
11921185
1193- # Slice this chunk's window out of the (padded) control maps and reflect-pad it up to a full chunk (repeat the
1194- # last frame once too short to keep reflecting). control_frames is already in canonical hint order.
1195- start_frame = chunk_id * block_state .stride
1196- end_frame = min (start_frame + chunk_frames , block_state .total_frames )
1197- chunk_controls = []
1198- for frames in block_state .control_frames .values ():
1199- frames = frames [:, :, start_frame :end_frame ]
1200- while frames .shape [2 ] < chunk_frames :
1201- pad_len = min (frames .shape [2 ] - 1 , chunk_frames - frames .shape [2 ])
1202- if pad_len <= 0 :
1203- pad_frame = frames [:, :, - 1 :].repeat (1 , 1 , chunk_frames - frames .shape [2 ], 1 , 1 )
1204- frames = torch .cat ([frames , pad_frame ], dim = 2 )
1205- break
1206- frames = torch .cat ([frames , frames .flip (dims = [2 ])[:, :, :pad_len ]], dim = 2 )
1207- chunk_controls .append (frames )
1208-
1209- # Seed the target with conditioning frames (first chunk from the input video, later chunks from the
1210- # previous chunk's tail), repeat-padding the remaining frames so the whole clip is well-defined.
1211- target = torch .zeros (1 , 3 , chunk_frames , height , width , device = device , dtype = dtype )
1212- current_conditional_frames = 0
1213- if chunk_id == 0 and block_state .num_first_chunk_conditional_frames > 0 and block_state .video is not None :
1214- input_frames = components .video_processor .preprocess_video (
1215- block_state .video , height = height , width = width
1216- ).to (device = device , dtype = dtype )
1217- current_conditional_frames = min (
1218- block_state .num_first_chunk_conditional_frames , input_frames .shape [2 ], chunk_frames
1219- )
1220- if current_conditional_frames > 0 :
1221- target [:, :, :current_conditional_frames ] = input_frames [:, :, :current_conditional_frames ]
1222- elif chunk_id > 0 and block_state .previous_output is not None :
1223- current_conditional_frames = min (
1224- block_state .num_conditional_frames , block_state .previous_output .shape [2 ], chunk_frames
1225- )
1226- if current_conditional_frames > 0 :
1227- target [:, :, :current_conditional_frames ] = block_state .previous_output [
1228- :, :, - current_conditional_frames :
1229- ].to (device = device , dtype = dtype )
1230- if 0 < current_conditional_frames < chunk_frames :
1231- fill = target [:, :, current_conditional_frames - 1 : current_conditional_frames ]
1232- target [:, :, current_conditional_frames :] = fill .expand (
1233- - 1 , - 1 , chunk_frames - current_conditional_frames , - 1 , - 1
1234- )
1186+ target_x0 = block_state .x0_tokens_vision .to (device = device )
1187+ current_conditional_frames = block_state .current_conditional_frames
12351188
1236- # Encode controls as clean latents and build the noisy target latents + conditioning mask.
1237- block_state .control_latents = [components ._encode_video (ctrl ).contiguous ().float () for ctrl in chunk_controls ]
1238- target_x0 = components ._encode_video (target ).contiguous ().float ()
1189+ # Build the noisy target latents + conditioning mask from the clean target latents.
12391190 latent_t = target_x0 .shape [2 ]
12401191 condition_mask = torch .zeros ((latent_t , 1 , 1 ), device = device , dtype = dtype )
12411192 latent_condition_frames = 0
@@ -1247,7 +1198,6 @@ def __call__(self, components: Cosmos3OmniModularPipeline, state: PipelineState)
12471198 block_state .velocity_mask = 1.0 - condition_mask
12481199 block_state .condition_latents = condition_mask * target_x0
12491200 block_state .target_condition_indexes = list (range (latent_condition_frames ))
1250- block_state .current_conditional_frames = current_conditional_frames
12511201
12521202 self .set_block_state (state , block_state )
12531203 return components , state
@@ -1266,22 +1216,60 @@ def description(self) -> str:
12661216 @property
12671217 def inputs (self ) -> list [InputParam ]:
12681218 return [
1269- InputParam (name = "cond_text_segment" , required = True ),
1270- InputParam (name = "uncond_text_segment" , required = True ),
1271- InputParam (name = "control_latents" , required = True ),
1272- InputParam (name = "latents" , required = True ),
1273- InputParam (name = "target_condition_indexes" , required = True ),
1274- InputParam (name = "fps" , type_hint = float , default = 24.0 ),
1275- InputParam (name = "share_vision_temporal_positions" , type_hint = bool , default = True ),
1219+ InputParam (name = "cond_text_segment" , type_hint = dict , required = True , description = "Conditional text segment." ),
1220+ InputParam (
1221+ name = "uncond_text_segment" , type_hint = dict , required = True , description = "Unconditional text segment."
1222+ ),
1223+ InputParam (
1224+ name = "control_latents" ,
1225+ type_hint = list [torch .Tensor ],
1226+ required = True ,
1227+ description = "Clean control latents for this chunk, one per hint in canonical order." ,
1228+ ),
1229+ InputParam (
1230+ name = "latents" , type_hint = torch .Tensor , required = True , description = "Noisy target latents for this chunk."
1231+ ),
1232+ InputParam (
1233+ name = "target_condition_indexes" ,
1234+ type_hint = list [int ],
1235+ required = True ,
1236+ description = "Latent-frame indexes fixed by the chunk's conditioning." ,
1237+ ),
1238+ InputParam (name = "fps" , type_hint = float , default = 24.0 , description = "Frame rate of the generated video." ),
1239+ InputParam (
1240+ name = "share_vision_temporal_positions" ,
1241+ type_hint = bool ,
1242+ default = True ,
1243+ description = "Whether control and target items share vision temporal positions." ,
1244+ ),
12761245 ]
12771246
12781247 @property
12791248 def intermediate_outputs (self ) -> list [OutputParam ]:
12801249 return [
1281- OutputParam ("cond_full_static" ),
1282- OutputParam ("cond_no_control_static" ),
1283- OutputParam ("uncond_full_static" ),
1284- OutputParam ("num_noisy_vision_tokens" ),
1250+ OutputParam (
1251+ "cond_full_static" ,
1252+ type_hint = dict ,
1253+ kwargs_type = "denoiser_input_fields" ,
1254+ description = "Conditional [control..., target] transfer sequence carrying every control item." ,
1255+ ),
1256+ OutputParam (
1257+ "cond_no_control_static" ,
1258+ type_hint = dict ,
1259+ kwargs_type = "denoiser_input_fields" ,
1260+ description = "Conditional [target] transfer sequence with the control items dropped." ,
1261+ ),
1262+ OutputParam (
1263+ "uncond_full_static" ,
1264+ type_hint = dict ,
1265+ kwargs_type = "denoiser_input_fields" ,
1266+ description = "Unconditional [control..., target] transfer sequence for text CFG." ,
1267+ ),
1268+ OutputParam (
1269+ "num_noisy_vision_tokens" ,
1270+ type_hint = int ,
1271+ description = "Number of noisy target vision tokens denoised each step." ,
1272+ ),
12851273 ]
12861274
12871275 @torch .no_grad ()
@@ -1347,8 +1335,10 @@ def inputs(self) -> list[InputParam]:
13471335 @property
13481336 def intermediate_outputs (self ) -> list [OutputParam ]:
13491337 return [
1350- OutputParam ("timesteps" ),
1351- OutputParam ("num_warmup_steps" ),
1338+ OutputParam ("timesteps" , type_hint = torch .Tensor , description = "Scheduler timesteps for this chunk." ),
1339+ OutputParam (
1340+ "num_warmup_steps" , type_hint = int , description = "Number of scheduler warmup steps for this chunk."
1341+ ),
13521342 ]
13531343
13541344 @torch .no_grad ()
0 commit comments