---
title: matrixgame2_denoising
---

<div class="python-reference">
<a id="fastvideo.pipelines.stages.matrixgame2_denoising-classes"></a>
<a id="fastvideo.pipelines.stages.matrixgame2_denoising-functions"></a>
<a id="fastvideo.pipelines.stages.matrixgame2_denoising"></a>

<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.get_local_torch_device"><code>fastvideo.pipelines.stages.matrixgame2_denoising.get_local_torch_device</code></h2>
<pre class="doc-signature"><code>get_local_torch_device() -&gt; torch.device</code></pre>
<p>Return the torch device for the current rank.</p>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs"><code>fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs</code></h2>
<pre class="doc-signature"><code>FastVideoArgs(model_path: str, mode: ExecutionMode = ExecutionMode.INFERENCE, workload_type: WorkloadType = WorkloadType.T2V, distributed_executor_backend: str = &#x27;mp&#x27;, enable_streaming_ipc_queues: bool = False, ray_placement_group: PlacementGroup | None = None, ray_runtime_env: RuntimeEnv | None = None, inference_mode: bool = True, trust_remote_code: bool = False, revision: str | None = None, num_gpus: int = 1, tp_size: int = -1, sp_size: int = -1, hsdp_replicate_dim: int = 1, hsdp_shard_dim: int = -1, dist_timeout: int | None = None, pipeline_config: PipelineConfig = PipelineConfig(), preprocess_config: PreprocessConfig | None = None, lora_path: str | None = None, lora_nickname: str = &#x27;default&#x27;, lora_strength: float = 1.0, lora_target_modules: list&#91;str&#93; | None = None, output_type: str = &#x27;pil&#x27;, attention_backend: str | None = None, dit_cpu_offload: bool = True, use_fsdp_inference: bool = False, dit_layerwise_offload: bool = True, text_encoder_cpu_offload: bool = True, image_encoder_cpu_offload: bool = True, vae_cpu_offload: bool = True, pin_cpu_memory: bool = True, h3_sequential_load: bool | None = None, h3_encoder_split: bool | None = None, h3_encoder_nodes: int = -1, h3_encoder_workers: int = 0, video_decode_backend: str = &#x27;h3-vae&#x27;, taeh3_checkpoint: str | None = None, taeh3_chunk_size: int = 5, h3_vae_nvfp4_decoder: str | None = None, lazy_module_load: bool | None = None, vae_parallel_decode: bool = False, vae_parallel_encode: bool = False, vae_parallel_decode_strategy: str | None = None, enable_torch_compile: bool = False, regional_compile: bool = False, enable_torch_compile_text_encoder: bool = False, enable_torch_compile_vae: bool = False, enable_torch_compile_audio_vae: bool = False, torch_compile_kwargs: dict&#91;str, Any&#93; = dict(), torch_compile_kwargs_dit: dict&#91;str, Any&#93; = dict(), torch_compile_kwargs_text_encoder: dict&#91;str, Any&#93; = dict(), torch_compile_kwargs_vae: dict&#91;str, Any&#93; = dict(), torch_compile_kwargs_audio_vae: dict&#91;str, Any&#93; = dict(), inference_torch_compile: bool = False, h3_vsa_fp4: dict&#91;str, Any&#93; = dict(), disable_autocast: bool = False, VSA_sparsity: float | None = None, VSA_tile_size: int | None = None, moba_config_path: str | None = None, moba_config: dict&#91;str, Any&#93; = dict(), master_port: int | None = None, enable_stage_verification: bool = True, prompt_txt: str | None = None, ltx2_vae_tiling: bool | None = None, ltx2_vae_spatial_tile_size_in_pixels: int | None = None, ltx2_vae_spatial_tile_overlap_in_pixels: int | None = None, ltx2_vae_temporal_tile_size_in_frames: int | None = None, ltx2_vae_temporal_tile_overlap_in_frames: int | None = None, ltx2_initial_latent_path: str | None = None, ltx2_audio_latent_path: str | None = None, refine_enabled: bool | None = None, refine_upsampler_path: str | None = None, refine_transformer_path: str | None = None, refine_lora_path: str | None = None, refine_num_inference_steps: int | None = None, refine_guidance_scale: float | None = None, refine_add_noise: bool | None = None, refine_noise_path: str | None = None, refine_audio_noise_path: str | None = None, ltx2_refine_enabled: bool = False, ltx2_refine_upsampler_path: str | None = None, ltx2_refine_transformer_path: str | None = None, ltx2_refine_lora_path: str | None = None, ltx2_refine_num_inference_steps: int = 3, ltx2_refine_guidance_scale: float = 1.0, ltx2_refine_add_noise: bool = True, ltx2_refine_noise_path: str | None = None, ltx2_refine_audio_noise_path: str | None = None, ltx2_legacy_native_noise_order: bool = False, ltx2_use_distilled_sigmas: bool = True, model_paths: dict&#91;str, str&#93; = dict(), model_loaded: dict&#91;str, bool&#93; = (lambda: &#123;&#x27;transformer&#x27;: True, &#x27;vae&#x27;: True, &#x27;upsampler&#x27;: True&#125;)(), override_text_encoder_safetensors: str | None = None, override_text_encoder_quant: QuantizationMethods = None, transformer_quant: Any | None = None, override_transformer_cls_name: str | None = None, init_weights_from_safetensors: str = &#x27;&#x27;, init_weights_from_safetensors_2: str = &#x27;&#x27;, override_pipeline_cls_name: str | None = None, boundary_ratio: float | None = 0.875)</code></pre>


<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.is_output_rank"><code>fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.is_output_rank</code></h3>
<pre class="doc-signature"><code>is_output_rank: bool</code></pre>
<p>Whether this process may materialize user-facing outputs.</p>
<p>This is runtime state assigned by an SPMD executor, not a public
configuration field, so dataclass serialization and typed config
parsing deliberately ignore it.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.add_cli_args"><code>fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.add_cli_args</code></h3>
<pre class="doc-signature"><code>add_cli_args(parser: FlexibleArgumentParser) -&gt; FlexibleArgumentParser</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.from_cli_args"><code>fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.from_cli_args</code></h3>
<pre class="doc-signature"><code>from_cli_args(args: argparse.Namespace) -&gt; FastVideoArgs</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.from_kwargs"><code>fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.from_kwargs</code></h3>
<pre class="doc-signature"><code>from_kwargs(**kwargs: Any) -&gt; FastVideoArgs</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.check_fastvideo_args"><code>fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.check_fastvideo_args</code></h3>
<pre class="doc-signature"><code>check_fastvideo_args() -&gt; None</code></pre>
<p>Validate inference arguments for consistency</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.finalize_device_offload_policy"><code>fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.finalize_device_offload_policy</code></h3>
<pre class="doc-signature"><code>finalize_device_offload_policy(device_id: int = 0) -&gt; bool</code></pre>
<p>Apply device-local memory policy, then resolve incompatible modes.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.disable_offload_on_unified_memory"><code>fastvideo.pipelines.stages.matrixgame2_denoising.FastVideoArgs.disable_offload_on_unified_memory</code></h3>
<pre class="doc-signature"><code>disable_offload_on_unified_memory(device_id: int = 0, *, offload_flag: str | None = None) -&gt; bool</code></pre>
<p>Disable host offload after a worker has selected its device.</p>
<p>CUDA's unified-memory probe reads runtime device properties and may
initialize a CUDA context. Callers must therefore use this only inside
a device-owning process, after selecting and binding <code>device_id</code>.
Returning the classification lets direct component-loader callers
apply the same policy to explicit per-call overrides. When
<code>offload_flag</code> is given, the return value says whether this policy
covers that component role.</p>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.set_forward_context"><code>fastvideo.pipelines.stages.matrixgame2_denoising.set_forward_context</code></h2>
<pre class="doc-signature"><code>set_forward_context(current_timestep, attn_metadata, forward_batch: Optional&#91;ForwardBatch&#93; = None)</code></pre>
<p>A context manager that stores the current forward context,
can be attention metadata, etc.
Here we can inject common logic for every model forward pass.</p>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.init_logger"><code>fastvideo.pipelines.stages.matrixgame2_denoising.init_logger</code></h2>
<pre class="doc-signature"><code>init_logger(name: str) -&gt; _FastvideoLogger</code></pre>
<p>The main purpose of this function is to ensure that loggers are
retrieved in such a way that we can be sure the root fastvideo logger has
already been configured.</p>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.pred_noise_to_pred_video"><code>fastvideo.pipelines.stages.matrixgame2_denoising.pred_noise_to_pred_video</code></h2>
<pre class="doc-signature"><code>pred_noise_to_pred_video(pred_noise: torch.Tensor, noise_input_latent: torch.Tensor, timestep: torch.Tensor, scheduler: Any) -&gt; torch.Tensor</code></pre>
<p>Convert predicted noise to clean latent.</p>
<p>pred_noise: the predicted noise with shape [B, C, H, W]
    where B is batch_size or batch_size * num_frames
noise_input_latent: the noisy latent with shape [B, C, H, W],
timestep: the timestep with shape [1] or [bs * num_frames] or [bs, num_frames]
scheduler: the scheduler</p>
<h3>Returns</h3>
<dl>
<dt><code>torch.Tensor</code></dt><dd><p>the predicted video with shape [B, C, H, W]</p></dd>
</dl>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.pred_noise_to_x_bound"><code>fastvideo.pipelines.stages.matrixgame2_denoising.pred_noise_to_x_bound</code></h2>
<pre class="doc-signature"><code>pred_noise_to_x_bound(pred_noise: torch.Tensor, noise_input_latent: torch.Tensor, timestep: torch.Tensor, boundary_timestep: torch.Tensor, scheduler: Any) -&gt; torch.Tensor</code></pre>
<p>Convert predicted noise to clean latent.</p>
<p>pred_noise: the predicted noise with shape [B, C, H, W]
    where B is batch_size or batch_size * num_frames
noise_input_latent: the noisy latent with shape [B, C, H, W],
timestep: the timestep with shape [1] or [bs * num_frames] or [bs, num_frames]
boundary_timestep: the boundary timestep with shape [1] or [bs * num_frames] or [bs, num_frames]
scheduler: the scheduler</p>
<h3>Returns</h3>
<dl>
<dt><code>torch.Tensor</code></dt><dd><p>the predicted video with shape [B, C, H, W]</p></dd>
</dl>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.ForwardBatch"><code>fastvideo.pipelines.stages.matrixgame2_denoising.ForwardBatch</code></h2>
<pre class="doc-signature"><code>ForwardBatch(data_type: str, generator: torch.Generator | list&#91;torch.Generator&#93; | None = None, image_path: str | None = None, image_embeds: list&#91;torch.Tensor&#93; = list(), pil_image: torch.Tensor | PIL.Image.Image | None = None, last_image: torch.Tensor | PIL.Image.Image | None = None, references: list&#91;Any&#93; | None = None, preprocessed_image: torch.Tensor | None = None, prompt: str | list&#91;str&#93; | None = None, negative_prompt: str | list&#91;str&#93; | None = None, prompt_path: str | None = None, output_path: str = &#x27;outputs/&#x27;, output_video_name: str | None = None, video_path: str | None = None, video_latent: torch.Tensor | None = None, pose_video_path: str | None = None, face_video_path: str | None = None, background_video_path: str | None = None, mask_video_path: str | None = None, animate_mode: str | None = None, pose_latents: torch.Tensor | None = None, face_pixel_values: torch.Tensor | None = None, audio_path: str | None = None, audio_embeds: torch.Tensor | None = None, t_thresh: float = 0.5, num_cond_frames: int = 0, prompt_embeds: list&#91;torch.Tensor&#93; = list(), negative_prompt_embeds: list&#91;torch.Tensor&#93; | None = None, prompt_attention_mask: list&#91;torch.Tensor&#93; | None = None, negative_attention_mask: list&#91;torch.Tensor&#93; | None = None, clip_embedding_pos: list&#91;torch.Tensor&#93; | None = None, clip_embedding_neg: list&#91;torch.Tensor&#93; | None = None, max_sequence_length: int | None = None, prompt_template: dict&#91;str, Any&#93; | None = None, do_classifier_free_guidance: bool = False, use_embedded_guidance: bool = False, true_cfg_scale: float = 1.0, batch_size: int | None = None, num_videos_per_prompt: int = 1, seed: int | None = None, seeds: list&#91;int&#93; | None = None, is_prompt_processed: bool = False, latents: torch.Tensor | None = None, audio_latents: torch.Tensor | None = None, lq_latents: torch.Tensor | None = None, raw_latent_shape: tuple&#91;int, ...&#93; | None = None, noise_pred: torch.Tensor | None = None, image_latent: torch.Tensor | None = None, first_frame_latent: torch.Tensor | None = None, helios_latent_chunks: list&#91;torch.Tensor&#93; | None = None, mouse_cond: torch.Tensor | None = None, keyboard_cond: torch.Tensor | None = None, grid_sizes: torch.Tensor | None = None, num_iterations: int | None = None, use_base_model: bool = False, pose: str | None = None, c2ws_plucker_emb: torch.Tensor | None = None, action_path: str | None = None, trajectory_type: str | None = None, movement_distance: float | None = None, camera_rotation: str | None = None, height_latents: list&#91;int&#93; | int | None = None, width_latents: list&#91;int&#93; | int | None = None, num_frames: list&#91;int&#93; | int = 1, height: list&#91;int&#93; | int | None = None, width: list&#91;int&#93; | int | None = None, height_sr: list&#91;int&#93; | int | None = None, width_sr: list&#91;int&#93; | int | None = None, fps: list&#91;int&#93; | int | None = None, timesteps: torch.Tensor | None = None, timestep: torch.Tensor | float | int | None = None, step_index: int | None = None, boundary_ratio: float | None = None, num_inference_steps: int = 50, num_inference_steps_sr: int = 50, guidance_scale: float = 1.0, batch_cfg: bool = False, guidance_scale_2: float | None = None, guidance_rescale: float = 0.0, eta: float = 0.0, sigmas: list&#91;float&#93; | None = None, pyramid_num_inference_steps_list: list&#91;int&#93; | None = None, history_sizes: list&#91;int&#93; | None = None, num_latent_frames_per_chunk: int = 9, keep_first_frame: bool = True, is_skip_first_chunk: bool = False, use_zero_init: bool = True, zero_steps: int = 1, is_amplify_first_chunk: bool = False, enable_teacache: bool = False, ltx2_cfg_scale_video: float = 1.0, ltx2_cfg_scale_audio: float = 1.0, ltx2_modality_scale_video: float = 1.0, ltx2_modality_scale_audio: float = 1.0, ltx2_rescale_scale: float = 0.0, ltx2_stg_scale_video: float = 0.0, ltx2_stg_scale_audio: float = 0.0, ltx2_stg_blocks_video: list&#91;int&#93; = list(), ltx2_stg_blocks_audio: list&#91;int&#93; = list(), ltx2_use_ancestral_sampler: bool = False, ltx2_images: list&#91;tuple&#91;str, int, float&#93;&#93; | None = None, ltx2_image_crf: float = 33.0, ltx2_conditioning_latent_stage1: torch.Tensor | None = None, ltx2_conditioning_latent_stage2: torch.Tensor | None = None, ltx2_video_conditions: list&#91;tuple&#91;list&#91;str&#93;, int, float&#93;&#93; | None = None, audio_start_in_s: float | None = None, audio_end_in_s: float | None = None, init_audio: Any = None, init_audio_strength: float | None = None, init_noise_level: float | None = None, inpaint_audio: Any = None, inpaint_mask: Any = None, n_tokens: int | None = None, extra_step_kwargs: dict&#91;str, Any&#93; = dict(), modules: dict&#91;str, Any&#93; = dict(), output: torch.Tensor | None = None, return_trajectory_latents: bool = False, return_trajectory_decoded: bool = False, trajectory_timesteps: list&#91;torch.Tensor&#93; | None = None, trajectory_latents: torch.Tensor | None = None, trajectory_decoded: list&#91;torch.Tensor&#93; | None = None, continuation_state: ContinuationState | None = None, return_continuation_state: bool = False, extra: dict&#91;str, Any&#93; = dict(), save_video: bool = True, return_frames: bool = False, is_cfg_negative: bool = False, VSA_sparsity: float = 0.0, logging_info: PipelineLoggingInfo = PipelineLoggingInfo(), *, return_samples: bool = False)</code></pre>
<p>Complete state passed through the pipeline execution.</p>
<p>This dataclass contains all information needed during the diffusion pipeline
execution, allowing methods to update specific components without needing
to manage numerous individual parameters.</p>

<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage</code></h2>
<pre class="doc-signature"><code>DenoisingStage(transformer, scheduler, pipeline = None, transformer_2 = None, vae = None)</code></pre>
<p>Stage for running the denoising loop in diffusion pipelines.</p>
<p>This stage handles the iterative denoising process that transforms
the initial noise into the final output.</p>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.forward"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.forward</code></h3>
<pre class="doc-signature"><code>forward(batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; ForwardBatch</code></pre>
<p>Run the denoising loop.</p>
<h4>Parameters</h4>
<dl>
<dt><code>batch: ForwardBatch</code></dt><dd><p>The current batch information.</p></dd>
<dt><code>fastvideo_args: FastVideoArgs</code></dt><dd><p>The inference arguments.</p></dd>
</dl>
<h4>Returns</h4>
<dl>
<dt><code>ForwardBatch</code></dt><dd><p>The batch with denoised latents.</p></dd>
</dl>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_denoising"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_denoising</code></h3>
<pre class="doc-signature"><code>prepare_denoising(batch, fastvideo_args, target_dtype) -&gt; DenoisingState</code></pre>
<p>Build request-local state. Family stages specialize latent conditioning.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_model_kwargs"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_model_kwargs</code></h3>
<pre class="doc-signature"><code>prepare_model_kwargs(batch, fastvideo_args) -&gt; tuple&#91;dict&#91;str, Any&#93;, dict&#91;str, Any&#93;&#93;</code></pre>
<p>Step-invariant transformer kwargs as (conditional, unconditional).</p>
<p>Family stages add named conditioning here (Wan-S2V's audio, reference
and motion latents) without the shared loop learning about it.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.activate_transformer"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.activate_transformer</code></h3>
<pre class="doc-signature"><code>activate_transformer(model, inactive_model, fastvideo_args) -&gt; None</code></pre>
<p>Keep CPU/layerwise/FSDP offload decisions independent of the sampling recipe.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.select_model"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.select_model</code></h3>
<pre class="doc-signature"><code>select_model(timestep, batch, fastvideo_args, state) -&gt; tuple&#91;Any, float&#93;</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_model_input"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_model_input</code></h3>
<pre class="doc-signature"><code>prepare_model_input(latents, batch, target_dtype, state) -&gt; torch.Tensor</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_timestep"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_timestep</code></h3>
<pre class="doc-signature"><code>prepare_timestep(timestep, latent_model_input, batch, state) -&gt; torch.Tensor</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.finish_step"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.finish_step</code></h3>
<pre class="doc-signature"><code>finish_step(latents, state) -&gt; torch.Tensor</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_extra_func_kwargs"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.prepare_extra_func_kwargs</code></h3>
<pre class="doc-signature"><code>prepare_extra_func_kwargs(func, kwargs) -&gt; dict&#91;str, Any&#93;</code></pre>
<p>Prepare extra kwargs for the scheduler step / denoise step.</p>
<h4>Parameters</h4>
<dl>
<dt><code>func</code></dt><dd><p>The function to prepare kwargs for.</p></dd>
<dt><code>kwargs</code></dt><dd><p>The kwargs to prepare.</p></dd>
</dl>
<h4>Returns</h4>
<dl>
<dt><code>dict[str, Any]</code></dt><dd><p>The prepared kwargs.</p></dd>
</dl>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.progress_bar"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.progress_bar</code></h3>
<pre class="doc-signature"><code>progress_bar(iterable: Iterable | None = None, total: int | None = None) -&gt; tqdm</code></pre>
<p>Create a progress bar for the denoising process.</p>
<h4>Parameters</h4>
<dl>
<dt><code>iterable: Iterable | None</code></dt><dd><p>The iterable to iterate over.</p></dd>
<dt><code>total: int | None</code></dt><dd><p>The total number of items.</p></dd>
</dl>
<h4>Returns</h4>
<dl>
<dt><code>tqdm</code></dt><dd><p>A tqdm progress bar.</p></dd>
</dl>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.rescale_noise_cfg"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.rescale_noise_cfg</code></h3>
<pre class="doc-signature"><code>rescale_noise_cfg(noise_cfg, noise_pred_text, guidance_rescale = 0.0) -&gt; torch.Tensor</code></pre>
<p>Rescale noise prediction according to guidance_rescale.</p>
<p>Based on findings of "Common Diffusion Noise Schedules and Sample Steps are Flawed"
(https://arxiv.org/pdf/2305.08891.pdf), Section 3.4.</p>
<h4>Parameters</h4>
<dl>
<dt><code>noise_cfg</code></dt><dd><p>The noise prediction with guidance.</p></dd>
<dt><code>noise_pred_text</code></dt><dd><p>The text-conditioned noise prediction.</p></dd>
<dt><code>guidance_rescale</code></dt><dd><p>The guidance rescale factor.</p></dd>
</dl>
<h4>Returns</h4>
<dl>
<dt><code>torch.Tensor</code></dt><dd><p>The rescaled noise prediction.</p></dd>
</dl>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.verify_input"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.verify_input</code></h3>
<pre class="doc-signature"><code>verify_input(batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; VerificationResult</code></pre>
<p>Verify denoising stage inputs.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.verify_output"><code>fastvideo.pipelines.stages.matrixgame2_denoising.DenoisingStage.verify_output</code></h3>
<pre class="doc-signature"><code>verify_output(batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; VerificationResult</code></pre>
<p>Verify denoising stage outputs.</p>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.V"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V</code></h2>
<pre class="doc-signature"><code>V()</code></pre>
<p>Common validators for pipeline stages.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.not_none"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.not_none</code></h3>
<pre class="doc-signature"><code>not_none(value: Any) -&gt; bool</code></pre>
<p>Check if value is not None.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.positive_int"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.positive_int</code></h3>
<pre class="doc-signature"><code>positive_int(value: Any) -&gt; bool</code></pre>
<p>Check if value is a positive integer.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.non_negative_int"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.non_negative_int</code></h3>
<pre class="doc-signature"><code>non_negative_int(value: Any) -&gt; bool</code></pre>
<p>Check if value is a non-negative integer (allows 0).</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.positive_float"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.positive_float</code></h3>
<pre class="doc-signature"><code>positive_float(value: Any) -&gt; bool</code></pre>
<p>Check if value is a positive float.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.non_negative_float"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.non_negative_float</code></h3>
<pre class="doc-signature"><code>non_negative_float(value: Any) -&gt; bool</code></pre>
<p>Check if value is a non-negative float.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.divisible_by"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.divisible_by</code></h3>
<pre class="doc-signature"><code>divisible_by(value: Any, divisor: int) -&gt; bool</code></pre>
<p>Check if value is divisible by divisor.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.is_tensor"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.is_tensor</code></h3>
<pre class="doc-signature"><code>is_tensor(value: Any) -&gt; bool</code></pre>
<p>Check if value is a torch tensor and doesn't contain NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.tensor_with_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.tensor_with_dims</code></h3>
<pre class="doc-signature"><code>tensor_with_dims(value: Any, dims: int) -&gt; bool</code></pre>
<p>Check if value is a tensor with specific dimensions and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.tensor_min_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.tensor_min_dims</code></h3>
<pre class="doc-signature"><code>tensor_min_dims(value: Any, min_dims: int) -&gt; bool</code></pre>
<p>Check if value is a tensor with at least min_dims dimensions and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.tensor_shape_matches"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.tensor_shape_matches</code></h3>
<pre class="doc-signature"><code>tensor_shape_matches(value: Any, expected_shape: tuple) -&gt; bool</code></pre>
<p>Check if tensor shape matches expected shape (None for any size) and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.list_not_empty"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.list_not_empty</code></h3>
<pre class="doc-signature"><code>list_not_empty(value: Any) -&gt; bool</code></pre>
<p>Check if value is a non-empty list.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.list_length"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.list_length</code></h3>
<pre class="doc-signature"><code>list_length(value: Any, length: int) -&gt; bool</code></pre>
<p>Check if list has specific length.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.list_min_length"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.list_min_length</code></h3>
<pre class="doc-signature"><code>list_min_length(value: Any, min_length: int) -&gt; bool</code></pre>
<p>Check if list has at least min_length items.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.string_not_empty"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.string_not_empty</code></h3>
<pre class="doc-signature"><code>string_not_empty(value: Any) -&gt; bool</code></pre>
<p>Check if value is a non-empty string.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.string_or_list_strings"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.string_or_list_strings</code></h3>
<pre class="doc-signature"><code>string_or_list_strings(value: Any) -&gt; bool</code></pre>
<p>Check if value is a string or list of strings.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.bool_value"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.bool_value</code></h3>
<pre class="doc-signature"><code>bool_value(value: Any) -&gt; bool</code></pre>
<p>Check if value is a boolean.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.generator_or_list_generators"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.generator_or_list_generators</code></h3>
<pre class="doc-signature"><code>generator_or_list_generators(value: Any) -&gt; bool</code></pre>
<p>Check if value is a Generator or list of Generators.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.is_list"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.is_list</code></h3>
<pre class="doc-signature"><code>is_list(value: Any) -&gt; bool</code></pre>
<p>Check if value is a list (can be empty).</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.is_tuple"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.is_tuple</code></h3>
<pre class="doc-signature"><code>is_tuple(value: Any) -&gt; bool</code></pre>
<p>Check if value is a tuple.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.none_or_tensor"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.none_or_tensor</code></h3>
<pre class="doc-signature"><code>none_or_tensor(value: Any) -&gt; bool</code></pre>
<p>Check if value is None or a tensor without NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors_with_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors_with_dims</code></h3>
<pre class="doc-signature"><code>list_of_tensors_with_dims(value: Any, dims: int) -&gt; bool</code></pre>
<p>Check if value is a non-empty list where all items are tensors with specific dimensions and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors</code></h3>
<pre class="doc-signature"><code>list_of_tensors(value: Any) -&gt; bool</code></pre>
<p>Check if value is a non-empty list where all items are tensors without NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors_with_min_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors_with_min_dims</code></h3>
<pre class="doc-signature"><code>list_of_tensors_with_min_dims(value: Any, min_dims: int) -&gt; bool</code></pre>
<p>Check if value is a non-empty list where all items are tensors with at least min_dims dimensions and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.none_or_tensor_with_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.none_or_tensor_with_dims</code></h3>
<pre class="doc-signature"><code>none_or_tensor_with_dims(dims: int) -&gt; Callable&#91;&#91;Any&#93;, bool&#93;</code></pre>
<p>Return a validator that checks if value is None or a tensor with specific dimensions and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.none_or_list"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.none_or_list</code></h3>
<pre class="doc-signature"><code>none_or_list(value: Any) -&gt; bool</code></pre>
<p>Check if value is None or a list.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.none_or_positive_int"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.none_or_positive_int</code></h3>
<pre class="doc-signature"><code>none_or_positive_int(value: Any) -&gt; bool</code></pre>
<p>Check if value is None or a positive integer.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.with_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.with_dims</code></h3>
<pre class="doc-signature"><code>with_dims(dims: int) -&gt; Callable&#91;&#91;Any&#93;, bool&#93;</code></pre>
<p>Return a validator that checks if tensor has specific dimensions and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.min_list_length"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.min_list_length</code></h3>
<pre class="doc-signature"><code>min_list_length(min_length: int) -&gt; Callable&#91;&#91;Any&#93;, bool&#93;</code></pre>
<p>Return a validator that checks if a list has at least min_length items.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.min_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.min_dims</code></h3>
<pre class="doc-signature"><code>min_dims(min_dims: int) -&gt; Callable&#91;&#91;Any&#93;, bool&#93;</code></pre>
<p>Return a validator that checks if tensor has at least min_dims dimensions and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.divisible"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.divisible</code></h3>
<pre class="doc-signature"><code>divisible(divisor: int) -&gt; Callable&#91;&#91;Any&#93;, bool&#93;</code></pre>
<p>Return a validator that checks if value is divisible by divisor.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.positive_int_divisible"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.positive_int_divisible</code></h3>
<pre class="doc-signature"><code>positive_int_divisible(divisor: int) -&gt; Callable&#91;&#91;Any&#93;, bool&#93;</code></pre>
<p>Return a validator that checks if value is a positive integer divisible by divisor.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors_dims</code></h3>
<pre class="doc-signature"><code>list_of_tensors_dims(dims: int) -&gt; Callable&#91;&#91;Any&#93;, bool&#93;</code></pre>
<p>Return a validator that checks if value is a list of tensors with specific dimensions and no NaN values.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors_min_dims"><code>fastvideo.pipelines.stages.matrixgame2_denoising.V.list_of_tensors_min_dims</code></h3>
<pre class="doc-signature"><code>list_of_tensors_min_dims(min_dims: int) -&gt; Callable&#91;&#91;Any&#93;, bool&#93;</code></pre>
<p>Return a validator that checks if value is a list of tensors with at least min_dims dimensions and no NaN values.</p>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult</code></h2>
<pre class="doc-signature"><code>VerificationResult()</code></pre>
<p>Wrapper class for stage verification results.</p>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.add_check"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.add_check</code></h3>
<pre class="doc-signature"><code>add_check(field_name: str, value: Any, validators: Callable&#91;&#91;Any&#93;, bool&#93; | list&#91;Callable&#91;&#91;Any&#93;, bool&#93;&#93;) -&gt; VerificationResult</code></pre>
<p>Add a validation check for a field.</p>
<h4>Parameters</h4>
<dl>
<dt><code>field_name: str</code></dt><dd><p>Name of the field being checked</p></dd>
<dt><code>value: Any</code></dt><dd><p>The actual value to validate</p></dd>
<dt><code>validators: Callable[[Any], bool] | list[Callable[[Any], bool]]</code></dt><dd><p>Single validation function or list of validation functions.
       Each function will be called with the value as its first argument.</p></dd>
</dl>
<h4>Returns</h4>
<dl>
<dt><code>VerificationResult</code></dt><dd><p>Self for method chaining</p></dd>
</dl>
<h4>Examples</h4>
<h1>Single validator</h1>
<p>result.add_check("tensor", my_tensor, V.is_tensor)</p>
<h1>Multiple validators (all must pass)</h1>
<p>result.add_check("latents", batch.latents, [V.is_tensor, V.with_dims(5)])</p>
<h1>Using partial functions for parameters</h1>
<p>result.add_check("height", batch.height, [V.not_none, V.divisible(8)])</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.is_valid"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.is_valid</code></h3>
<pre class="doc-signature"><code>is_valid() -&gt; bool</code></pre>
<p>Check if all validations passed.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.get_failed_fields"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.get_failed_fields</code></h3>
<pre class="doc-signature"><code>get_failed_fields() -&gt; list&#91;str&#93;</code></pre>
<p>Get list of fields that failed validation.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.get_detailed_failures"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.get_detailed_failures</code></h3>
<pre class="doc-signature"><code>get_detailed_failures() -&gt; dict&#91;str, list&#91;ValidationFailure&#93;&#93;</code></pre>
<p>Get detailed failure information for each failed field.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.get_failure_summary"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.get_failure_summary</code></h3>
<pre class="doc-signature"><code>get_failure_summary() -&gt; str</code></pre>
<p>Get a comprehensive summary of all validation failures.</p>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.to_dict"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VerificationResult.to_dict</code></h3>
<pre class="doc-signature"><code>to_dict() -&gt; dict</code></pre>
<p>Convert to dictionary for backward compatibility.</p>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend</code></h2>
<pre class="doc-signature"><code>VideoSparseAttentionBackend()</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_supported_head_sizes"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_supported_head_sizes</code></h3>
<pre class="doc-signature"><code>get_supported_head_sizes() -&gt; list&#91;int&#93;</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_name"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_name</code></h3>
<pre class="doc-signature"><code>get_name() -&gt; str</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_impl_cls"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_impl_cls</code></h3>
<pre class="doc-signature"><code>get_impl_cls() -&gt; type&#91;VideoSparseAttentionImpl&#93;</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_metadata_cls"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_metadata_cls</code></h3>
<pre class="doc-signature"><code>get_metadata_cls() -&gt; type&#91;VideoSparseAttentionMetadata&#93;</code></pre>

<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_builder_cls"><code>fastvideo.pipelines.stages.matrixgame2_denoising.VideoSparseAttentionBackend.get_builder_cls</code></h3>
<pre class="doc-signature"><code>get_builder_cls() -&gt; type&#91;VideoSparseAttentionMetadataBuilder&#93;</code></pre>

<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.BlockProcessingContext"><code>fastvideo.pipelines.stages.matrixgame2_denoising.BlockProcessingContext</code></h2>
<pre class="doc-signature"><code>BlockProcessingContext(batch: ForwardBatch, block_idx: int, start_index: int, kv_cache1: list&#91;dict&#91;Any, Any&#93;&#93;, kv_cache2: list&#91;dict&#91;Any, Any&#93;&#93; | None, kv_cache_mouse: list&#91;dict&#91;Any, Any&#93;&#93; | None, kv_cache_keyboard: list&#91;dict&#91;Any, Any&#93;&#93; | None, crossattn_cache: list&#91;dict&#91;Any, Any&#93;&#93;, timesteps: torch.Tensor, block_sizes: list&#91;int&#93;, noise_pool: list&#91;torch.Tensor&#93; | None, fastvideo_args: FastVideoArgs, target_dtype: torch.dtype, autocast_enabled: bool, boundary_timestep: float | None, high_noise_timesteps: torch.Tensor | None, context_noise: float, image_kwargs: dict&#91;str, Any&#93;, pos_cond_kwargs: dict&#91;str, Any&#93;)</code></pre>
<p>Dataclass contains for block processing.</p>

<details><summary>Source</summary><pre><code>@dataclass
class BlockProcessingContext:
    &quot;&quot;&quot;Dataclass contains for block processing.&quot;&quot;&quot;

    batch: ForwardBatch

    block_idx: int
    start_index: int

    kv_cache1: list&#91;dict&#91;Any, Any&#93;&#93;
    kv_cache2: list&#91;dict&#91;Any, Any&#93;&#93; | None
    kv_cache_mouse: list&#91;dict&#91;Any, Any&#93;&#93; | None
    kv_cache_keyboard: list&#91;dict&#91;Any, Any&#93;&#93; | None
    crossattn_cache: list&#91;dict&#91;Any, Any&#93;&#93;

    timesteps: torch.Tensor
    block_sizes: list&#91;int&#93;
    noise_pool: list&#91;torch.Tensor&#93; | None

    fastvideo_args: FastVideoArgs
    target_dtype: torch.dtype
    autocast_enabled: bool
    boundary_timestep: float | None
    high_noise_timesteps: torch.Tensor | None
    context_noise: float

    image_kwargs: dict&#91;str, Any&#93;
    pos_cond_kwargs: dict&#91;str, Any&#93;

    def get_kv_cache(self, timestep_val: float) -&gt; list&#91;dict&#91;Any, Any&#93;&#93;:
        if self.boundary_timestep is not None:
            if timestep_val &gt;= self.boundary_timestep:
                return self.kv_cache1
            else:
                assert self.kv_cache2 is not None, &quot;kv_cache2 is not initialized&quot;
                return self.kv_cache2
        return self.kv_cache1</code></pre></details>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.BlockProcessingContext.get_kv_cache"><code>fastvideo.pipelines.stages.matrixgame2_denoising.BlockProcessingContext.get_kv_cache</code></h3>
<pre class="doc-signature"><code>get_kv_cache(timestep_val: float) -&gt; list&#91;dict&#91;Any, Any&#93;&#93;</code></pre>

<details><summary>Source</summary><pre><code>def get_kv_cache(self, timestep_val: float) -&gt; list&#91;dict&#91;Any, Any&#93;&#93;:
    if self.boundary_timestep is not None:
        if timestep_val &gt;= self.boundary_timestep:
            return self.kv_cache1
        else:
            assert self.kv_cache2 is not None, &quot;kv_cache2 is not initialized&quot;
            return self.kv_cache2
    return self.kv_cache1</code></pre></details>
<h2 id="fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage"><code>fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage</code></h2>
<pre class="doc-signature"><code>MatrixGame2CausalDenoisingStage(transformer, scheduler, pipeline = None, transformer_2 = None, vae = None)</code></pre>


<details><summary>Source</summary><pre><code>class MatrixGame2CausalDenoisingStage(DenoisingStage):

    def __init__(self, transformer, scheduler, pipeline=None, transformer_2=None, vae=None) -&gt; None:
        super().__init__(transformer, scheduler, pipeline, transformer_2, vae)
        self.transformer = transformer
        self.transformer_2 = transformer_2
        self.vae = vae
        self.num_transformer_blocks = len(self.transformer.blocks)

        if hasattr(self.transformer, &#x27;config&#x27;) and hasattr(self.transformer.config, &#x27;arch_config&#x27;):
            self.num_frame_per_block = getattr(self.transformer.config.arch_config, &#x27;num_frames_per_block&#x27;,
                                               getattr(self.transformer, &#x27;num_frame_per_block&#x27;, 1))
            self.sliding_window_num_frames = getattr(self.transformer.config.arch_config, &#x27;sliding_window_num_frames&#x27;,
                                                     15)
        else:
            self.num_frame_per_block = getattr(self.transformer, &#x27;num_frame_per_block&#x27;, 1)
            self.sliding_window_num_frames = 15

        try:
            self.local_attn_size = getattr(self.transformer, &quot;local_attn_size&quot;, -1)
        except Exception:
            self.local_attn_size = -1

        assert self.local_attn_size != -1, (f&quot;local_attn_size must be set for Matrix-Game causal inference, &quot;
                                            f&quot;got &#123;self.local_attn_size&#125;. Check MatrixGame2WanVideoArchConfig.&quot;)
        assert self.num_frame_per_block &gt; 0, (f&quot;num_frame_per_block must be positive, got &#123;self.num_frame_per_block&#125;&quot;)

        logger.info(&quot;Matrix-Game 2.0 causal inference initialized: &quot;
                    &quot;local_attn_size=%s, num_frame_per_block=%s&quot;, self.local_attn_size, self.num_frame_per_block)

        self.action_config = getattr(self.transformer, &#x27;action_config&#x27;, &#123;&#125;)
        self.use_action_module = len(self.action_config) &gt; 0

        self._streaming_initialized: bool = False
        self._streaming_ctx: BlockProcessingContext | None = None

    def forward(
        self,
        batch: ForwardBatch,
        fastvideo_args: FastVideoArgs,
    ) -&gt; ForwardBatch:
        target_dtype = torch.bfloat16
        autocast_enabled = (target_dtype != torch.float32) and not fastvideo_args.disable_autocast

        latent_seq_length = batch.latents.shape&#91;-1&#93; * batch.latents.shape&#91;-2&#93;
        patch_size = self.transformer.patch_size
        patch_ratio = patch_size&#91;-1&#93; * patch_size&#91;-2&#93;
        self.frame_seq_length = latent_seq_length // patch_ratio

        timesteps = torch.tensor(fastvideo_args.pipeline_config.dmd_denoising_steps, dtype=torch.long).cpu()
        if fastvideo_args.pipeline_config.warp_denoising_step:
            scheduler_timesteps = torch.cat((self.scheduler.timesteps.cpu(), torch.tensor(&#91;0&#93;, dtype=torch.float32)))
            timesteps = scheduler_timesteps&#91;1000 - timesteps&#93;
        timesteps = timesteps.to(get_local_torch_device())

        boundary_ratio = getattr(fastvideo_args.pipeline_config.dit_config, &#x27;boundary_ratio&#x27;, None)
        if boundary_ratio is not None:
            boundary_timestep = boundary_ratio * self.scheduler.num_train_timesteps
            high_noise_timesteps = timesteps&#91;timesteps &gt;= boundary_timestep&#93;
        else:
            boundary_timestep = None
            high_noise_timesteps = None

        image_embeds = batch.image_embeds
        if len(image_embeds) &gt; 0:
            assert torch.isnan(image_embeds&#91;0&#93;).sum() == 0
            image_embeds = &#91;image_embed.to(target_dtype) for image_embed in image_embeds&#93;

        # directly set the kwarg.
        image_kwargs = &#123;&quot;encoder_hidden_states_image&quot;: image_embeds&#125;
        pos_cond_kwargs: dict&#91;str, Any&#93; = &#123;&#125;

        assert batch.latents is not None, &quot;latents must be provided&quot;
        latents = batch.latents
        b, c, t, h, w = latents.shape
        prompt_embeds = batch.prompt_embeds
        assert torch.isnan(prompt_embeds&#91;0&#93;).sum() == 0

        kv_cache1 = self._initialize_kv_cache(batch_size=latents.shape&#91;0&#93;, dtype=target_dtype, device=latents.device)
        kv_cache2 = None
        if boundary_timestep is not None:
            kv_cache2 = self._initialize_kv_cache(batch_size=latents.shape&#91;0&#93;,
                                                  dtype=target_dtype,
                                                  device=latents.device)

        kv_cache_mouse = None
        kv_cache_keyboard = None
        if self.use_action_module:
            kv_cache_mouse, kv_cache_keyboard = self._initialize_action_kv_cache(batch_size=latents.shape&#91;0&#93;,
                                                                                 dtype=target_dtype,
                                                                                 device=latents.device)

        crossattn_cache = self._initialize_crossattn_cache(
            batch_size=latents.shape&#91;0&#93;,
            max_text_len=257,  # 1 CLS + 256 patch tokens
            dtype=target_dtype,
            device=latents.device)

        if t % self.num_frame_per_block != 0:
            raise ValueError(&quot;num_frames must be divisible by num_frame_per_block for causal denoising&quot;)
        num_blocks = t // self.num_frame_per_block
        block_sizes = &#91;self.num_frame_per_block&#93; * num_blocks
        start_index = 0

        if boundary_timestep is not None:
            block_sizes&#91;0&#93; = 1

        # NOTE: Matrix-Game 2.0 does NOT process the first frame separately.
        # The first frame information is already encoded in batch.image_latent (cond_concat)
        # and will be used by the model via channel concatenation: torch.cat(&#91;x, cond_concat&#93;, dim=1)

        ctx = BlockProcessingContext(
            batch=batch,
            block_idx=0,
            start_index=0,
            kv_cache1=kv_cache1,
            kv_cache2=kv_cache2,
            kv_cache_mouse=kv_cache_mouse,
            kv_cache_keyboard=kv_cache_keyboard,
            crossattn_cache=crossattn_cache,
            timesteps=timesteps,
            block_sizes=block_sizes,
            noise_pool=None,
            fastvideo_args=fastvideo_args,
            target_dtype=target_dtype,
            autocast_enabled=autocast_enabled,
            boundary_timestep=boundary_timestep,
            high_noise_timesteps=high_noise_timesteps,
            context_noise=getattr(fastvideo_args.pipeline_config, &quot;context_noise&quot;, 0),
            image_kwargs=image_kwargs,
            pos_cond_kwargs=pos_cond_kwargs,
        )

        context_noise = getattr(fastvideo_args.pipeline_config, &quot;context_noise&quot;, 0)

        with self.progress_bar(total=len(block_sizes) * len(timesteps)) as progress_bar:
            for block_idx, current_num_frames in enumerate(block_sizes):
                ctx.block_idx = block_idx
                ctx.start_index = start_index
                current_latents = latents&#91;:, :, start_index:start_index + current_num_frames, :, :&#93;

                action_kwargs = self._prepare_action_kwargs(batch, start_index, current_num_frames)

                current_latents = self._process_single_block(
                    current_latents=current_latents,
                    batch=batch,
                    start_index=start_index,
                    current_num_frames=current_num_frames,
                    timesteps=timesteps,
                    ctx=ctx,
                    action_kwargs=action_kwargs,
                    progress_bar=progress_bar,
                )

                latents&#91;:, :, start_index:start_index + current_num_frames, :, :&#93; = current_latents

                # Update KV caches with clean context
                self._update_context_cache(
                    current_latents=current_latents,
                    batch=batch,
                    start_index=start_index,
                    current_num_frames=current_num_frames,
                    ctx=ctx,
                    action_kwargs=action_kwargs,
                    context_noise=context_noise,
                )

                start_index += current_num_frames

        if boundary_timestep is not None:
            num_frames_to_remove = self.num_frame_per_block - 1
            if num_frames_to_remove &gt; 0:
                latents = latents&#91;:, :, :-num_frames_to_remove, :, :&#93;

        batch.latents = latents
        return batch

    def _prepare_action_kwargs(self, batch: ForwardBatch, start_index: int, num_frames: int) -&gt; dict&#91;str, Any&#93;:
        action_kwargs: dict&#91;str, Any&#93; = &#123;&#125;
        if not self.use_action_module:
            return action_kwargs

        vae_time_compression_ratio = 4
        end_frame_idx = 1 + vae_time_compression_ratio * (start_index + num_frames - 1)
        if hasattr(batch, &#x27;mouse_cond&#x27;) and batch.mouse_cond is not None:
            action_kwargs&#91;&#x27;mouse_cond&#x27;&#93; = batch.mouse_cond&#91;:, :end_frame_idx&#93;
        if hasattr(batch, &#x27;keyboard_cond&#x27;) and batch.keyboard_cond is not None:
            action_kwargs&#91;&#x27;keyboard_cond&#x27;&#93; = batch.keyboard_cond&#91;:, :end_frame_idx&#93;

        # CRITICAL: Pass num_frame_per_block to model - this should be num_frames (current block size)
        action_kwargs&#91;&#x27;num_frame_per_block&#x27;&#93; = num_frames
        return action_kwargs

    def _initialize_kv_cache(self, batch_size: int, dtype: torch.dtype, device: torch.device) -&gt; list&#91;dict&#93;:
        kv_cache = &#91;&#93;
        num_attention_heads = self.transformer.num_attention_heads
        attention_head_dim = getattr(self.transformer, &#x27;attention_head_dim&#x27;,
                                     self.transformer.hidden_size // num_attention_heads)
        if self.local_attn_size != -1:
            kv_cache_size = self.local_attn_size * self.frame_seq_length
        else:
            kv_cache_size = self.frame_seq_length * self.sliding_window_num_frames

        for _ in range(self.num_transformer_blocks):
            kv_cache.append(&#123;
                &quot;k&quot;:
                torch.zeros(&#91;batch_size, kv_cache_size, num_attention_heads, attention_head_dim&#93;,
                            dtype=dtype,
                            device=device),
                &quot;v&quot;:
                torch.zeros(&#91;batch_size, kv_cache_size, num_attention_heads, attention_head_dim&#93;,
                            dtype=dtype,
                            device=device),
                &quot;global_end_index&quot;:
                torch.tensor(&#91;0&#93;, dtype=torch.long, device=device),
                &quot;local_end_index&quot;:
                torch.tensor(&#91;0&#93;, dtype=torch.long, device=device),
            &#125;)

        return kv_cache

    def _initialize_action_kv_cache(self, batch_size: int, dtype: torch.dtype, device: torch.device):
        kv_cache_mouse = &#91;&#93;
        kv_cache_keyboard = &#91;&#93;

        action_heads = self.action_config.get(&#x27;heads_num&#x27;, 16)
        mouse_head_dim = self.action_config.get(&#x27;mouse_hidden_dim&#x27;, 1024) // action_heads
        keyboard_head_dim = self.action_config.get(&#x27;keyboard_hidden_dim&#x27;, 1024) // action_heads

        kv_cache_size = self.local_attn_size if self.local_attn_size != -1 else 15

        for _ in range(self.num_transformer_blocks):
            kv_cache_keyboard.append(&#123;
                &quot;k&quot;:
                torch.zeros(&#91;batch_size, kv_cache_size, action_heads, keyboard_head_dim&#93;, dtype=dtype, device=device),
                &quot;v&quot;:
                torch.zeros(&#91;batch_size, kv_cache_size, action_heads, keyboard_head_dim&#93;, dtype=dtype, device=device),
                &quot;global_end_index&quot;:
                torch.tensor(&#91;0&#93;, dtype=torch.long, device=device),
                &quot;local_end_index&quot;:
                torch.tensor(&#91;0&#93;, dtype=torch.long, device=device),
            &#125;)
            kv_cache_mouse.append(&#123;
                &quot;k&quot;:
                torch.zeros(&#91;batch_size * self.frame_seq_length, kv_cache_size, action_heads, mouse_head_dim&#93;,
                            dtype=dtype,
                            device=device),
                &quot;v&quot;:
                torch.zeros(&#91;batch_size * self.frame_seq_length, kv_cache_size, action_heads, mouse_head_dim&#93;,
                            dtype=dtype,
                            device=device),
                &quot;global_end_index&quot;:
                torch.tensor(&#91;0&#93;, dtype=torch.long, device=device),
                &quot;local_end_index&quot;:
                torch.tensor(&#91;0&#93;, dtype=torch.long, device=device),
            &#125;)

        return kv_cache_mouse, kv_cache_keyboard

    def _initialize_crossattn_cache(self, batch_size: int, max_text_len: int, dtype: torch.dtype,
                                    device: torch.device) -&gt; list&#91;dict&#93;:
        crossattn_cache = &#91;&#93;
        num_attention_heads = self.transformer.num_attention_heads
        attention_head_dim = getattr(self.transformer, &#x27;attention_head_dim&#x27;,
                                     self.transformer.hidden_size // num_attention_heads)
        for _ in range(self.num_transformer_blocks):
            crossattn_cache.append(&#123;
                &quot;k&quot;:
                torch.zeros(&#91;batch_size, max_text_len, num_attention_heads, attention_head_dim&#93;,
                            dtype=dtype,
                            device=device),
                &quot;v&quot;:
                torch.zeros(&#91;batch_size, max_text_len, num_attention_heads, attention_head_dim&#93;,
                            dtype=dtype,
                            device=device),
                &quot;is_init&quot;:
                False,
            &#125;)
        return crossattn_cache

    def _process_single_block(
        self,
        current_latents: torch.Tensor,
        batch: ForwardBatch,
        start_index: int,
        current_num_frames: int,
        timesteps: torch.Tensor,
        ctx: BlockProcessingContext,
        action_kwargs: dict&#91;str, Any&#93;,
        noise_generator: Callable&#91;&#91;tuple, torch.dtype, int&#93;, torch.Tensor&#93;
        | None = None,
        progress_bar: Any | None = None,
    ) -&gt; torch.Tensor:
        prompt_embeds = batch.prompt_embeds
        noise_latents_btchw = current_latents.permute(0, 2, 1, 3, 4)

        for i, t_cur in enumerate(timesteps):
            # Stop if interrupted
            if getattr(self, &quot;interrupt&quot;, False):
                break
            if ctx.boundary_timestep is not None and t_cur &lt; ctx.boundary_timestep:
                current_model = self.transformer_2 if self.transformer_2 is not None else self.transformer
            else:
                current_model = self.transformer

            noise_latents = noise_latents_btchw.clone()
            latent_model_input = current_latents.to(ctx.target_dtype)

            independent_first_frame = getattr(self.transformer, &#x27;independent_first_frame&#x27;, False)
            if batch.image_latent is not None and independent_first_frame and start_index == 0:
                latent_model_input = torch.cat(&#91;latent_model_input, batch.image_latent.to(ctx.target_dtype)&#93;, dim=2)

            # t_expand needs to be &#91;batch * frames&#93; to match flattened pred_noise/noise_latents
            t_expand = t_cur.repeat(latent_model_input.shape&#91;0&#93; * current_num_frames)

            # Build attention metadata if VSA is available
            if vsa_available and self.attn_backend == VideoSparseAttentionBackend:
                self.attn_metadata_builder_cls = self.attn_backend.get_builder_cls()
                if self.attn_metadata_builder_cls is not None:
                    self.attn_metadata_builder = self.attn_metadata_builder_cls()
                    h, w = current_latents.shape&#91;-2:&#93;
                    attn_metadata = self.attn_metadata_builder.build(
                        current_timestep=i,
                        raw_latent_shape=(current_num_frames, h, w),
                        patch_size=ctx.fastvideo_args.pipeline_config.dit_config.patch_size,
                        VSA_sparsity=ctx.fastvideo_args.VSA_sparsity,
                        device=get_local_torch_device(),
                    )
                    assert attn_metadata is not None, &quot;attn_metadata cannot be None&quot;
                else:
                    attn_metadata = None
            else:
                attn_metadata = None

            with torch.autocast(device_type=&quot;cuda&quot;,
                                dtype=ctx.target_dtype,
                                enabled=ctx.autocast_enabled), \
                set_forward_context(current_timestep=i,
                                    attn_metadata=attn_metadata,
                                    forward_batch=batch):
                # Expand timestep to per-frame format &#91;batch, num_frames&#93; for causal model
                t_expanded_noise = t_cur * torch.ones((latent_model_input.shape&#91;0&#93;, current_num_frames),
                                                      device=latent_model_input.device,
                                                      dtype=torch.long)

                model_kwargs = &#123;
                    &quot;kv_cache&quot;: ctx.get_kv_cache(t_cur),
                    &quot;crossattn_cache&quot;: ctx.crossattn_cache,
                    &quot;current_start&quot;: start_index * self.frame_seq_length,
                    &quot;start_frame&quot;: start_index,
                &#125;

                if self.use_action_module and current_model == self.transformer:
                    model_kwargs.update(&#123;
                        &quot;kv_cache_mouse&quot;: ctx.kv_cache_mouse,
                        &quot;kv_cache_keyboard&quot;: ctx.kv_cache_keyboard,
                    &#125;)
                    model_kwargs.update(action_kwargs)

                pred_noise_btchw = current_model(
                    latent_model_input,
                    prompt_embeds,
                    t_expanded_noise,
                    **ctx.image_kwargs,
                    **ctx.pos_cond_kwargs,
                    **model_kwargs,
                ).permute(0, 2, 1, 3, 4)

            if ctx.boundary_timestep is not None and t_cur &gt;= ctx.boundary_timestep:
                pred_video_btchw = pred_noise_to_x_bound(
                    pred_noise=pred_noise_btchw.flatten(0, 1),
                    noise_input_latent=noise_latents.flatten(0, 1),
                    timestep=t_expand,
                    boundary_timestep=torch.ones_like(t_expand) * ctx.boundary_timestep,
                    scheduler=self.scheduler).unflatten(0, pred_noise_btchw.shape&#91;:2&#93;)
            else:
                pred_video_btchw = pred_noise_to_pred_video(pred_noise=pred_noise_btchw.flatten(0, 1),
                                                            noise_input_latent=noise_latents.flatten(0, 1),
                                                            timestep=t_expand,
                                                            scheduler=self.scheduler).unflatten(
                                                                0, pred_noise_btchw.shape&#91;:2&#93;)

            if i &lt; len(timesteps) - 1:
                next_timestep = timesteps&#91;i + 1&#93; * torch.ones(&#91;1&#93;, dtype=torch.long, device=pred_video_btchw.device)

                # Use custom noise generator if provided (for streaming), else generate
                if noise_generator is not None:
                    noise = noise_generator(pred_video_btchw.shape, pred_video_btchw.dtype, i)
                else:
                    noise = torch.randn(
                        pred_video_btchw.shape,
                        dtype=pred_video_btchw.dtype,
                        generator=(batch.generator&#91;0&#93; if isinstance(batch.generator, list) else batch.generator)).to(
                            pred_video_btchw.device)

                noise_btchw = noise
                if ctx.boundary_timestep is not None and ctx.high_noise_timesteps is not None and i &lt; len(
                        ctx.high_noise_timesteps) - 1:
                    noise_latents_btchw = self.scheduler.add_noise_high(
                        pred_video_btchw.flatten(0, 1), noise_btchw.flatten(0, 1), next_timestep,
                        torch.ones_like(next_timestep) * ctx.boundary_timestep).unflatten(
                            0, pred_video_btchw.shape&#91;:2&#93;)
                elif ctx.boundary_timestep is not None and ctx.high_noise_timesteps is not None and i == len(
                        ctx.high_noise_timesteps) - 1:
                    noise_latents_btchw = pred_video_btchw
                else:
                    noise_latents_btchw = self.scheduler.add_noise(pred_video_btchw.flatten(0, 1),
                                                                   noise_btchw.flatten(0, 1), next_timestep).unflatten(
                                                                       0, pred_video_btchw.shape&#91;:2&#93;)
                current_latents = noise_latents_btchw.permute(0, 2, 1, 3, 4)
            else:
                current_latents = pred_video_btchw.permute(0, 2, 1, 3, 4)

            if progress_bar is not None:
                progress_bar.update()

        return current_latents

    def _update_context_cache(
        self,
        current_latents: torch.Tensor,
        batch: ForwardBatch,
        start_index: int,
        current_num_frames: int,
        ctx: BlockProcessingContext,
        action_kwargs: dict&#91;str, Any&#93;,
        context_noise: float,
    ) -&gt; None:
        prompt_embeds = batch.prompt_embeds
        latents_device = current_latents.device

        # Expand context timestep to per-frame format &#91;batch, num_frames&#93; for causal model
        t_context = torch.ones(&#91;current_latents.shape&#91;0&#93;, current_num_frames&#93;, device=latents_device,
                               dtype=torch.long) * int(context_noise)
        context_bcthw = current_latents.to(ctx.target_dtype)

        with torch.autocast(device_type=&quot;cuda&quot;,
                            dtype=ctx.target_dtype,
                            enabled=ctx.autocast_enabled), \
            set_forward_context(current_timestep=0,
                                attn_metadata=None,
                                forward_batch=batch):

            context_model_kwargs = &#123;
                &quot;kv_cache&quot;: ctx.kv_cache1,
                &quot;crossattn_cache&quot;: ctx.crossattn_cache,
                &quot;current_start&quot;: start_index * self.frame_seq_length,
                &quot;start_frame&quot;: start_index,
            &#125;

            if self.use_action_module:
                context_model_kwargs.update(&#123;
                    &quot;kv_cache_mouse&quot;: ctx.kv_cache_mouse,
                    &quot;kv_cache_keyboard&quot;: ctx.kv_cache_keyboard,
                &#125;)
                context_model_kwargs.update(action_kwargs)

            if ctx.boundary_timestep is not None and self.transformer_2 is not None:
                self.transformer_2(
                    context_bcthw,
                    prompt_embeds,
                    t_context,
                    kv_cache=ctx.kv_cache2,
                    crossattn_cache=ctx.crossattn_cache,
                    current_start=start_index * self.frame_seq_length,
                    start_frame=start_index,
                    **ctx.image_kwargs,
                    **ctx.pos_cond_kwargs,
                )

            self.transformer(
                context_bcthw,
                prompt_embeds,
                t_context,
                **ctx.image_kwargs,
                **ctx.pos_cond_kwargs,
                **context_model_kwargs,
            )

    def streaming_reset(self, batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; ForwardBatch:
        target_dtype = torch.bfloat16
        autocast_enabled = (target_dtype != torch.float32) and not fastvideo_args.disable_autocast

        latent_seq_length = batch.latents.shape&#91;-1&#93; * batch.latents.shape&#91;-2&#93;
        patch_size = self.transformer.patch_size
        patch_ratio = patch_size&#91;-1&#93; * patch_size&#91;-2&#93;
        self.frame_seq_length = latent_seq_length // patch_ratio

        timesteps = torch.tensor(fastvideo_args.pipeline_config.dmd_denoising_steps, dtype=torch.long).cpu()
        if fastvideo_args.pipeline_config.warp_denoising_step:
            scheduler_timesteps = torch.cat((self.scheduler.timesteps.cpu(), torch.tensor(&#91;0&#93;, dtype=torch.float32)))
            timesteps = scheduler_timesteps&#91;1000 - timesteps&#93;
        timesteps = timesteps.to(get_local_torch_device())

        boundary_ratio = getattr(fastvideo_args.pipeline_config.dit_config, &#x27;boundary_ratio&#x27;, None)
        if boundary_ratio is not None:
            boundary_timestep = boundary_ratio * self.scheduler.num_train_timesteps
            high_noise_timesteps = timesteps&#91;timesteps &gt;= boundary_timestep&#93;
        else:
            boundary_timestep = None
            high_noise_timesteps = None

        image_embeds = batch.image_embeds
        if len(image_embeds) &gt; 0:
            assert torch.isnan(image_embeds&#91;0&#93;).sum() == 0
            image_embeds = &#91;image_embed.to(target_dtype) for image_embed in image_embeds&#93;

        # directly set the kwarg.
        image_kwargs = &#123;&quot;encoder_hidden_states_image&quot;: image_embeds&#125;
        pos_cond_kwargs: dict&#91;str, Any&#93; = &#123;&#125;

        assert batch.latents is not None, &quot;latents must be provided&quot;
        latents = batch.latents
        b, c, t, h, w = latents.shape
        prompt_embeds = batch.prompt_embeds
        assert torch.isnan(prompt_embeds&#91;0&#93;).sum() == 0

        # Initialize caches
        kv_cache1 = self._initialize_kv_cache(batch_size=latents.shape&#91;0&#93;, dtype=target_dtype, device=latents.device)
        kv_cache2 = None
        if boundary_timestep is not None:
            kv_cache2 = self._initialize_kv_cache(batch_size=latents.shape&#91;0&#93;,
                                                  dtype=target_dtype,
                                                  device=latents.device)

        kv_cache_mouse = None
        kv_cache_keyboard = None
        if self.use_action_module:
            kv_cache_mouse, kv_cache_keyboard = self._initialize_action_kv_cache(batch_size=latents.shape&#91;0&#93;,
                                                                                 dtype=target_dtype,
                                                                                 device=latents.device)

        crossattn_cache = self._initialize_crossattn_cache(
            batch_size=latents.shape&#91;0&#93;,
            max_text_len=257,  # 1 CLS + 256 patch tokens
            dtype=target_dtype,
            device=latents.device)

        # Calculate block sizes
        if t % self.num_frame_per_block != 0:
            raise ValueError(&quot;num_frames must be divisible by num_frame_per_block for causal denoising&quot;)
        num_blocks = t // self.num_frame_per_block
        block_sizes = &#91;self.num_frame_per_block&#93; * num_blocks
        if boundary_timestep is not None:
            block_sizes&#91;0&#93; = 1

        # Pre-allocate noise pool
        num_denoising_steps = len(timesteps)
        noise_shape = (b, self.num_frame_per_block, c, h, w)
        noise_pool = &#91;
            torch.randn(
                noise_shape,
                dtype=target_dtype,
                device=latents.device,
            ) for _ in range(num_denoising_steps - 1)
        &#93;

        # Create and store context
        self._streaming_ctx = BlockProcessingContext(
            batch=batch,
            block_idx=0,
            start_index=0,
            kv_cache1=kv_cache1,
            kv_cache2=kv_cache2,
            kv_cache_mouse=kv_cache_mouse,
            kv_cache_keyboard=kv_cache_keyboard,
            crossattn_cache=crossattn_cache,
            timesteps=timesteps,
            block_sizes=block_sizes,
            noise_pool=noise_pool,
            fastvideo_args=fastvideo_args,
            target_dtype=target_dtype,
            autocast_enabled=autocast_enabled,
            boundary_timestep=boundary_timestep,
            high_noise_timesteps=high_noise_timesteps,
            context_noise=getattr(fastvideo_args.pipeline_config, &quot;context_noise&quot;, 0),
            image_kwargs=image_kwargs,
            pos_cond_kwargs=pos_cond_kwargs,
        )

        self._streaming_initialized = True
        return batch

    def streaming_step(self,
                       keyboard_action: torch.Tensor | None = None,
                       mouse_action: torch.Tensor | None = None) -&gt; ForwardBatch:
        if not self._streaming_initialized or self._streaming_ctx is None:
            raise RuntimeError(&quot;Streaming not initialized! Call streaming_reset first.&quot;)

        ctx = self._streaming_ctx
        if ctx.block_idx &gt;= len(ctx.block_sizes):
            return ctx.batch

        batch = ctx.batch
        latents = batch.latents
        assert latents is not None, &quot;latents must be set in batch&quot;

        current_num_frames = ctx.block_sizes&#91;ctx.block_idx&#93;
        start_index = ctx.start_index

        current_latents = latents&#91;:, :, start_index:start_index + current_num_frames, :, :&#93;

        # Update batch with new actions for this block
        if keyboard_action is not None or mouse_action is not None:
            vae_ratio = 4
            start_frame = 0 if start_index == 0 else 1 + vae_ratio * (start_index - 1)

            if keyboard_action is not None:
                n = keyboard_action.shape&#91;1&#93;
                batch.keyboard_cond&#91;:, start_frame:start_frame + n&#93; = keyboard_action.to(batch.keyboard_cond.device)
            if mouse_action is not None:
                n = mouse_action.shape&#91;1&#93;
                batch.mouse_cond&#91;:, start_frame:start_frame + n&#93; = mouse_action.to(batch.mouse_cond.device)

        action_kwargs = self._prepare_action_kwargs(batch, start_index, current_num_frames)

        # Create noise generator that uses pre-allocated noise pool
        def streaming_noise_generator(shape: tuple, dtype: torch.dtype, step_idx: int) -&gt; torch.Tensor:
            if ctx.noise_pool is not None and step_idx &lt; len(ctx.noise_pool):
                return ctx.noise_pool&#91;step_idx&#93;&#91;:, :shape&#91;1&#93;, :, :, :&#93;.to(latents.device)
            else:
                # Fallback to dynamic allocation if pool not available
                return torch.randn(
                    shape,
                    dtype=dtype,
                    generator=(batch.generator&#91;0&#93; if isinstance(batch.generator, list) else batch.generator)).to(
                        latents.device)

        current_latents = self._process_single_block(
            current_latents=current_latents,
            batch=batch,
            start_index=start_index,
            current_num_frames=current_num_frames,
            timesteps=ctx.timesteps,
            ctx=ctx,
            action_kwargs=action_kwargs,
            noise_generator=streaming_noise_generator,
        )

        latents&#91;:, :, start_index:start_index + current_num_frames, :, :&#93; = current_latents

        # Update KV caches with clean context
        self._update_context_cache(
            current_latents=current_latents,
            batch=batch,
            start_index=start_index,
            current_num_frames=current_num_frames,
            ctx=ctx,
            action_kwargs=action_kwargs,
            context_noise=ctx.context_noise,
        )

        # Advance streaming state
        ctx.start_index += current_num_frames
        ctx.block_idx += 1

        return batch

    def streaming_clear(self) -&gt; None:
        self._streaming_initialized = False
        self._streaming_ctx = None

    def verify_input(self, batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; VerificationResult:
        result = VerificationResult()
        result.add_check(&quot;latents&quot;, batch.latents, &#91;V.is_tensor, V.with_dims(5)&#93;)
        result.add_check(&quot;prompt_embeds&quot;, batch.prompt_embeds, V.list_not_empty)
        result.add_check(&quot;image_embeds&quot;, batch.image_embeds, V.is_list)
        result.add_check(&quot;image_latent&quot;, batch.image_latent, V.none_or_tensor_with_dims(5))
        result.add_check(&quot;num_inference_steps&quot;, batch.num_inference_steps, V.positive_int)
        result.add_check(&quot;guidance_scale&quot;, batch.guidance_scale, V.positive_float)
        result.add_check(&quot;eta&quot;, batch.eta, V.non_negative_float)
        result.add_check(&quot;generator&quot;, batch.generator, V.generator_or_list_generators)
        result.add_check(&quot;do_classifier_free_guidance&quot;, batch.do_classifier_free_guidance, V.bool_value)
        result.add_check(&quot;negative_prompt_embeds&quot;, batch.negative_prompt_embeds,
                         lambda x: not batch.do_classifier_free_guidance or V.list_not_empty(x))
        return result</code></pre></details>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.forward"><code>fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.forward</code></h3>
<pre class="doc-signature"><code>forward(batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; ForwardBatch</code></pre>

<details><summary>Source</summary><pre><code>def forward(
    self,
    batch: ForwardBatch,
    fastvideo_args: FastVideoArgs,
) -&gt; ForwardBatch:
    target_dtype = torch.bfloat16
    autocast_enabled = (target_dtype != torch.float32) and not fastvideo_args.disable_autocast

    latent_seq_length = batch.latents.shape&#91;-1&#93; * batch.latents.shape&#91;-2&#93;
    patch_size = self.transformer.patch_size
    patch_ratio = patch_size&#91;-1&#93; * patch_size&#91;-2&#93;
    self.frame_seq_length = latent_seq_length // patch_ratio

    timesteps = torch.tensor(fastvideo_args.pipeline_config.dmd_denoising_steps, dtype=torch.long).cpu()
    if fastvideo_args.pipeline_config.warp_denoising_step:
        scheduler_timesteps = torch.cat((self.scheduler.timesteps.cpu(), torch.tensor(&#91;0&#93;, dtype=torch.float32)))
        timesteps = scheduler_timesteps&#91;1000 - timesteps&#93;
    timesteps = timesteps.to(get_local_torch_device())

    boundary_ratio = getattr(fastvideo_args.pipeline_config.dit_config, &#x27;boundary_ratio&#x27;, None)
    if boundary_ratio is not None:
        boundary_timestep = boundary_ratio * self.scheduler.num_train_timesteps
        high_noise_timesteps = timesteps&#91;timesteps &gt;= boundary_timestep&#93;
    else:
        boundary_timestep = None
        high_noise_timesteps = None

    image_embeds = batch.image_embeds
    if len(image_embeds) &gt; 0:
        assert torch.isnan(image_embeds&#91;0&#93;).sum() == 0
        image_embeds = &#91;image_embed.to(target_dtype) for image_embed in image_embeds&#93;

    # directly set the kwarg.
    image_kwargs = &#123;&quot;encoder_hidden_states_image&quot;: image_embeds&#125;
    pos_cond_kwargs: dict&#91;str, Any&#93; = &#123;&#125;

    assert batch.latents is not None, &quot;latents must be provided&quot;
    latents = batch.latents
    b, c, t, h, w = latents.shape
    prompt_embeds = batch.prompt_embeds
    assert torch.isnan(prompt_embeds&#91;0&#93;).sum() == 0

    kv_cache1 = self._initialize_kv_cache(batch_size=latents.shape&#91;0&#93;, dtype=target_dtype, device=latents.device)
    kv_cache2 = None
    if boundary_timestep is not None:
        kv_cache2 = self._initialize_kv_cache(batch_size=latents.shape&#91;0&#93;,
                                              dtype=target_dtype,
                                              device=latents.device)

    kv_cache_mouse = None
    kv_cache_keyboard = None
    if self.use_action_module:
        kv_cache_mouse, kv_cache_keyboard = self._initialize_action_kv_cache(batch_size=latents.shape&#91;0&#93;,
                                                                             dtype=target_dtype,
                                                                             device=latents.device)

    crossattn_cache = self._initialize_crossattn_cache(
        batch_size=latents.shape&#91;0&#93;,
        max_text_len=257,  # 1 CLS + 256 patch tokens
        dtype=target_dtype,
        device=latents.device)

    if t % self.num_frame_per_block != 0:
        raise ValueError(&quot;num_frames must be divisible by num_frame_per_block for causal denoising&quot;)
    num_blocks = t // self.num_frame_per_block
    block_sizes = &#91;self.num_frame_per_block&#93; * num_blocks
    start_index = 0

    if boundary_timestep is not None:
        block_sizes&#91;0&#93; = 1

    # NOTE: Matrix-Game 2.0 does NOT process the first frame separately.
    # The first frame information is already encoded in batch.image_latent (cond_concat)
    # and will be used by the model via channel concatenation: torch.cat(&#91;x, cond_concat&#93;, dim=1)

    ctx = BlockProcessingContext(
        batch=batch,
        block_idx=0,
        start_index=0,
        kv_cache1=kv_cache1,
        kv_cache2=kv_cache2,
        kv_cache_mouse=kv_cache_mouse,
        kv_cache_keyboard=kv_cache_keyboard,
        crossattn_cache=crossattn_cache,
        timesteps=timesteps,
        block_sizes=block_sizes,
        noise_pool=None,
        fastvideo_args=fastvideo_args,
        target_dtype=target_dtype,
        autocast_enabled=autocast_enabled,
        boundary_timestep=boundary_timestep,
        high_noise_timesteps=high_noise_timesteps,
        context_noise=getattr(fastvideo_args.pipeline_config, &quot;context_noise&quot;, 0),
        image_kwargs=image_kwargs,
        pos_cond_kwargs=pos_cond_kwargs,
    )

    context_noise = getattr(fastvideo_args.pipeline_config, &quot;context_noise&quot;, 0)

    with self.progress_bar(total=len(block_sizes) * len(timesteps)) as progress_bar:
        for block_idx, current_num_frames in enumerate(block_sizes):
            ctx.block_idx = block_idx
            ctx.start_index = start_index
            current_latents = latents&#91;:, :, start_index:start_index + current_num_frames, :, :&#93;

            action_kwargs = self._prepare_action_kwargs(batch, start_index, current_num_frames)

            current_latents = self._process_single_block(
                current_latents=current_latents,
                batch=batch,
                start_index=start_index,
                current_num_frames=current_num_frames,
                timesteps=timesteps,
                ctx=ctx,
                action_kwargs=action_kwargs,
                progress_bar=progress_bar,
            )

            latents&#91;:, :, start_index:start_index + current_num_frames, :, :&#93; = current_latents

            # Update KV caches with clean context
            self._update_context_cache(
                current_latents=current_latents,
                batch=batch,
                start_index=start_index,
                current_num_frames=current_num_frames,
                ctx=ctx,
                action_kwargs=action_kwargs,
                context_noise=context_noise,
            )

            start_index += current_num_frames

    if boundary_timestep is not None:
        num_frames_to_remove = self.num_frame_per_block - 1
        if num_frames_to_remove &gt; 0:
            latents = latents&#91;:, :, :-num_frames_to_remove, :, :&#93;

    batch.latents = latents
    return batch</code></pre></details>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.streaming_reset"><code>fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.streaming_reset</code></h3>
<pre class="doc-signature"><code>streaming_reset(batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; ForwardBatch</code></pre>

<details><summary>Source</summary><pre><code>def streaming_reset(self, batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; ForwardBatch:
    target_dtype = torch.bfloat16
    autocast_enabled = (target_dtype != torch.float32) and not fastvideo_args.disable_autocast

    latent_seq_length = batch.latents.shape&#91;-1&#93; * batch.latents.shape&#91;-2&#93;
    patch_size = self.transformer.patch_size
    patch_ratio = patch_size&#91;-1&#93; * patch_size&#91;-2&#93;
    self.frame_seq_length = latent_seq_length // patch_ratio

    timesteps = torch.tensor(fastvideo_args.pipeline_config.dmd_denoising_steps, dtype=torch.long).cpu()
    if fastvideo_args.pipeline_config.warp_denoising_step:
        scheduler_timesteps = torch.cat((self.scheduler.timesteps.cpu(), torch.tensor(&#91;0&#93;, dtype=torch.float32)))
        timesteps = scheduler_timesteps&#91;1000 - timesteps&#93;
    timesteps = timesteps.to(get_local_torch_device())

    boundary_ratio = getattr(fastvideo_args.pipeline_config.dit_config, &#x27;boundary_ratio&#x27;, None)
    if boundary_ratio is not None:
        boundary_timestep = boundary_ratio * self.scheduler.num_train_timesteps
        high_noise_timesteps = timesteps&#91;timesteps &gt;= boundary_timestep&#93;
    else:
        boundary_timestep = None
        high_noise_timesteps = None

    image_embeds = batch.image_embeds
    if len(image_embeds) &gt; 0:
        assert torch.isnan(image_embeds&#91;0&#93;).sum() == 0
        image_embeds = &#91;image_embed.to(target_dtype) for image_embed in image_embeds&#93;

    # directly set the kwarg.
    image_kwargs = &#123;&quot;encoder_hidden_states_image&quot;: image_embeds&#125;
    pos_cond_kwargs: dict&#91;str, Any&#93; = &#123;&#125;

    assert batch.latents is not None, &quot;latents must be provided&quot;
    latents = batch.latents
    b, c, t, h, w = latents.shape
    prompt_embeds = batch.prompt_embeds
    assert torch.isnan(prompt_embeds&#91;0&#93;).sum() == 0

    # Initialize caches
    kv_cache1 = self._initialize_kv_cache(batch_size=latents.shape&#91;0&#93;, dtype=target_dtype, device=latents.device)
    kv_cache2 = None
    if boundary_timestep is not None:
        kv_cache2 = self._initialize_kv_cache(batch_size=latents.shape&#91;0&#93;,
                                              dtype=target_dtype,
                                              device=latents.device)

    kv_cache_mouse = None
    kv_cache_keyboard = None
    if self.use_action_module:
        kv_cache_mouse, kv_cache_keyboard = self._initialize_action_kv_cache(batch_size=latents.shape&#91;0&#93;,
                                                                             dtype=target_dtype,
                                                                             device=latents.device)

    crossattn_cache = self._initialize_crossattn_cache(
        batch_size=latents.shape&#91;0&#93;,
        max_text_len=257,  # 1 CLS + 256 patch tokens
        dtype=target_dtype,
        device=latents.device)

    # Calculate block sizes
    if t % self.num_frame_per_block != 0:
        raise ValueError(&quot;num_frames must be divisible by num_frame_per_block for causal denoising&quot;)
    num_blocks = t // self.num_frame_per_block
    block_sizes = &#91;self.num_frame_per_block&#93; * num_blocks
    if boundary_timestep is not None:
        block_sizes&#91;0&#93; = 1

    # Pre-allocate noise pool
    num_denoising_steps = len(timesteps)
    noise_shape = (b, self.num_frame_per_block, c, h, w)
    noise_pool = &#91;
        torch.randn(
            noise_shape,
            dtype=target_dtype,
            device=latents.device,
        ) for _ in range(num_denoising_steps - 1)
    &#93;

    # Create and store context
    self._streaming_ctx = BlockProcessingContext(
        batch=batch,
        block_idx=0,
        start_index=0,
        kv_cache1=kv_cache1,
        kv_cache2=kv_cache2,
        kv_cache_mouse=kv_cache_mouse,
        kv_cache_keyboard=kv_cache_keyboard,
        crossattn_cache=crossattn_cache,
        timesteps=timesteps,
        block_sizes=block_sizes,
        noise_pool=noise_pool,
        fastvideo_args=fastvideo_args,
        target_dtype=target_dtype,
        autocast_enabled=autocast_enabled,
        boundary_timestep=boundary_timestep,
        high_noise_timesteps=high_noise_timesteps,
        context_noise=getattr(fastvideo_args.pipeline_config, &quot;context_noise&quot;, 0),
        image_kwargs=image_kwargs,
        pos_cond_kwargs=pos_cond_kwargs,
    )

    self._streaming_initialized = True
    return batch</code></pre></details>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.streaming_step"><code>fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.streaming_step</code></h3>
<pre class="doc-signature"><code>streaming_step(keyboard_action: torch.Tensor | None = None, mouse_action: torch.Tensor | None = None) -&gt; ForwardBatch</code></pre>

<details><summary>Source</summary><pre><code>def streaming_step(self,
                   keyboard_action: torch.Tensor | None = None,
                   mouse_action: torch.Tensor | None = None) -&gt; ForwardBatch:
    if not self._streaming_initialized or self._streaming_ctx is None:
        raise RuntimeError(&quot;Streaming not initialized! Call streaming_reset first.&quot;)

    ctx = self._streaming_ctx
    if ctx.block_idx &gt;= len(ctx.block_sizes):
        return ctx.batch

    batch = ctx.batch
    latents = batch.latents
    assert latents is not None, &quot;latents must be set in batch&quot;

    current_num_frames = ctx.block_sizes&#91;ctx.block_idx&#93;
    start_index = ctx.start_index

    current_latents = latents&#91;:, :, start_index:start_index + current_num_frames, :, :&#93;

    # Update batch with new actions for this block
    if keyboard_action is not None or mouse_action is not None:
        vae_ratio = 4
        start_frame = 0 if start_index == 0 else 1 + vae_ratio * (start_index - 1)

        if keyboard_action is not None:
            n = keyboard_action.shape&#91;1&#93;
            batch.keyboard_cond&#91;:, start_frame:start_frame + n&#93; = keyboard_action.to(batch.keyboard_cond.device)
        if mouse_action is not None:
            n = mouse_action.shape&#91;1&#93;
            batch.mouse_cond&#91;:, start_frame:start_frame + n&#93; = mouse_action.to(batch.mouse_cond.device)

    action_kwargs = self._prepare_action_kwargs(batch, start_index, current_num_frames)

    # Create noise generator that uses pre-allocated noise pool
    def streaming_noise_generator(shape: tuple, dtype: torch.dtype, step_idx: int) -&gt; torch.Tensor:
        if ctx.noise_pool is not None and step_idx &lt; len(ctx.noise_pool):
            return ctx.noise_pool&#91;step_idx&#93;&#91;:, :shape&#91;1&#93;, :, :, :&#93;.to(latents.device)
        else:
            # Fallback to dynamic allocation if pool not available
            return torch.randn(
                shape,
                dtype=dtype,
                generator=(batch.generator&#91;0&#93; if isinstance(batch.generator, list) else batch.generator)).to(
                    latents.device)

    current_latents = self._process_single_block(
        current_latents=current_latents,
        batch=batch,
        start_index=start_index,
        current_num_frames=current_num_frames,
        timesteps=ctx.timesteps,
        ctx=ctx,
        action_kwargs=action_kwargs,
        noise_generator=streaming_noise_generator,
    )

    latents&#91;:, :, start_index:start_index + current_num_frames, :, :&#93; = current_latents

    # Update KV caches with clean context
    self._update_context_cache(
        current_latents=current_latents,
        batch=batch,
        start_index=start_index,
        current_num_frames=current_num_frames,
        ctx=ctx,
        action_kwargs=action_kwargs,
        context_noise=ctx.context_noise,
    )

    # Advance streaming state
    ctx.start_index += current_num_frames
    ctx.block_idx += 1

    return batch</code></pre></details>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.streaming_clear"><code>fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.streaming_clear</code></h3>
<pre class="doc-signature"><code>streaming_clear() -&gt; None</code></pre>

<details><summary>Source</summary><pre><code>def streaming_clear(self) -&gt; None:
    self._streaming_initialized = False
    self._streaming_ctx = None</code></pre></details>
<h3 id="fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.verify_input"><code>fastvideo.pipelines.stages.matrixgame2_denoising.MatrixGame2CausalDenoisingStage.verify_input</code></h3>
<pre class="doc-signature"><code>verify_input(batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; VerificationResult</code></pre>

<details><summary>Source</summary><pre><code>def verify_input(self, batch: ForwardBatch, fastvideo_args: FastVideoArgs) -&gt; VerificationResult:
    result = VerificationResult()
    result.add_check(&quot;latents&quot;, batch.latents, &#91;V.is_tensor, V.with_dims(5)&#93;)
    result.add_check(&quot;prompt_embeds&quot;, batch.prompt_embeds, V.list_not_empty)
    result.add_check(&quot;image_embeds&quot;, batch.image_embeds, V.is_list)
    result.add_check(&quot;image_latent&quot;, batch.image_latent, V.none_or_tensor_with_dims(5))
    result.add_check(&quot;num_inference_steps&quot;, batch.num_inference_steps, V.positive_int)
    result.add_check(&quot;guidance_scale&quot;, batch.guidance_scale, V.positive_float)
    result.add_check(&quot;eta&quot;, batch.eta, V.non_negative_float)
    result.add_check(&quot;generator&quot;, batch.generator, V.generator_or_list_generators)
    result.add_check(&quot;do_classifier_free_guidance&quot;, batch.do_classifier_free_guidance, V.bool_value)
    result.add_check(&quot;negative_prompt_embeds&quot;, batch.negative_prompt_embeds,
                     lambda x: not batch.do_classifier_free_guidance or V.list_not_empty(x))
    return result</code></pre></details>
</div>
