Skip to content
FastVideo
Esc
↑↓navigate↵open⌘Jpreview
On this page

model

fastvideo.models.dits.matrixgame2.model.DistributedAttention

DistributedAttention(num_heads: int, head_size: int, num_kv_heads: int | None = None, softmax_scale: float | None = None, causal: bool = False, supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None, prefix: str = '', **extra_impl_args)

Distributed attention layer.

fastvideo.models.dits.matrixgame2.model.DistributedAttention.forward

forward(q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, original_seq_len: int | None = None, replicated_q: torch.Tensor | None = None, replicated_k: torch.Tensor | None = None, replicated_v: torch.Tensor | None = None, freqs_cis: tuple[torch.Tensor, torch.Tensor] | None = None, attn_metadata: AttentionMetadata | None = None) -> tuple[torch.Tensor, torch.Tensor | None]

Forward pass for distributed attention.

Parameters

q: torch.Tensor

Query tensor [batch_size, seq_len, num_heads, head_dim]

k: torch.Tensor

Key tensor [batch_size, seq_len, num_heads, head_dim]

v: torch.Tensor

Value tensor [batch_size, seq_len, num_heads, head_dim]

original_seq_len: int

Original (unpadded) full sequence length

replicated_q: Optional[torch.Tensor]

Replicated query tensor, typically for text tokens

replicated_k: Optional[torch.Tensor]

Replicated key tensor

replicated_v: Optional[torch.Tensor]

Replicated value tensor

Returns

tuple[torch.Tensor, torch.Tensor | None]

Tuple[torch.Tensor, Optional[torch.Tensor]]: A tuple containing: - o (torch.Tensor): Output tensor after attention for the main sequence - replicated_o (Optional[torch.Tensor]): Output tensor for replicated tokens, if provided

fastvideo.models.dits.matrixgame2.model.MatrixGame2WanVideoConfig

MatrixGame2WanVideoConfig(arch_config: MatrixGame2WanVideoArchConfig = MatrixGame2WanVideoArchConfig(), prefix: str = 'Wan', quant_config: QuantizationConfig | None = None, _compile_conditions: list = (lambda: [_is_transformer_block])(), *, _resolved_attention_backend: AttentionBackendEnum | None = None)

fastvideo.models.dits.matrixgame2.model.get_sp_world_size

get_sp_world_size() -> int

Return world size for the sequence model parallel group.

fastvideo.models.dits.matrixgame2.model.FP32LayerNorm

FP32LayerNorm()

fastvideo.models.dits.matrixgame2.model.FP32LayerNorm.forward

forward(inputs: torch.Tensor) -> torch.Tensor

fastvideo.models.dits.matrixgame2.model.LayerNormScaleShift

LayerNormScaleShift(hidden_size: int, norm_type: str = 'rms', eps: float = 1e-06, elementwise_affine: bool = False, dtype: torch.dtype = torch.float32, compute_dtype: torch.dtype | None = None, prefix: str = '')

Fused operation that combines LayerNorm with scale and shift operations. This reduces memory bandwidth by combining memory-bound operations.

fastvideo.models.dits.matrixgame2.model.LayerNormScaleShift.forward

forward(x: torch.Tensor, shift: torch.Tensor, scale: torch.Tensor, convert_modulation_dtype: bool = False) -> torch.Tensor

Apply ln followed by scale and shift in a single fused operation.

fastvideo.models.dits.matrixgame2.model.RMSNorm

RMSNorm(hidden_size: int, eps: float = 1e-06, dtype: torch.dtype = torch.float32, var_hidden_size: int | None = None, has_weight: bool = True)

Root mean square normalization.

Computes x -> w * x / sqrt(E[x^2] + eps) where w is the learned weight. Refer to https://arxiv.org/abs/1910.07467

fastvideo.models.dits.matrixgame2.model.RMSNorm.forward_native

forward_native(x: torch.Tensor, residual: torch.Tensor | None = None) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]

PyTorch-native implementation equivalent to forward().

fastvideo.models.dits.matrixgame2.model.RMSNorm.extra_repr

extra_repr() -> str

fastvideo.models.dits.matrixgame2.model.ScaleResidual

ScaleResidual(prefix: str = '')

Applies gated residual connection.

fastvideo.models.dits.matrixgame2.model.ScaleResidual.forward

forward(residual: torch.Tensor, x: torch.Tensor, gate: torch.Tensor) -> torch.Tensor

Apply gated residual connection.

fastvideo.models.dits.matrixgame2.model.ScaleResidualLayerNormScaleShift

ScaleResidualLayerNormScaleShift(hidden_size: int, norm_type: str = 'rms', eps: float = 1e-06, elementwise_affine: bool = False, dtype: torch.dtype = torch.float32, compute_dtype: torch.dtype | None = None, prefix: str = '', fuse_inference: bool = False)

Fused operation that combines: 1. Gated residual connection 2. LayerNorm 3. Scale and shift operations

This reduces memory bandwidth by combining memory-bound operations.

fastvideo.models.dits.matrixgame2.model.ScaleResidualLayerNormScaleShift.forward

forward(residual: torch.Tensor, x: torch.Tensor, gate: torch.Tensor | int, shift: torch.Tensor | None, scale: torch.Tensor | None, convert_modulation_dtype: bool = False) -> tuple[torch.Tensor, torch.Tensor]

Apply gated residual connection, followed by layernorm and scale/shift in a single fused operation.

Pass shift=None, scale=None (both, not just one) to skip the modulation entirely and return the normalized tensor as-is. Callers that need norm-only behavior (e.g. Wan's post-self-attn site) would otherwise pay two full-tensor elementwise passes computing normalized * (1.0 + 0) + 0.

Returns

torch.Tensor

Tuple containing:

torch.Tensor
  • normalized and modulated output
tuple[torch.Tensor, torch.Tensor]
  • residual value (value after residual connection but before normalization)

fastvideo.models.dits.matrixgame2.model.ReplicatedLinear

ReplicatedLinear(input_size: int, output_size: int, bias: bool = True, skip_bias_add: bool = False, params_dtype: torch.dtype | None = None, quant_config: QuantizationConfig | None = None, prefix: str = '')

Replicated linear layer.

Parameters

input_size: int

input dimension of the linear layer.

output_size: int

output dimension of the linear layer.

bias: bool

If true, add bias.

skip_bias_add: bool

If true, skip adding bias but instead return it.

params_dtype: torch.dtype | None

Data type for the parameters.

quant_config: QuantizationConfig | None

Quantization configure.

prefix: str

The name of the layer in the state dict, including all parents (e.g. model.layers.0.qkv_proj)

fastvideo.models.dits.matrixgame2.model.ReplicatedLinear.weight_loader

weight_loader(param: Parameter, loaded_weight: torch.Tensor) -> None

fastvideo.models.dits.matrixgame2.model.ReplicatedLinear.forward

forward(x: torch.Tensor) -> tuple[torch.Tensor, Parameter | None]

fastvideo.models.dits.matrixgame2.model.ReplicatedLinear.extra_repr

extra_repr() -> str

fastvideo.models.dits.matrixgame2.model.ReplicatedLinear.get_shape_mapping

get_shape_mapping() -> dict

Get the mapping from (input_shape, output_shape) to layer types.

fastvideo.models.dits.matrixgame2.model.ReplicatedLinear.reset_shape_tracking

reset_shape_tracking() -> None

Clear tracked shapes and layer type mappings.

fastvideo.models.dits.matrixgame2.model.ReplicatedLinear.print_shape_summary

print_shape_summary() -> None

Log a summary of all unique shapes and their layer types.

fastvideo.models.dits.matrixgame2.model.MLP

MLP(input_dim: int, mlp_hidden_dim: int, output_dim: int | None = None, bias: bool = True, act_type: str = 'gelu_pytorch_tanh', dtype: torch.dtype | None = None, prefix: str = '', quant_config: QuantizationConfig | None = None)

MLP for DiT blocks, NO gated linear units

fastvideo.models.dits.matrixgame2.model.MLP.forward

forward(x: torch.Tensor) -> torch.Tensor

fastvideo.models.dits.matrixgame2.model.get_rotary_pos_embed

get_rotary_pos_embed(rope_sizes, hidden_size, heads_num, rope_dim_list, rope_theta, theta_rescale_factor = 1.0, interpolation_factor = 1.0, shard_dim: int = 0, do_sp_sharding: bool = False, dtype: torch.dtype = torch.float32, start_frame: int = 0, use_real: bool = True) -> tuple[torch.Tensor, torch.Tensor]

Generate rotary positional embeddings for the given sizes.

Parameters

rope_sizes

Tuple of dimensions (t, h, w)

hidden_size

Hidden dimension size

heads_num

Number of attention heads

rope_dim_list

List of dimensions for each axis, or None

rope_theta

Base for frequency calculations

theta_rescale_factor

Rescale factor for theta. Defaults to 1.0

interpolation_factor

Factor to scale positions. Defaults to 1.0

shard_dim: int

Which dimension to shard for sequence parallelism. Defaults to 0.

do_sp_sharding: bool

Whether to shard the positional embeddings for sequence parallelism. Defaults to False.

use_real: bool

If True, output full head_dim for rotate_half style RoPE. Defaults to True.

Returns

tuple[torch.Tensor, torch.Tensor]

Tuple of (cos, sin) tensors for rotary embeddings. Shape [S, D] if use_real, [S, D/2] otherwise.

fastvideo.models.dits.matrixgame2.model.PatchEmbed

PatchEmbed(patch_size = 16, in_chans = 3, embed_dim = 768, norm_layer = None, flatten = True, bias = True, dtype = None, prefix: str = '')

2D Image to Patch Embedding

Image to Patch Embedding using Conv2d

A convolution based approach to patchifying a 2D image w/ embedding projection.

Based on the impl in https://github.com/google-research/vision_transformer

Hacked together by / Copyright 2020 Ross Wightman

Remove the _assert function in forward function to be compatible with multi-resolution images.

fastvideo.models.dits.matrixgame2.model.PatchEmbed.forward

forward(x)

fastvideo.models.dits.matrixgame2.model.TimestepEmbedder

TimestepEmbedder(hidden_size, act_layer = 'silu', frequency_embedding_size = 256, max_period = 10000, dtype = None, freq_dtype = torch.float32, prefix: str = '')

Embeds scalar timesteps into vector representations.

fastvideo.models.dits.matrixgame2.model.TimestepEmbedder.forward

forward(t: torch.Tensor, timestep_seq_len: int | None = None) -> torch.Tensor

fastvideo.models.dits.matrixgame2.model.ModulateProjection

ModulateProjection(hidden_size: int, factor: int = 2, act_layer: str = 'silu', dtype: torch.dtype | None = None, prefix: str = '')

Modulation layer for DiT blocks.

fastvideo.models.dits.matrixgame2.model.ModulateProjection.forward

forward(x: torch.Tensor) -> torch.Tensor

fastvideo.models.dits.matrixgame2.model.init_logger

init_logger(name: str) -> _FastvideoLogger

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.

fastvideo.models.dits.matrixgame2.model.BaseDiT

BaseDiT(config: DiTConfig, hf_config: dict[str, Any], **kwargs)

fastvideo.models.dits.matrixgame2.model.BaseDiT.forward

forward(hidden_states: torch.Tensor, encoder_hidden_states: torch.Tensor | list[torch.Tensor], timestep: torch.LongTensor, encoder_hidden_states_image: torch.Tensor | list[torch.Tensor] | None = None, guidance = None, **kwargs) -> torch.Tensor

fastvideo.models.dits.matrixgame2.model.BaseDiT.preprocess_loaded_weight

preprocess_loaded_weight(name: str, tensor: torch.Tensor) -> torch.Tensor

Adapt a checkpoint tensor before sharding; default models are unchanged.

fastvideo.models.dits.matrixgame2.model.BaseDiT.inference_config_overrides

inference_config_overrides() -> dict[str, Any]

Extra config.json keys a deployable checkpoint of this model needs.

fastvideo.models.dits.matrixgame2.model.BaseDiT.inference_export_expected_shape

inference_export_expected_shape(output_key: str, base_shape: tuple[int, ...]) -> tuple[int, ...]

The exported shape of output_key given the base checkpoint's shape.

fastvideo.models.dits.matrixgame2.model.WanSelfAttention

WanSelfAttention(dim: int, num_heads: int, window_size = (-1, -1), qk_norm = True, eps = 1e-06, parallel_attention = False, quant_config: QuantizationConfig | None = None, prefix: str = '')

fastvideo.models.dits.matrixgame2.model.WanSelfAttention.forward

forward(x: torch.Tensor, context: torch.Tensor, context_lens: int)

Parameters

x: Tensor

Shape [B, L, num_heads, C / num_heads]

seq_lens: Tensor

Shape [B]

grid_sizes: Tensor

Shape [B, 3], the second dimension contains (F, H, W)

freqs: Tensor

Rope freqs, shape [1024, C / num_heads / 2]

fastvideo.models.dits.matrixgame2.model.WanI2VCrossAttention

WanI2VCrossAttention(dim: int, num_heads: int, window_size = (-1, -1), qk_norm = True, eps = 1e-06, supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None, quant_config: QuantizationConfig | None = None, prefix: str = '')

fastvideo.models.dits.matrixgame2.model.WanI2VCrossAttention.forward

forward(x, context, context_lens)

Parameters

x: Tensor

Shape [B, L1, C]

context: Tensor

Shape [B, L2, C]

context_lens: Tensor

Shape [B]

fastvideo.models.dits.matrixgame2.model.WanT2VCrossAttention

WanT2VCrossAttention(dim: int, num_heads: int, window_size = (-1, -1), qk_norm = True, eps = 1e-06, parallel_attention = False, quant_config: QuantizationConfig | None = None, prefix: str = '')

fastvideo.models.dits.matrixgame2.model.WanT2VCrossAttention.forward

forward(x, context, context_lens, crossattn_cache = None)

Parameters

x: Tensor

Shape [B, L1, C]

context: Tensor

Shape [B, L2, C]

context_lens: Tensor

Shape [B]

fastvideo.models.dits.matrixgame2.model.WanImageEmbedding

WanImageEmbedding(in_features: int, out_features: int)

fastvideo.models.dits.matrixgame2.model.WanImageEmbedding.forward

forward(encoder_hidden_states_image: torch.Tensor) -> torch.Tensor

fastvideo.models.dits.matrixgame2.model.AttentionBackendEnum

AttentionBackendEnum()

fastvideo.models.dits.matrixgame2.model.ActionModule

ActionModule(mouse_dim_in: int = 2, keyboard_dim_in: int = 6, hidden_size: int = 128, img_hidden_size: int = 1536, keyboard_hidden_dim: int = 1024, mouse_hidden_dim: int = 1024, vae_time_compression_ratio: int = 4, windows_size: int = 3, heads_num: int = 16, patch_size: list | None = None, qk_norm: bool = True, qkv_bias: bool = False, rope_dim_list: list | None = None, rope_theta = 256, mouse_qk_dim_list: list | None = None, enable_mouse = True, enable_keyboard = True, local_attn_size = 6, sink_size = 0, blocks: list | None = None)

action module from https://arxiv.org/pdf/2501.08325

fastvideo.models.dits.matrixgame2.model.ActionModule.patchify

patchify(x, patch_size)

x : (N C T H W)

fastvideo.models.dits.matrixgame2.model.ActionModule.unpatchify

unpatchify(x, t, h, w, patch_size)

x: (N, T, patch_size**2 * C) imgs: (N, H, W, C)

fastvideo.models.dits.matrixgame2.model.ActionModule.get_rotary_pos_embed

get_rotary_pos_embed(video_length, height, width, head_dim, rope_dim_list = None, start_offset = 0)

fastvideo.models.dits.matrixgame2.model.ActionModule.forward

forward(x: torch.Tensor, tt: int, th: int, tw: int, mouse_condition: torch.Tensor | None = None, keyboard_condition: torch.Tensor | None = None, block_mask_mouse: BlockMask | None = None, block_mask_keyboard: BlockMask | None = None, is_causal: bool = False, kv_cache_mouse: dict[str, torch.Tensor] | None = None, kv_cache_keyboard: dict[str, torch.Tensor] | None = None, start_frame: int = 0, use_rope_keyboard: bool = True, num_frame_per_block: int = 3)

hidden_states: B, ttthtw, C mouse_condition: B, N_frames, C1 keyboard_condition: B, N_frames, C2

fastvideo.models.dits.matrixgame2.model.MatrixGame2TimeImageEmbedding

MatrixGame2TimeImageEmbedding(dim: int, time_freq_dim: int, image_embed_dim: int | None = None)
Source
class MatrixGame2TimeImageEmbedding(nn.Module):
def __init__(
    self,
    dim: int,
    time_freq_dim: int,
    image_embed_dim: int | None = None,
):
    super().__init__()

    self.time_embedder = TimestepEmbedder(dim, frequency_embedding_size=time_freq_dim, act_layer="silu")
    self.time_modulation = ModulateProjection(dim, factor=6, act_layer="silu")

    self.image_embedder = None
    if image_embed_dim is not None:
        self.image_embedder = WanImageEmbedding(image_embed_dim, dim)

def forward(
    self,
    timestep: torch.Tensor,
    encoder_hidden_states: torch.Tensor,  # Kept for interface compatibility
    encoder_hidden_states_image: torch.Tensor | None = None,
    timestep_seq_len: int | None = None,
):
    temb = self.time_embedder(timestep, timestep_seq_len)
    timestep_proj = self.time_modulation(temb)

    # Matrix-Game 2.0 does not use text embeddings, so we ignore encoder_hidden_states

    if encoder_hidden_states_image is not None:
        assert self.image_embedder is not None
        encoder_hidden_states_image = self.image_embedder(encoder_hidden_states_image)

    encoder_hidden_states = torch.zeros(
        (timestep.shape[0], 0, temb.shape[-1]),
        device=temb.device,
        dtype=temb.dtype,
    )

    return (
        temb,
        timestep_proj,
        encoder_hidden_states,
        encoder_hidden_states_image,
    )</code></pre></details>

fastvideo.models.dits.matrixgame2.model.MatrixGame2TimeImageEmbedding.forward

forward(timestep: torch.Tensor, encoder_hidden_states: torch.Tensor, encoder_hidden_states_image: torch.Tensor | None = None, timestep_seq_len: int | None = None)
Source
def forward(
    self,
    timestep: torch.Tensor,
    encoder_hidden_states: torch.Tensor,  # Kept for interface compatibility
    encoder_hidden_states_image: torch.Tensor | None = None,
    timestep_seq_len: int | None = None,
):
    temb = self.time_embedder(timestep, timestep_seq_len)
    timestep_proj = self.time_modulation(temb)
# Matrix-Game 2.0 does not use text embeddings, so we ignore encoder_hidden_states

if encoder_hidden_states_image is not None:
    assert self.image_embedder is not None
    encoder_hidden_states_image = self.image_embedder(encoder_hidden_states_image)

encoder_hidden_states = torch.zeros(
    (timestep.shape&#91;0&#93;, 0, temb.shape&#91;-1&#93;),
    device=temb.device,
    dtype=temb.dtype,
)

return (
    temb,
    timestep_proj,
    encoder_hidden_states,
    encoder_hidden_states_image,
)</code></pre></details>

fastvideo.models.dits.matrixgame2.model.MatrixGame2CrossAttention

MatrixGame2CrossAttention(dim: int, num_heads: int, window_size = (-1, -1), qk_norm = True, eps = 1e-06, parallel_attention = False, quant_config: QuantizationConfig | None = None, prefix: str = '')
Source
class MatrixGame2CrossAttention(WanSelfAttention):
def forward(self, x, context, context_lens=None, crossattn_cache=None):
    r&quot;&quot;&quot;
    Args:
        x(Tensor): Shape &#91;B, L1, C&#93;
        context(Tensor): Shape &#91;B, L2, C&#93; - typically 257 image tokens
        context_lens(Tensor): Shape &#91;B&#93;
        crossattn_cache(dict): Optional cache for k/v during inference
    &quot;&quot;&quot;
    b, n, d = x.size(0), self.num_heads, self.head_dim

    # compute query, key, value
    q = self.norm_q(self.to_q(x)&#91;0&#93;).view(b, -1, n, d)

    if crossattn_cache is not None:
        if not crossattn_cache&#91;&quot;is_init&quot;&#93;:
            crossattn_cache&#91;&quot;is_init&quot;&#93; = True
            k = self.norm_k(self.to_k(context)&#91;0&#93;).view(b, -1, n, d)
            v = self.to_v(context)&#91;0&#93;.view(b, -1, n, d)
            crossattn_cache&#91;&quot;k&quot;&#93; = k
            crossattn_cache&#91;&quot;v&quot;&#93; = v
        else:
            k = crossattn_cache&#91;&quot;k&quot;&#93;
            v = crossattn_cache&#91;&quot;v&quot;&#93;
    else:
        k = self.norm_k(self.to_k(context)&#91;0&#93;).view(b, -1, n, d)
        v = self.to_v(context)&#91;0&#93;.view(b, -1, n, d)

    # compute attention
    x = self.attn(q, k, v)

    # output
    x = x.flatten(2)
    x, _ = self.to_out(x)
    return x</code></pre></details>

fastvideo.models.dits.matrixgame2.model.MatrixGame2CrossAttention.forward

forward(x, context, context_lens = None, crossattn_cache = None)

Parameters

x: Tensor

Shape [B, L1, C]

context: Tensor

Shape [B, L2, C] - typically 257 image tokens

context_lens: Tensor

Shape [B]

crossattn_cache: dict

Optional cache for k/v during inference

Source
def forward(self, x, context, context_lens=None, crossattn_cache=None):
    r"""
    Args:
        x(Tensor): Shape [B, L1, C]
        context(Tensor): Shape [B, L2, C] - typically 257 image tokens
        context_lens(Tensor): Shape [B]
        crossattn_cache(dict): Optional cache for k/v during inference
    """
    b, n, d = x.size(0), self.num_heads, self.head_dim
# compute query, key, value
q = self.norm_q(self.to_q(x)&#91;0&#93;).view(b, -1, n, d)

if crossattn_cache is not None:
    if not crossattn_cache&#91;&quot;is_init&quot;&#93;:
        crossattn_cache&#91;&quot;is_init&quot;&#93; = True
        k = self.norm_k(self.to_k(context)&#91;0&#93;).view(b, -1, n, d)
        v = self.to_v(context)&#91;0&#93;.view(b, -1, n, d)
        crossattn_cache&#91;&quot;k&quot;&#93; = k
        crossattn_cache&#91;&quot;v&quot;&#93; = v
    else:
        k = crossattn_cache&#91;&quot;k&quot;&#93;
        v = crossattn_cache&#91;&quot;v&quot;&#93;
else:
    k = self.norm_k(self.to_k(context)&#91;0&#93;).view(b, -1, n, d)
    v = self.to_v(context)&#91;0&#93;.view(b, -1, n, d)

# compute attention
x = self.attn(q, k, v)

# output
x = x.flatten(2)
x, _ = self.to_out(x)
return x</code></pre></details>

fastvideo.models.dits.matrixgame2.model.MatrixGame2TransformerBlock

MatrixGame2TransformerBlock(dim: int, ffn_dim: int, num_heads: int, qk_norm: str = 'rms_norm_across_heads', cross_attn_norm: bool = False, eps: float = 1e-06, added_kv_proj_dim: int | None = None, supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None, prefix: str = '', action_config: dict | None = None)
Source
class MatrixGame2TransformerBlock(nn.Module):
def __init__(
    self,
    dim: int,
    ffn_dim: int,
    num_heads: int,
    qk_norm: str = &quot;rms_norm_across_heads&quot;,
    cross_attn_norm: bool = False,
    eps: float = 1e-6,
    added_kv_proj_dim: int | None = None,
    supported_attention_backends: tuple&#91;AttentionBackendEnum, ...&#93;
    | None = None,
    prefix: str = &quot;&quot;,
    action_config: dict | None = None,
):
    super().__init__()
    action_config = action_config or &#123;&#125;

    # 1. Self-attention
    self.norm1 = FP32LayerNorm(dim, eps, elementwise_affine=False)
    self.to_q = ReplicatedLinear(dim, dim, bias=True)
    self.to_k = ReplicatedLinear(dim, dim, bias=True)
    self.to_v = ReplicatedLinear(dim, dim, bias=True)

    self.to_out = ReplicatedLinear(dim, dim, bias=True)
    self.attn1 = DistributedAttention(
        num_heads=num_heads,
        head_size=dim // num_heads,
        causal=False,
        supported_attention_backends=supported_attention_backends,
        prefix=f&quot;&#123;prefix&#125;.attn1&quot;,
    )
    self.hidden_dim = dim
    self.num_attention_heads = num_heads
    dim_head = dim // num_heads
    if qk_norm == &quot;rms_norm&quot;:
        self.norm_q = RMSNorm(dim_head, eps=eps)
        self.norm_k = RMSNorm(dim_head, eps=eps)
    elif qk_norm == &quot;rms_norm_across_heads&quot;:
        # LTX applies qk norm across all heads
        self.norm_q = RMSNorm(dim, eps=eps)
        self.norm_k = RMSNorm(dim, eps=eps)
    else:
        print(&quot;QK Norm type not supported&quot;)
        raise Exception
    assert cross_attn_norm is True
    self.self_attn_residual_norm = ScaleResidualLayerNormScaleShift(
        dim,
        norm_type=&quot;layer&quot;,
        eps=eps,
        elementwise_affine=True,
        dtype=torch.float32,
        compute_dtype=torch.float32,
    )

    # 2. Cross-attention
    if added_kv_proj_dim is not None:
        # I2V
        self.attn2 = WanI2VCrossAttention(dim, num_heads, qk_norm=qk_norm, eps=eps)
    else:
        # T2V
        self.attn2 = WanT2VCrossAttention(dim, num_heads, qk_norm=qk_norm, eps=eps)
    self.cross_attn_residual_norm = ScaleResidualLayerNormScaleShift(
        dim,
        norm_type=&quot;layer&quot;,
        eps=eps,
        elementwise_affine=False,
        dtype=torch.float32,
        compute_dtype=torch.float32,
    )

    # 2.1. Action Module Integration
    self.use_action_module = len(action_config) &gt; 0
    if self.use_action_module:
        self.action_model = ActionModule(**action_config)
    else:
        self.action_model = None

    # 3. Feed-forward
    self.ffn = MLP(dim, ffn_dim, act_type=&quot;gelu_pytorch_tanh&quot;)
    self.mlp_residual = ScaleResidual()

    self.scale_shift_table = nn.Parameter(torch.randn(1, 6, dim) / dim**0.5)

def forward(
    self,
    hidden_states: torch.Tensor,
    encoder_hidden_states: torch.Tensor,
    temb: torch.Tensor,
    freqs_cis: tuple&#91;torch.Tensor, torch.Tensor&#93;,
    # Action Module specific args
    grid_sizes: torch.Tensor,
    mouse_cond: torch.Tensor | None = None,
    keyboard_cond: torch.Tensor | None = None,
) -&gt; torch.Tensor:
    if hidden_states.dim() == 4:
        hidden_states = hidden_states.squeeze(1)
    orig_dtype = hidden_states.dtype

    if temb.dim() == 4:
        # temb: batch_size, seq_len, 6, inner_dim (wan2.2 ti2v)
        (
            shift_msa,
            scale_msa,
            gate_msa,
            c_shift_msa,
            c_scale_msa,
            c_gate_msa,
        ) = (self.scale_shift_table.unsqueeze(0) + temb.float()).chunk(6, dim=2)
        # batch_size, seq_len, 1, inner_dim
        shift_msa = shift_msa.squeeze(2)
        scale_msa = scale_msa.squeeze(2)
        gate_msa = gate_msa.squeeze(2)
        c_shift_msa = c_shift_msa.squeeze(2)
        c_scale_msa = c_scale_msa.squeeze(2)
        c_gate_msa = c_gate_msa.squeeze(2)
    else:
        # temb: batch_size, 6, inner_dim (wan2.1/wan2.2 14B)
        e = self.scale_shift_table + temb.float()
        (
            shift_msa,
            scale_msa,
            gate_msa,
            c_shift_msa,
            c_scale_msa,
            c_gate_msa,
        ) = e.chunk(6, dim=1)
    assert shift_msa.dtype == torch.float32

    # 1. Self-attention
    norm_hidden_states = (self.norm1(hidden_states.float()) * (1 + scale_msa) + shift_msa).to(orig_dtype)
    query, _ = self.to_q(norm_hidden_states)
    key, _ = self.to_k(norm_hidden_states)
    value, _ = self.to_v(norm_hidden_states)

    if self.norm_q is not None:
        query = self.norm_q(query)
    if self.norm_k is not None:
        key = self.norm_k(key)

    query = query.squeeze(1).unflatten(2, (self.num_attention_heads, -1))
    key = key.squeeze(1).unflatten(2, (self.num_attention_heads, -1))
    value = value.squeeze(1).unflatten(2, (self.num_attention_heads, -1))

    # Apply rotary embeddings
    cos, sin = freqs_cis
    query, key = (
        _apply_rotary_emb(query, cos, sin, is_neox_style=False),
        _apply_rotary_emb(key, cos, sin, is_neox_style=False),
    )

    attn_output, _ = self.attn1(query, key, value)
    attn_output = attn_output.flatten(2)
    attn_output, _ = self.to_out(attn_output)
    attn_output = attn_output.squeeze(1)

    null_shift = null_scale = torch.tensor(&#91;0&#93;, device=hidden_states.device)
    norm_hidden_states, hidden_states = self.self_attn_residual_norm(hidden_states, attn_output, gate_msa,
                                                                     null_shift, null_scale)
    norm_hidden_states, hidden_states = (
        norm_hidden_states.to(orig_dtype),
        hidden_states.to(orig_dtype),
    )

    # 2. Cross-attention
    attn_output = self.attn2(norm_hidden_states, context=encoder_hidden_states, context_lens=None)
    norm_hidden_states, hidden_states = self.cross_attn_residual_norm(hidden_states, attn_output, 1, c_shift_msa,
                                                                      c_scale_msa)
    norm_hidden_states, hidden_states = (
        norm_hidden_states.to(orig_dtype),
        hidden_states.to(orig_dtype),
    )

    # ================= Action Module =================
    if self.action_model is not None:
        if mouse_cond is not None or keyboard_cond is not None:
            # grid_sizes is expected to be &#91;F, H, W&#93;
            # ActionModule implementation takes hidden_states directly
            hidden_states = self.action_model(
                hidden_states,
                int(grid_sizes&#91;0&#93;),
                int(grid_sizes&#91;1&#93;),
                int(grid_sizes&#91;2&#93;),
                mouse_cond,
                keyboard_cond,
                num_frame_per_block=int(grid_sizes&#91;0&#93;),
            )
    # =================================================

    # 3. Feed-forward
    ff_output = self.ffn(norm_hidden_states)
    hidden_states = self.mlp_residual(hidden_states, ff_output, c_gate_msa)
    hidden_states = hidden_states.to(orig_dtype)

    return hidden_states</code></pre></details>

fastvideo.models.dits.matrixgame2.model.MatrixGame2TransformerBlock.forward

forward(hidden_states: torch.Tensor, encoder_hidden_states: torch.Tensor, temb: torch.Tensor, freqs_cis: tuple[torch.Tensor, torch.Tensor], grid_sizes: torch.Tensor, mouse_cond: torch.Tensor | None = None, keyboard_cond: torch.Tensor | None = None) -> torch.Tensor
Source
def forward(
    self,
    hidden_states: torch.Tensor,
    encoder_hidden_states: torch.Tensor,
    temb: torch.Tensor,
    freqs_cis: tuple[torch.Tensor, torch.Tensor],
    # Action Module specific args
    grid_sizes: torch.Tensor,
    mouse_cond: torch.Tensor | None = None,
    keyboard_cond: torch.Tensor | None = None,
) -> torch.Tensor:
    if hidden_states.dim() == 4:
        hidden_states = hidden_states.squeeze(1)
    orig_dtype = hidden_states.dtype
if temb.dim() == 4:
    # temb: batch_size, seq_len, 6, inner_dim (wan2.2 ti2v)
    (
        shift_msa,
        scale_msa,
        gate_msa,
        c_shift_msa,
        c_scale_msa,
        c_gate_msa,
    ) = (self.scale_shift_table.unsqueeze(0) + temb.float()).chunk(6, dim=2)
    # batch_size, seq_len, 1, inner_dim
    shift_msa = shift_msa.squeeze(2)
    scale_msa = scale_msa.squeeze(2)
    gate_msa = gate_msa.squeeze(2)
    c_shift_msa = c_shift_msa.squeeze(2)
    c_scale_msa = c_scale_msa.squeeze(2)
    c_gate_msa = c_gate_msa.squeeze(2)
else:
    # temb: batch_size, 6, inner_dim (wan2.1/wan2.2 14B)
    e = self.scale_shift_table + temb.float()
    (
        shift_msa,
        scale_msa,
        gate_msa,
        c_shift_msa,
        c_scale_msa,
        c_gate_msa,
    ) = e.chunk(6, dim=1)
assert shift_msa.dtype == torch.float32

# 1. Self-attention
norm_hidden_states = (self.norm1(hidden_states.float()) * (1 + scale_msa) + shift_msa).to(orig_dtype)
query, _ = self.to_q(norm_hidden_states)
key, _ = self.to_k(norm_hidden_states)
value, _ = self.to_v(norm_hidden_states)

if self.norm_q is not None:
    query = self.norm_q(query)
if self.norm_k is not None:
    key = self.norm_k(key)

query = query.squeeze(1).unflatten(2, (self.num_attention_heads, -1))
key = key.squeeze(1).unflatten(2, (self.num_attention_heads, -1))
value = value.squeeze(1).unflatten(2, (self.num_attention_heads, -1))

# Apply rotary embeddings
cos, sin = freqs_cis
query, key = (
    _apply_rotary_emb(query, cos, sin, is_neox_style=False),
    _apply_rotary_emb(key, cos, sin, is_neox_style=False),
)

attn_output, _ = self.attn1(query, key, value)
attn_output = attn_output.flatten(2)
attn_output, _ = self.to_out(attn_output)
attn_output = attn_output.squeeze(1)

null_shift = null_scale = torch.tensor(&#91;0&#93;, device=hidden_states.device)
norm_hidden_states, hidden_states = self.self_attn_residual_norm(hidden_states, attn_output, gate_msa,
                                                                 null_shift, null_scale)
norm_hidden_states, hidden_states = (
    norm_hidden_states.to(orig_dtype),
    hidden_states.to(orig_dtype),
)

# 2. Cross-attention
attn_output = self.attn2(norm_hidden_states, context=encoder_hidden_states, context_lens=None)
norm_hidden_states, hidden_states = self.cross_attn_residual_norm(hidden_states, attn_output, 1, c_shift_msa,
                                                                  c_scale_msa)
norm_hidden_states, hidden_states = (
    norm_hidden_states.to(orig_dtype),
    hidden_states.to(orig_dtype),
)

# ================= Action Module =================
if self.action_model is not None:
    if mouse_cond is not None or keyboard_cond is not None:
        # grid_sizes is expected to be &#91;F, H, W&#93;
        # ActionModule implementation takes hidden_states directly
        hidden_states = self.action_model(
            hidden_states,
            int(grid_sizes&#91;0&#93;),
            int(grid_sizes&#91;1&#93;),
            int(grid_sizes&#91;2&#93;),
            mouse_cond,
            keyboard_cond,
            num_frame_per_block=int(grid_sizes&#91;0&#93;),
        )
# =================================================

# 3. Feed-forward
ff_output = self.ffn(norm_hidden_states)
hidden_states = self.mlp_residual(hidden_states, ff_output, c_gate_msa)
hidden_states = hidden_states.to(orig_dtype)

return hidden_states</code></pre></details>

fastvideo.models.dits.matrixgame2.model.MatrixGame2WanModel

MatrixGame2WanModel(config: MatrixGame2WanVideoConfig, hf_config: dict[str, Any], **kwargs)
Source
class MatrixGame2WanModel(BaseDiT):
    # Marker for action input support (Matrix-Game)
    supports_action_input = True
_fsdp_shard_conditions = _DEFAULT_MATRIXGAME2_CONFIG._fsdp_shard_conditions
_compile_conditions = _DEFAULT_MATRIXGAME2_CONFIG._compile_conditions
_supported_attention_backends = (_DEFAULT_MATRIXGAME2_CONFIG._supported_attention_backends)
param_names_mapping = _DEFAULT_MATRIXGAME2_CONFIG.param_names_mapping
reverse_param_names_mapping = (_DEFAULT_MATRIXGAME2_CONFIG.reverse_param_names_mapping)
lora_param_names_mapping = (_DEFAULT_MATRIXGAME2_CONFIG.lora_param_names_mapping)

def __init__(
    self,
    config: MatrixGame2WanVideoConfig,
    hf_config: dict&#91;str, Any&#93;,
    **kwargs,
) -&gt; None:
    super().__init__(config=config, hf_config=hf_config)

    inner_dim = config.num_attention_heads * config.attention_head_dim
    self.hidden_size = config.hidden_size
    self.num_attention_heads = config.num_attention_heads
    self.num_channels_latents = config.out_channels
    self.patch_size = config.patch_size

    # 1. Patch &amp; position embedding
    self.patch_embedding = PatchEmbed(
        in_chans=config.in_channels,
        embed_dim=inner_dim,
        patch_size=config.patch_size,
        flatten=False,
    )

    # 2. Condition embeddings
    self.condition_embedder = MatrixGame2TimeImageEmbedding(
        dim=inner_dim,
        time_freq_dim=config.freq_dim,
        image_embed_dim=config.image_dim,
    )

    # 2.1. Get action config
    self.action_config = getattr(config, &quot;action_config&quot;, &#123;&#125;)

    # 3. Transformer blocks
    self.blocks = nn.ModuleList(&#91;
        MatrixGame2TransformerBlock(
            inner_dim,
            config.ffn_dim,
            config.num_attention_heads,
            config.qk_norm,
            config.cross_attn_norm,
            config.eps,
            config.added_kv_proj_dim,
            self._supported_attention_backends,
            prefix=f&quot;&#123;getattr(config, &#x27;prefix&#x27;, &#x27;Wan&#x27;)&#125;.blocks.&#123;i&#125;&quot;,
            action_config=self.action_config,
        ) for i in range(config.num_layers)
    &#93;)

    # 4. Output norm &amp; projection
    self.norm_out = LayerNormScaleShift(
        inner_dim,
        norm_type=&quot;layer&quot;,
        eps=config.eps,
        elementwise_affine=False,
        dtype=torch.float32,
        compute_dtype=torch.float32,
    )
    self.proj_out = nn.Linear(inner_dim, config.out_channels * math.prod(config.patch_size))
    self.scale_shift_table = nn.Parameter(torch.randn(1, 2, inner_dim) / inner_dim**0.5)

    self.gradient_checkpointing = False

def forward(
    self,
    hidden_states: torch.Tensor,
    encoder_hidden_states: torch.Tensor | list&#91;torch.Tensor&#93;,
    timestep: torch.LongTensor,
    encoder_hidden_states_image: torch.Tensor
    | list&#91;torch.Tensor&#93;
    | None = None,
    # Action inputs
    mouse_cond: torch.Tensor | None = None,
    keyboard_cond: torch.Tensor | None = None,
    **kwargs,
) -&gt; torch.Tensor:
    if encoder_hidden_states is not None and not isinstance(encoder_hidden_states, torch.Tensor):
        encoder_hidden_states = encoder_hidden_states&#91;0&#93;
    if (isinstance(encoder_hidden_states_image, list) and len(encoder_hidden_states_image) &gt; 0):
        encoder_hidden_states_image = encoder_hidden_states_image&#91;0&#93;
    elif not isinstance(encoder_hidden_states_image, torch.Tensor):
        encoder_hidden_states_image = None

    batch_size, num_channels, num_frames, height, width = (hidden_states.shape)
    p_t, p_h, p_w = self.patch_size
    post_patch_num_frames = num_frames // p_t
    post_patch_height = height // p_h
    post_patch_width = width // p_w

    # Get rotary embeddings
    d = self.hidden_size // self.num_attention_heads
    rope_dim_list = &#91;d - 4 * (d // 6), 2 * (d // 6), 2 * (d // 6)&#93;
    freqs_cos, freqs_sin = get_rotary_pos_embed(
        (
            post_patch_num_frames * get_sp_world_size(),
            post_patch_height,
            post_patch_width,
        ),
        self.hidden_size,
        self.num_attention_heads,
        rope_dim_list,
        dtype=torch.float32 if current_platform.is_mps() else torch.float64,
        rope_theta=10000,
        do_sp_sharding=True,
    )
    freqs_cos = freqs_cos.to(hidden_states.device)
    freqs_sin = freqs_sin.to(hidden_states.device)
    freqs_cis = ((freqs_cos.float(), freqs_sin.float()) if freqs_cos is not None else None)

    hidden_states = self.patch_embedding(hidden_states)
    hidden_states = hidden_states.flatten(2).transpose(1, 2)

    if timestep.dim() == 2:
        timestep = timestep.flatten()

    (
        temb,
        timestep_proj,
        encoder_hidden_states,
        encoder_hidden_states_image,
    ) = self.condition_embedder(timestep, encoder_hidden_states, encoder_hidden_states_image)
    timestep_proj = timestep_proj.unflatten(1, (6, -1))

    if encoder_hidden_states is not None:
        if isinstance(encoder_hidden_states, list):
            encoder_hidden_states = encoder_hidden_states&#91;0&#93;
        elif encoder_hidden_states.ndim == 2:
            encoder_hidden_states = encoder_hidden_states.unsqueeze(0)
    else:
        # encoder_hidden_states is None (e.g. no text encoder)
        # Matrix-Game 2.0 uses image-action cross-attn.
        pass

    if encoder_hidden_states_image is not None:
        if encoder_hidden_states is not None:
            encoder_hidden_states = torch.concat(&#91;encoder_hidden_states_image, encoder_hidden_states&#93;, dim=1)
        else:
            encoder_hidden_states = encoder_hidden_states_image

    # This is &#91;F, H, W&#93; for the ActionModule
    grid_sizes = torch.tensor(
        &#91;post_patch_num_frames, post_patch_height, post_patch_width&#93;,
        device=hidden_states.device,
    )

    # Blocks
    for block in self.blocks:
        if torch.is_grad_enabled() and self.gradient_checkpointing:
            hidden_states = self._gradient_checkpointing_func(
                block,
                hidden_states,
                encoder_hidden_states,
                timestep_proj,
                freqs_cis,
                grid_sizes=grid_sizes,
                mouse_cond=mouse_cond,
                keyboard_cond=keyboard_cond,
            )
        else:
            hidden_states = block(
                hidden_states,
                encoder_hidden_states,
                timestep_proj,
                freqs_cis,
                grid_sizes=grid_sizes,
                mouse_cond=mouse_cond,
                keyboard_cond=keyboard_cond,
            )

    # Output
    shift, scale = (self.scale_shift_table + temb.unsqueeze(1)).chunk(2, dim=1)
    hidden_states = self.norm_out(hidden_states, shift, scale)
    hidden_states = self.proj_out(hidden_states)

    hidden_states = hidden_states.reshape(
        batch_size,
        post_patch_num_frames,
        post_patch_height,
        post_patch_width,
        p_t,
        p_h,
        p_w,
        -1,
    )
    hidden_states = hidden_states.permute(0, 7, 1, 4, 2, 5, 3, 6)
    output = hidden_states.flatten(6, 7).flatten(4, 5).flatten(2, 3)

    return output</code></pre></details>

fastvideo.models.dits.matrixgame2.model.MatrixGame2WanModel.forward

forward(hidden_states: torch.Tensor, encoder_hidden_states: torch.Tensor | list[torch.Tensor], timestep: torch.LongTensor, encoder_hidden_states_image: torch.Tensor | list[torch.Tensor] | None = None, mouse_cond: torch.Tensor | None = None, keyboard_cond: torch.Tensor | None = None, **kwargs) -> torch.Tensor
Source
def forward(
    self,
    hidden_states: torch.Tensor,
    encoder_hidden_states: torch.Tensor | list[torch.Tensor],
    timestep: torch.LongTensor,
    encoder_hidden_states_image: torch.Tensor
    | list[torch.Tensor]
    | None = None,
    # Action inputs
    mouse_cond: torch.Tensor | None = None,
    keyboard_cond: torch.Tensor | None = None,
    **kwargs,
) -> torch.Tensor:
    if encoder_hidden_states is not None and not isinstance(encoder_hidden_states, torch.Tensor):
        encoder_hidden_states = encoder_hidden_states[0]
    if (isinstance(encoder_hidden_states_image, list) and len(encoder_hidden_states_image) > 0):
        encoder_hidden_states_image = encoder_hidden_states_image[0]
    elif not isinstance(encoder_hidden_states_image, torch.Tensor):
        encoder_hidden_states_image = None
batch_size, num_channels, num_frames, height, width = (hidden_states.shape)
p_t, p_h, p_w = self.patch_size
post_patch_num_frames = num_frames // p_t
post_patch_height = height // p_h
post_patch_width = width // p_w

# Get rotary embeddings
d = self.hidden_size // self.num_attention_heads
rope_dim_list = &#91;d - 4 * (d // 6), 2 * (d // 6), 2 * (d // 6)&#93;
freqs_cos, freqs_sin = get_rotary_pos_embed(
    (
        post_patch_num_frames * get_sp_world_size(),
        post_patch_height,
        post_patch_width,
    ),
    self.hidden_size,
    self.num_attention_heads,
    rope_dim_list,
    dtype=torch.float32 if current_platform.is_mps() else torch.float64,
    rope_theta=10000,
    do_sp_sharding=True,
)
freqs_cos = freqs_cos.to(hidden_states.device)
freqs_sin = freqs_sin.to(hidden_states.device)
freqs_cis = ((freqs_cos.float(), freqs_sin.float()) if freqs_cos is not None else None)

hidden_states = self.patch_embedding(hidden_states)
hidden_states = hidden_states.flatten(2).transpose(1, 2)

if timestep.dim() == 2:
    timestep = timestep.flatten()

(
    temb,
    timestep_proj,
    encoder_hidden_states,
    encoder_hidden_states_image,
) = self.condition_embedder(timestep, encoder_hidden_states, encoder_hidden_states_image)
timestep_proj = timestep_proj.unflatten(1, (6, -1))

if encoder_hidden_states is not None:
    if isinstance(encoder_hidden_states, list):
        encoder_hidden_states = encoder_hidden_states&#91;0&#93;
    elif encoder_hidden_states.ndim == 2:
        encoder_hidden_states = encoder_hidden_states.unsqueeze(0)
else:
    # encoder_hidden_states is None (e.g. no text encoder)
    # Matrix-Game 2.0 uses image-action cross-attn.
    pass

if encoder_hidden_states_image is not None:
    if encoder_hidden_states is not None:
        encoder_hidden_states = torch.concat(&#91;encoder_hidden_states_image, encoder_hidden_states&#93;, dim=1)
    else:
        encoder_hidden_states = encoder_hidden_states_image

# This is &#91;F, H, W&#93; for the ActionModule
grid_sizes = torch.tensor(
    &#91;post_patch_num_frames, post_patch_height, post_patch_width&#93;,
    device=hidden_states.device,
)

# Blocks
for block in self.blocks:
    if torch.is_grad_enabled() and self.gradient_checkpointing:
        hidden_states = self._gradient_checkpointing_func(
            block,
            hidden_states,
            encoder_hidden_states,
            timestep_proj,
            freqs_cis,
            grid_sizes=grid_sizes,
            mouse_cond=mouse_cond,
            keyboard_cond=keyboard_cond,
        )
    else:
        hidden_states = block(
            hidden_states,
            encoder_hidden_states,
            timestep_proj,
            freqs_cis,
            grid_sizes=grid_sizes,
            mouse_cond=mouse_cond,
            keyboard_cond=keyboard_cond,
        )

# Output
shift, scale = (self.scale_shift_table + temb.unsqueeze(1)).chunk(2, dim=1)
hidden_states = self.norm_out(hidden_states, shift, scale)
hidden_states = self.proj_out(hidden_states)

hidden_states = hidden_states.reshape(
    batch_size,
    post_patch_num_frames,
    post_patch_height,
    post_patch_width,
    p_t,
    p_h,
    p_w,
    -1,
)
hidden_states = hidden_states.permute(0, 7, 1, 4, 2, 5, 3, 6)
output = hidden_states.flatten(6, 7).flatten(4, 5).flatten(2, 3)

return output</code></pre></details>

Was this page helpful?