Skip to content

gen3c

GEN3C is a video-conditioned diffusion model that uses a 3D cache for camera control.

Key Features: - Extends Cosmos 2.5 architecture with video conditioning inputs - condition_video_input_mask: Binary mask indicating conditioning frames - condition_video_pose: VAE-encoded 3D cache buffers (rendered warped images/masks) - Augment sigma embedding for conditioning noise augmentation - 3D RoPE with learnable per-axis positional embeddings

Reference: https://arxiv.org/abs/2503.03751

Classes

fastvideo.models.dits.gen3c.Gen3CAdaLayerNormZero

Gen3CAdaLayerNormZero(in_features: int)

Bases: Module

GEN3C Adaptive Layer Normalization with zero initialization and gate. This is a simplified version that expects pre-computed shift/scale/gate parameters.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    in_features: int,
) -> None:
    super().__init__()
    self.norm = nn.LayerNorm(in_features, elementwise_affine=False, eps=1e-6)

Methods:

fastvideo.models.dits.gen3c.Gen3CAdaLayerNormZero.forward
forward(hidden_states: Tensor, shift: Tensor, scale: Tensor) -> Tensor

Parameters:

Name Type Description Default
hidden_states Tensor

Input tensor

required
shift Tensor

Shift parameter for modulation

required
scale Tensor

Scale parameter for modulation

required

Returns:

Name Type Description
normalized_hidden_states Tensor

Modulated normalized hidden states

Source code in fastvideo/models/dits/gen3c.py
def forward(
    self,
    hidden_states: torch.Tensor,
    shift: torch.Tensor,
    scale: torch.Tensor,
) -> torch.Tensor:
    """
    Args:
        hidden_states: Input tensor
        shift: Shift parameter for modulation
        scale: Scale parameter for modulation

    Returns:
        normalized_hidden_states: Modulated normalized hidden states
    """
    # Apply layer norm and modulation
    hidden_states = self.norm(hidden_states)
    hidden_states = hidden_states * (1 + scale) + shift
    return hidden_states

fastvideo.models.dits.gen3c.Gen3CCrossAttention

Gen3CCrossAttention(dim: int, cross_attention_dim: int, num_heads: int, qk_norm: bool = True, eps: float = 1e-06, supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None)

Bases: Module

GEN3C cross-attention for text conditioning.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    dim: int,
    cross_attention_dim: int,
    num_heads: int,
    qk_norm: bool = True,
    eps: float = 1e-6,
    supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None,
) -> None:
    assert dim % num_heads == 0
    super().__init__()
    self.dim = dim
    self.cross_attention_dim = cross_attention_dim
    self.num_heads = num_heads
    self.head_dim = dim // num_heads

    self.to_q = ReplicatedLinear(dim, dim, bias=False)
    self.to_k = ReplicatedLinear(cross_attention_dim, dim, bias=False)
    self.to_v = ReplicatedLinear(cross_attention_dim, dim, bias=False)
    self.to_out = ReplicatedLinear(dim, dim, bias=False)

    self.norm_q = RMSNorm(self.head_dim, eps=eps) if qk_norm else nn.Identity()
    self.norm_k = RMSNorm(self.head_dim, eps=eps) if qk_norm else nn.Identity()

    if supported_attention_backends is None:
        supported_attention_backends = (AttentionBackendEnum.FLASH_ATTN, AttentionBackendEnum.TORCH_SDPA)

    self.attn = LocalAttention(
        num_heads=num_heads,
        head_size=self.head_dim,
        causal=False,
        supported_attention_backends=supported_attention_backends,
    )

Methods:

fastvideo.models.dits.gen3c.Gen3CCrossAttention.forward
forward(hidden_states: Tensor, encoder_hidden_states: Tensor, attention_mask: Tensor | None = None) -> Tensor

Parameters:

Name Type Description Default
hidden_states Tensor

(B, S, D)

required
encoder_hidden_states Tensor

(B, N, D_text)

required
Source code in fastvideo/models/dits/gen3c.py
def forward(
    self,
    hidden_states: torch.Tensor,
    encoder_hidden_states: torch.Tensor,
    attention_mask: torch.Tensor | None = None,
) -> torch.Tensor:
    """
    Args:
        hidden_states: (B, S, D)
        encoder_hidden_states: (B, N, D_text)
    """
    # Get QKV
    query, _ = self.to_q(hidden_states)
    key, _ = self.to_k(encoder_hidden_states)
    value, _ = self.to_v(encoder_hidden_states)

    # Reshape for multi-head attention
    query = query.unflatten(-1, (self.num_heads, self.head_dim))
    key = key.unflatten(-1, (self.num_heads, self.head_dim))
    value = value.unflatten(-1, (self.num_heads, self.head_dim))

    # Apply QK normalization
    query = self.norm_q(query)
    key = self.norm_k(key)

    attn_output = self.attn(query, key, value)
    attn_output = attn_output.flatten(-2, -1)

    # Output projection
    attn_output, _ = self.to_out(attn_output)
    return attn_output

fastvideo.models.dits.gen3c.Gen3CEmbedding

Gen3CEmbedding(embedding_dim: int, condition_dim: int, use_adaln_lora: bool = True, adaln_lora_dim: int = 256)

Bases: Module

GEN3C timestep conditioning embedding. Generates sinusoidal embeddings and processes them through MLP.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    embedding_dim: int,
    condition_dim: int,
    use_adaln_lora: bool = True,
    adaln_lora_dim: int = 256,
) -> None:
    super().__init__()

    self.time_proj = Timesteps(embedding_dim, flip_sin_to_cos=True, downscale_freq_shift=0.0)
    self.t_embedder = Gen3CTimestepEmbedding(
        embedding_dim,
        condition_dim,
        use_adaln_lora=use_adaln_lora,
        adaln_lora_dim=adaln_lora_dim,
    )

Methods:

fastvideo.models.dits.gen3c.Gen3CEmbedding.forward
forward(timestep: Tensor, dtype: dtype) -> tuple[Tensor, Tensor | None]

Parameters:

Name Type Description Default
timestep Tensor

(B,) tensor of timesteps

required
dtype dtype

Target dtype for embeddings

required

Returns:

Name Type Description
embedded_timestep Tensor

Timestep embedding (B, D)

adaln_lora Tensor | None

AdaLN-LoRA parameters (B, 3D) or None

Source code in fastvideo/models/dits/gen3c.py
def forward(
    self,
    timestep: torch.Tensor,
    dtype: torch.dtype,
) -> tuple[torch.Tensor, torch.Tensor | None]:
    """
    Args:
        timestep: (B,) tensor of timesteps
        dtype: Target dtype for embeddings

    Returns:
        embedded_timestep: Timestep embedding (B, D)
        adaln_lora: AdaLN-LoRA parameters (B, 3D) or None
    """
    # timestep should be 1D (B,)
    timestep = timestep.flatten()
    timesteps_proj = self.time_proj(timestep).to(dtype)  # (B, D)
    embedded_timestep, adaln_lora = self.t_embedder(timesteps_proj)

    return embedded_timestep, adaln_lora

fastvideo.models.dits.gen3c.Gen3CFinalLayer

Gen3CFinalLayer(hidden_size: int, out_channels: int, patch_size: tuple[int, int, int], adaln_lora_dim: int = 256, use_adaln_lora: bool = True)

Bases: Module

GEN3C final layer with AdaLN modulation and unpatchification.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    hidden_size: int,
    out_channels: int,
    patch_size: tuple[int, int, int],
    adaln_lora_dim: int = 256,
    use_adaln_lora: bool = True,
) -> None:
    super().__init__()
    self.hidden_size = hidden_size
    self.use_adaln_lora = use_adaln_lora

    self.norm = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)

    # AdaLN modulation
    if use_adaln_lora:
        self.adaln_modulation = nn.ModuleList([
            nn.SiLU(),
            ReplicatedLinear(hidden_size, adaln_lora_dim, bias=False),
            ReplicatedLinear(adaln_lora_dim, 2 * hidden_size, bias=False),
        ])
    else:
        self.adaln_modulation = nn.ModuleList([
            nn.SiLU(),
            ReplicatedLinear(hidden_size, 2 * hidden_size, bias=False),
        ])

    # Output projection
    output_dim = out_channels * patch_size[0] * patch_size[1] * patch_size[2]
    self.proj_out = ReplicatedLinear(hidden_size,
                                     output_dim,
                                     bias=False)

Methods:

fastvideo.models.dits.gen3c.Gen3CFinalLayer.forward
forward(hidden_states: Tensor, affine_emb: Tensor, adaln_lora: Tensor | None = None) -> Tensor

Parameters:

Name Type Description Default
hidden_states Tensor

(B, T, H, W, D)

required
affine_emb Tensor

(B, D)

required
adaln_lora Tensor | None

(B, 3D) or None

None
Source code in fastvideo/models/dits/gen3c.py
def forward(
    self,
    hidden_states: torch.Tensor,
    affine_emb: torch.Tensor,
    adaln_lora: torch.Tensor | None = None,
) -> torch.Tensor:
    """
    Args:
        hidden_states: (B, T, H, W, D)
        affine_emb: (B, D)
        adaln_lora: (B, 3D) or None
    """
    # Generate modulation parameters
    modulation = _run_linear_stack(self.adaln_modulation, affine_emb)

    if self.use_adaln_lora and adaln_lora is not None:
        modulation = modulation + adaln_lora[..., : 2 * self.hidden_size]

    shift, scale = modulation.chunk(2, dim=-1)

    # Apply normalization and modulation
    hidden_states = self.norm(hidden_states)

    # Broadcast over all non-channel dimensions. Supports both:
    # - (B, T, H, W, D)
    # - (B, S, D) when sequence-parallel path is active.
    mod_shape = [hidden_states.shape[0]] + [1] * (hidden_states.dim() - 2) + [self.hidden_size]
    shift = shift.view(*mod_shape)
    scale = scale.view(*mod_shape)

    hidden_states = hidden_states * (1 + scale) + shift

    # Project to output
    hidden_states, _ = self.proj_out(hidden_states)

    return hidden_states

fastvideo.models.dits.gen3c.Gen3CLearnablePositionalEmbed

Gen3CLearnablePositionalEmbed(hidden_size: int, max_size: tuple[int, int, int], patch_size: tuple[int, int, int], eps: float = 1e-06)

Bases: Module

GEN3C learnable absolute positional embeddings.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    hidden_size: int,
    max_size: tuple[int, int, int],
    patch_size: tuple[int, int, int],
    eps: float = 1e-6,
) -> None:
    super().__init__()

    self.max_size = [size // patch for size, patch in zip(max_size, patch_size, strict=True)]
    self.patch_size = patch_size
    self.eps = eps

    self.pos_emb_t = nn.Parameter(torch.zeros(self.max_size[0], hidden_size))
    self.pos_emb_h = nn.Parameter(torch.zeros(self.max_size[1], hidden_size))
    self.pos_emb_w = nn.Parameter(torch.zeros(self.max_size[2], hidden_size))

Methods:

fastvideo.models.dits.gen3c.Gen3CLearnablePositionalEmbed.forward
forward(hidden_states: Tensor) -> Tensor

Parameters:

Name Type Description Default
hidden_states Tensor

(B, T, H, W, D)

required

Returns: pos_emb: (B, T, H, W, D)

Source code in fastvideo/models/dits/gen3c.py
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
    """
    Args:
        hidden_states: (B, T, H, W, D)
    Returns:
        pos_emb: (B, T, H, W, D)
    """
    B, T, H, W, D = hidden_states.shape

    emb_t = self.pos_emb_t[:T][None, :, None, None, :].repeat(B, 1, H, W, 1)
    emb_h = self.pos_emb_h[:H][None, None, :, None, :].repeat(B, T, 1, W, 1)
    emb_w = self.pos_emb_w[:W][None, None, None, :, :].repeat(B, T, H, 1, 1)

    emb = emb_t + emb_h + emb_w

    # Normalize
    norm = torch.linalg.vector_norm(emb, dim=-1, keepdim=True, dtype=torch.float32)
    norm = torch.add(self.eps, norm, alpha=np.sqrt(norm.numel() / emb.numel()))
    return (emb / norm).type_as(hidden_states)

fastvideo.models.dits.gen3c.Gen3CPatchEmbed

Gen3CPatchEmbed(in_channels: int, out_channels: int, patch_size: tuple[int, int, int])

Bases: Module

GEN3C patch embedding - converts video (B, C, T, H, W) to patches (B, T', H', W', D). Uses linear projection after rearranging patches.

Input channels include: - VAE latent (16 channels) - condition_video_input_mask (1 channel) - condition_video_pose (frame_buffer_max * 32 channels) - padding_mask (1 channel, if concat_padding_mask=True)

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    in_channels: int,
    out_channels: int,
    patch_size: tuple[int, int, int],
) -> None:
    super().__init__()
    self.patch_size = patch_size
    self.dim = in_channels * patch_size[0] * patch_size[1] * patch_size[2]

    self.proj = ReplicatedLinear(self.dim, out_channels, bias=False)

Methods:

fastvideo.models.dits.gen3c.Gen3CPatchEmbed.forward
forward(hidden_states: Tensor) -> Tensor

Parameters:

Name Type Description Default
hidden_states Tensor

(B, C, T, H, W)

required

Returns: (B, T', H', W', D) where T'=T//pt, H'=H//ph, W'=W//pw

Source code in fastvideo/models/dits/gen3c.py
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
    """
    Args:
        hidden_states: (B, C, T, H, W)
    Returns:
        (B, T', H', W', D) where T'=T//pt, H'=H//ph, W'=W//pw
    """
    batch_size, num_channels, num_frames, height, width = hidden_states.shape
    p_t, p_h, p_w = self.patch_size

    # Rearrange: b c (t pt) (h ph) (w pw) -> b t h w (c pt ph pw)
    hidden_states = hidden_states.reshape(
        batch_size, num_channels,
        num_frames // p_t, p_t,
        height // p_h, p_h,
        width // p_w, p_w
    )
    hidden_states = hidden_states.permute(0, 2, 4, 6, 1, 3, 5, 7)
    hidden_states = hidden_states.flatten(4, 7)  # Flatten patch dimensions

    # Project to model dimension
    hidden_states, _ = self.proj(hidden_states)
    return hidden_states

fastvideo.models.dits.gen3c.Gen3CRotaryPosEmbed

Gen3CRotaryPosEmbed(hidden_size: int, max_size: tuple[int, int, int] = (128, 240, 240), patch_size: tuple[int, int, int] = (1, 2, 2), base_fps: int = 24, rope_scale: tuple[float, float, float] = (1.0, 1.0, 1.0), enable_fps_modulation: bool = True)

Bases: Module

GEN3C 3D Rotary Position Embedding with NTK-aware extrapolation.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    hidden_size: int,
    max_size: tuple[int, int, int] = (128, 240, 240),
    patch_size: tuple[int, int, int] = (1, 2, 2),
    base_fps: int = 24,
    rope_scale: tuple[float, float, float] = (1.0, 1.0, 1.0),
    enable_fps_modulation: bool = True,
) -> None:
    super().__init__()

    self.max_size = [size // patch for size, patch in zip(max_size, patch_size, strict=True)]
    self.patch_size = patch_size
    self.base_fps = base_fps
    self.enable_fps_modulation = enable_fps_modulation

    # Split dimensions: 1/3 for T, 1/3 for H, 1/3 for W
    self.dim_h = hidden_size // 6 * 2
    self.dim_w = hidden_size // 6 * 2
    self.dim_t = hidden_size - self.dim_h - self.dim_w

    # NTK-aware extrapolation factors
    self.h_ntk_factor = rope_scale[1] ** (self.dim_h / (self.dim_h - 2))
    self.w_ntk_factor = rope_scale[2] ** (self.dim_w / (self.dim_w - 2))
    self.t_ntk_factor = rope_scale[0] ** (self.dim_t / (self.dim_t - 2))

Methods:

fastvideo.models.dits.gen3c.Gen3CRotaryPosEmbed.forward
forward(hidden_states: Tensor, fps: int | None = None) -> tuple[Tensor, Tensor]

Generate 3D RoPE embeddings.

Source code in fastvideo/models/dits/gen3c.py
def forward(
    self, hidden_states: torch.Tensor, fps: int | None = None
) -> tuple[torch.Tensor, torch.Tensor]:
    """
    Generate 3D RoPE embeddings.
    """
    batch_size, T, H, W, input_dim = hidden_states.shape
    device = hidden_states.device

    # Generate frequency scales with NTK
    h_theta = 10000.0 * self.h_ntk_factor
    w_theta = 10000.0 * self.w_ntk_factor
    t_theta = 10000.0 * self.t_ntk_factor

    seq = torch.arange(max(self.max_size), device=device, dtype=torch.float32)

    dim_h_range = torch.arange(0, self.dim_h, 2, device=device, dtype=torch.float32)[: (self.dim_h // 2)] / self.dim_h
    dim_w_range = torch.arange(0, self.dim_w, 2, device=device, dtype=torch.float32)[: (self.dim_w // 2)] / self.dim_w
    dim_t_range = torch.arange(0, self.dim_t, 2, device=device, dtype=torch.float32)[: (self.dim_t // 2)] / self.dim_t

    h_spatial_freqs = 1.0 / (h_theta ** dim_h_range)
    w_spatial_freqs = 1.0 / (w_theta ** dim_w_range)
    temporal_freqs = 1.0 / (t_theta ** dim_t_range)

    # Generate positional embeddings
    half_emb_h = torch.outer(seq[:H], h_spatial_freqs)
    half_emb_w = torch.outer(seq[:W], w_spatial_freqs)

    if self.enable_fps_modulation and fps is not None:
        half_emb_t = torch.outer(seq[:T] / fps * self.base_fps, temporal_freqs)
    else:
        half_emb_t = torch.outer(seq[:T], temporal_freqs)

    # Broadcast and concatenate embeddings
    emb_t = half_emb_t[:, None, None, :].repeat(1, H, W, 1)
    emb_h = half_emb_h[None, :, None, :].repeat(T, 1, W, 1)
    emb_w = half_emb_w[None, None, :, :].repeat(T, H, 1, 1)

    # Concatenate [t, h, w, t, h, w] for sin/cos pairs
    freqs = torch.cat([emb_t, emb_h, emb_w] * 2, dim=-1)
    freqs = freqs.flatten(0, 2).float()  # (THW, D)

    cos = torch.cos(freqs)
    sin = torch.sin(freqs)

    return cos, sin

fastvideo.models.dits.gen3c.Gen3CSelfAttention

Gen3CSelfAttention(dim: int, num_heads: int, qk_norm: bool = True, eps: float = 1e-06, supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None)

Bases: Module

GEN3C self-attention with QK normalization and RoPE.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    dim: int,
    num_heads: int,
    qk_norm: bool = True,
    eps: float = 1e-6,
    supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None,
) -> None:
    assert dim % num_heads == 0
    super().__init__()
    self.dim = dim
    self.num_heads = num_heads
    self.head_dim = dim // num_heads

    self.to_q = ReplicatedLinear(dim, dim, bias=False)
    self.to_k = ReplicatedLinear(dim, dim, bias=False)
    self.to_v = ReplicatedLinear(dim, dim, bias=False)
    self.to_out = ReplicatedLinear(dim, dim, bias=False)

    self.norm_q = RMSNorm(self.head_dim, eps=eps) if qk_norm else nn.Identity()
    self.norm_k = RMSNorm(self.head_dim, eps=eps) if qk_norm else nn.Identity()

    if supported_attention_backends is None:
        supported_attention_backends = (AttentionBackendEnum.FLASH_ATTN, AttentionBackendEnum.TORCH_SDPA)

    self.attn = DistributedAttention(
        num_heads=num_heads,
        head_size=self.head_dim,
        causal=False,
        supported_attention_backends=supported_attention_backends,
        prefix="self_attn"
    )

Methods:

fastvideo.models.dits.gen3c.Gen3CSelfAttention.forward
forward(hidden_states: Tensor, rope_emb: tuple[Tensor, Tensor] | None = None, original_seq_len: int | None = None) -> Tensor

Parameters:

Name Type Description Default
hidden_states Tensor

(B, S, D) where S = THW

required
rope_emb tuple[Tensor, Tensor] | None

Tuple of (cos, sin) for RoPE

None
original_seq_len int | None

Original (unpadded) full sequence length

None
Source code in fastvideo/models/dits/gen3c.py
def forward(
    self,
    hidden_states: torch.Tensor,
    rope_emb: tuple[torch.Tensor, torch.Tensor] | None = None,
    original_seq_len: int | None = None,
) -> torch.Tensor:
    """
    Args:
        hidden_states: (B, S, D) where S = T*H*W
        rope_emb: Tuple of (cos, sin) for RoPE
        original_seq_len: Original (unpadded) full sequence length
    """
    # Get QKV
    query, _ = self.to_q(hidden_states)
    key, _ = self.to_k(hidden_states)
    value, _ = self.to_v(hidden_states)

    # Reshape for multi-head attention: (B, S, D) -> (B, S, H, D_h) -> (B, H, S, D_h)
    query = query.unflatten(-1, (self.num_heads, self.head_dim)).transpose(1, 2)
    key = key.unflatten(-1, (self.num_heads, self.head_dim)).transpose(1, 2)
    value = value.unflatten(-1, (self.num_heads, self.head_dim)).transpose(1, 2)

    # Apply QK normalization
    query = self.norm_q(query)
    key = self.norm_k(key)

    # Apply RoPE if provided (query/key are now in (B, H, S, D_h) format)
    if rope_emb is not None:
        cos, sin = rope_emb
        query = apply_rotary_emb(query, (cos, sin), use_real=True, use_real_unbind_dim=-2)
        key = apply_rotary_emb(key, (cos, sin), use_real=True, use_real_unbind_dim=-2)

    # Attention computation
    query = query.transpose(1, 2)  # (B, H, S, D_h) -> (B, S, H, D_h)
    key = key.transpose(1, 2)
    value = value.transpose(1, 2)

    attn_output, _ = self.attn(
        query, key, value, original_seq_len=original_seq_len
    )
    attn_output = attn_output.flatten(-2, -1)  # (B, S, H*D_h)

    # Output projection
    attn_output, _ = self.to_out(attn_output)
    return attn_output

fastvideo.models.dits.gen3c.Gen3CTimestepEmbedding

Gen3CTimestepEmbedding(in_features: int, out_features: int, use_adaln_lora: bool = True, adaln_lora_dim: int = 256)

Bases: Module

GEN3C timestep embedding with AdaLN-LoRA support. Generates both standard embedding and AdaLN-LoRA parameters.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    in_features: int,
    out_features: int,
    use_adaln_lora: bool = True,
    adaln_lora_dim: int = 256,
) -> None:
    super().__init__()
    self.use_adaln_lora = use_adaln_lora

    self.linear_1 = ReplicatedLinear(in_features, out_features, bias=False)
    self.activation = nn.SiLU()

    if use_adaln_lora:
        self.linear_2 = ReplicatedLinear(out_features,
                                         3 * out_features,
                                         bias=False)
    else:
        self.linear_2 = ReplicatedLinear(out_features,
                                         out_features,
                                         bias=False)

Methods:

fastvideo.models.dits.gen3c.Gen3CTimestepEmbedding.forward
forward(sample: Tensor) -> tuple[Tensor, Tensor | None]

Returns:

Name Type Description
emb Tensor

Standard embedding (B, D) - the original sinusoidal input

adaln_lora Tensor | None

AdaLN-LoRA parameters (B, 3D) or None

Note: When use_adaln_lora=True, the standard embedding is the INPUT (sinusoidal timestep embedding), not the processed output. The processed output (linear_2) is used exclusively for AdaLN-LoRA parameters. This matches the official GEN3C implementation.

Source code in fastvideo/models/dits/gen3c.py
def forward(self, sample: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor | None]:
    """
    Returns:
        emb: Standard embedding (B, D) - the original sinusoidal input
        adaln_lora: AdaLN-LoRA parameters (B, 3D) or None

    Note: When use_adaln_lora=True, the standard embedding is the INPUT
    (sinusoidal timestep embedding), not the processed output. The processed
    output (linear_2) is used exclusively for AdaLN-LoRA parameters.
    This matches the official GEN3C implementation.
    """
    emb, _ = self.linear_1(sample)
    emb = self.activation(emb)
    emb, _ = self.linear_2(emb)

    if self.use_adaln_lora:
        adaln_lora = emb  # (B, 3D) - full processed embedding for LoRA
        emb_standard = sample  # (B, D) - original input as the standard embedding
    else:
        emb_standard = emb
        adaln_lora = None

    return emb_standard, adaln_lora

fastvideo.models.dits.gen3c.Gen3CTransformer3DModel

Gen3CTransformer3DModel(config: Gen3CVideoConfig, hf_config: dict[str, Any])

Bases: BaseDiT

GEN3C DiT - Video-conditioned diffusion transformer with 3D cache support.

Key features: - AdaLN-LoRA conditioning - 3D RoPE with NTK-aware extrapolation - Learnable positional embeddings - QK normalization - Video conditioning with 3D cache buffers - Augment sigma embedding for conditioning noise augmentation

Source code in fastvideo/models/dits/gen3c.py
def __init__(self, config: Gen3CVideoConfig, hf_config: dict[str, Any]) -> None:
    super().__init__(config=config, hf_config=hf_config)

    inner_dim = config.num_attention_heads * config.attention_head_dim
    self.hidden_size = inner_dim
    self.num_attention_heads = config.num_attention_heads
    self.in_channels = config.in_channels
    self.out_channels = config.out_channels
    self.num_channels_latents = config.num_channels_latents
    self.patch_size = config.patch_size
    self.max_size = config.max_size
    self.rope_scale = config.rope_scale
    self.concat_padding_mask = config.concat_padding_mask
    self.use_adaln_lora = getattr(config, "use_adaln_lora", True)
    self.adaln_lora_dim = getattr(config, "adaln_lora_dim", 256)
    self.extra_pos_embed_type = getattr(config, "extra_pos_embed_type", "learnable")
    self.affine_emb_norm = getattr(config, "affine_emb_norm", True)

    # GEN3C-specific
    self.frame_buffer_max = getattr(config, "frame_buffer_max", 2)
    self.buffer_channels = self.frame_buffer_max * 32  # Each buffer: 16 (frame) + 16 (mask)
    self.add_augment_sigma_embedding = getattr(config, "add_augment_sigma_embedding", True)

    # 1. Patch Embedding
    # Input channels: VAE (16) + condition_mask (1) + pose_buffers (64 for 2 buffers) + padding (1)
    patch_embed_in_channels = config.in_channels + 1 + self.buffer_channels
    if config.concat_padding_mask:
        patch_embed_in_channels += 1

    self.patch_embed = Gen3CPatchEmbed(
        patch_embed_in_channels, inner_dim, config.patch_size
    )

    # 2. Positional Embeddings
    self.rope = Gen3CRotaryPosEmbed(
        hidden_size=config.attention_head_dim,
        max_size=config.max_size,
        patch_size=config.patch_size,
        rope_scale=config.rope_scale,
        enable_fps_modulation=getattr(config, "rope_enable_fps_modulation", True),
    )

    self.learnable_pos_embed = None
    if self.extra_pos_embed_type == "learnable":
        self.learnable_pos_embed = Gen3CLearnablePositionalEmbed(
            hidden_size=inner_dim,
            max_size=config.max_size,
            patch_size=config.patch_size,
        )

    # 3. Time Embedding
    self.time_embed = Gen3CEmbedding(
        inner_dim,
        inner_dim,
        use_adaln_lora=self.use_adaln_lora,
        adaln_lora_dim=self.adaln_lora_dim,
    )

    # 4. Augment Sigma Embedding (GEN3C-specific)
    if self.add_augment_sigma_embedding:
        self.augment_sigma_embed = Gen3CEmbedding(
            inner_dim,
            inner_dim,
            use_adaln_lora=self.use_adaln_lora,
            adaln_lora_dim=self.adaln_lora_dim,
        )

    # 5. Affine Embedding Normalization
    if self.affine_emb_norm:
        self.affine_norm = RMSNorm(inner_dim, eps=config.eps)
    else:
        self.affine_norm = nn.Identity()

    # 6. Transformer Blocks
    self.transformer_blocks = nn.ModuleList([
        Gen3CTransformerBlock(
            num_attention_heads=config.num_attention_heads,
            attention_head_dim=config.attention_head_dim,
            cross_attention_dim=config.text_embed_dim,
            mlp_ratio=config.mlp_ratio,
            adaln_lora_dim=self.adaln_lora_dim,
            use_adaln_lora=self.use_adaln_lora,
            qk_norm=(config.qk_norm == "rms_norm"),
            supported_attention_backends=config._supported_attention_backends,
        )
        for i in range(config.num_layers)
    ])

    # 7. Final Layer
    self.final_layer = Gen3CFinalLayer(
        hidden_size=inner_dim,
        out_channels=config.out_channels,
        patch_size=config.patch_size,
        adaln_lora_dim=self.adaln_lora_dim,
        use_adaln_lora=self.use_adaln_lora,
    )

    self.gradient_checkpointing = False
    self.__post_init__()

Methods:

fastvideo.models.dits.gen3c.Gen3CTransformer3DModel.forward
forward(hidden_states: Tensor, timestep: Tensor, encoder_hidden_states: Tensor | list[Tensor], attention_mask: Tensor | None = None, fps: int | None = None, condition_video_input_mask: Tensor | None = None, condition_video_pose: Tensor | None = None, condition_video_augment_sigma: Tensor | None = None, padding_mask: Tensor | None = None, **kwargs) -> Tensor

Parameters:

Name Type Description Default
hidden_states Tensor

(B, C, T, H, W) latent video (16 channels)

required
timestep Tensor

(B,) diffusion timesteps

required
encoder_hidden_states Tensor | list[Tensor]

(B, N, D_text) text embeddings

required
attention_mask Tensor | None

Optional attention mask

None
fps int | None

Frames per second

None
condition_video_input_mask Tensor | None

(B, 1, T, H, W) conditioning mask for video frames

None
condition_video_pose Tensor | None

(B, buffer_channels, T, H, W) VAE-encoded 3D cache buffers

None
condition_video_augment_sigma Tensor | None

(B,) sigma for conditioning noise augmentation

None
padding_mask Tensor | None

(B, 1, H, W) padding mask

None
Source code in fastvideo/models/dits/gen3c.py
def forward(
    self,
    hidden_states: torch.Tensor,
    timestep: torch.Tensor,
    encoder_hidden_states: torch.Tensor | list[torch.Tensor],
    attention_mask: torch.Tensor | None = None,
    fps: int | None = None,
    condition_video_input_mask: torch.Tensor | None = None,
    condition_video_pose: torch.Tensor | None = None,
    condition_video_augment_sigma: torch.Tensor | None = None,
    padding_mask: torch.Tensor | None = None,
    **kwargs,
) -> torch.Tensor:
    """
    Args:
        hidden_states: (B, C, T, H, W) latent video (16 channels)
        timestep: (B,) diffusion timesteps
        encoder_hidden_states: (B, N, D_text) text embeddings
        attention_mask: Optional attention mask
        fps: Frames per second
        condition_video_input_mask: (B, 1, T, H, W) conditioning mask for video frames
        condition_video_pose: (B, buffer_channels, T, H, W) VAE-encoded 3D cache buffers
        condition_video_augment_sigma: (B,) sigma for conditioning noise augmentation
        padding_mask: (B, 1, H, W) padding mask
    """
    if not isinstance(encoder_hidden_states, torch.Tensor):
        encoder_hidden_states = encoder_hidden_states[0]

    batch_size, num_channels, num_frames, height, width = hidden_states.shape

    # 1. Concatenate condition_video_input_mask
    if condition_video_input_mask is not None:
        hidden_states = torch.cat([hidden_states, condition_video_input_mask], dim=1)
    else:
        # Default: zeros mask (no conditioning)
        condition_video_input_mask = torch.zeros(
            batch_size, 1, num_frames, height, width, 
            device=hidden_states.device, dtype=hidden_states.dtype
        )
        hidden_states = torch.cat([hidden_states, condition_video_input_mask], dim=1)

    # 2. Concatenate condition_video_pose (3D cache buffers)
    if condition_video_pose is not None:
        hidden_states = torch.cat([hidden_states, condition_video_pose], dim=1)
    else:
        # Default: zeros for pose buffers
        pose_zeros = torch.zeros(
            batch_size, self.buffer_channels, num_frames, height, width,
            device=hidden_states.device, dtype=hidden_states.dtype
        )
        hidden_states = torch.cat([hidden_states, pose_zeros], dim=1)

    # 3. Concatenate padding mask if needed
    if self.concat_padding_mask:
        if padding_mask is None:
            padding_mask = torch.ones(
                batch_size, 1, height, width,
                device=hidden_states.device, dtype=hidden_states.dtype
            )
        padding_mask = transforms.functional.resize(
            padding_mask,
            list(hidden_states.shape[-2:]),
            interpolation=transforms.InterpolationMode.NEAREST,
        )
        hidden_states = torch.cat(
            [hidden_states, padding_mask.unsqueeze(2).repeat(1, 1, num_frames, 1, 1)],
            dim=1,
        )

    # 4. Patchify input
    p_t, p_h, p_w = self.patch_size
    hidden_states = self.patch_embed(hidden_states)  # (B, T', H', W', D)
    post_patch_num_frames, post_patch_height, post_patch_width = hidden_states.shape[1:4]

    # 5. Generate RoPE embeddings
    rope_emb = self.rope(hidden_states, fps=fps)

    # 6. Generate learnable positional embeddings
    extra_pos_emb = None
    if self.learnable_pos_embed is not None:
        extra_pos_emb = self.learnable_pos_embed(hidden_states)

    # Flatten to sequence representation for transformer blocks.
    hidden_states = hidden_states.flatten(1, 3)  # (B, S, D)
    if extra_pos_emb is not None:
        extra_pos_emb = extra_pos_emb.flatten(1, 3)

    # Sequence parallel sharding with optional padding.
    # This is a no-op when SP world size is 1.
    sp_world_size = get_sp_world_size()
    original_seq_len = hidden_states.shape[1]
    if sp_world_size > 1:
        hidden_states, original_seq_len = sequence_model_parallel_shard(
            hidden_states, dim=1
        )
        if extra_pos_emb is not None:
            extra_pos_emb, _ = sequence_model_parallel_shard(extra_pos_emb, dim=1)
        rope_cos, _ = sequence_model_parallel_shard(rope_emb[0], dim=0)
        rope_sin, _ = sequence_model_parallel_shard(rope_emb[1], dim=0)
        rope_emb = (rope_cos, rope_sin)

    # 7. Timestep embeddings
    affine_emb, adaln_lora = self.time_embed(timestep, hidden_states.dtype)

    # 8. Augment sigma embedding (GEN3C-specific)
    if self.add_augment_sigma_embedding:
        if condition_video_augment_sigma is None:
            condition_video_augment_sigma = torch.zeros_like(timestep)
        augment_emb, _ = self.augment_sigma_embed(condition_video_augment_sigma, hidden_states.dtype)
        affine_emb = affine_emb + augment_emb

    # 9. Apply affine normalization
    affine_emb = self.affine_norm(affine_emb)

    # 10. Transformer blocks
    if torch.is_grad_enabled() and self.gradient_checkpointing:
        for block in self.transformer_blocks:
            hidden_states = self._gradient_checkpointing_func(
                block,
                hidden_states,
                encoder_hidden_states,
                affine_emb,
                adaln_lora,
                rope_emb,
                extra_pos_emb,
                original_seq_len,
            )
    else:
        for block in self.transformer_blocks:
            hidden_states = block(
                hidden_states=hidden_states,
                encoder_hidden_states=encoder_hidden_states,
                affine_emb=affine_emb,
                adaln_lora=adaln_lora,
                rope_emb=rope_emb,
                extra_pos_emb=extra_pos_emb,
                original_seq_len=original_seq_len,
            )

    # 11. Final layer
    hidden_states = self.final_layer(hidden_states, affine_emb, adaln_lora)

    if sp_world_size > 1:
        hidden_states = sequence_model_parallel_all_gather_with_unpad(
            hidden_states, original_seq_len, dim=1
        )

    # 12. Unpatchify: (B, S, P) -> (B, T', H', W', P) -> (B, C, T, H, W)
    hidden_states = hidden_states.unflatten(
        1, (post_patch_num_frames, post_patch_height, post_patch_width)
    )
    hidden_states = hidden_states.unflatten(-1, (p_t, p_h, p_w, self.out_channels))
    hidden_states = hidden_states.permute(0, 7, 1, 4, 2, 5, 3, 6)
    hidden_states = hidden_states.flatten(2, 3).flatten(3, 4).flatten(4, 5)

    return hidden_states

fastvideo.models.dits.gen3c.Gen3CTransformerBlock

Gen3CTransformerBlock(num_attention_heads: int, attention_head_dim: int, cross_attention_dim: int, mlp_ratio: float = 4.0, adaln_lora_dim: int = 256, use_adaln_lora: bool = True, qk_norm: bool = True, supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None)

Bases: Module

GEN3C transformer block with self-attention, cross-attention, and MLP. Uses AdaLN-LoRA for conditioning.

Source code in fastvideo/models/dits/gen3c.py
def __init__(
    self,
    num_attention_heads: int,
    attention_head_dim: int,
    cross_attention_dim: int,
    mlp_ratio: float = 4.0,
    adaln_lora_dim: int = 256,
    use_adaln_lora: bool = True,
    qk_norm: bool = True,
    supported_attention_backends: tuple[AttentionBackendEnum, ...] | None = None,
) -> None:
    super().__init__()

    hidden_size = num_attention_heads * attention_head_dim
    self.use_adaln_lora = use_adaln_lora

    # Layer norms
    self.norm1 = Gen3CAdaLayerNormZero(hidden_size)
    self.norm2 = Gen3CAdaLayerNormZero(hidden_size)
    self.norm3 = Gen3CAdaLayerNormZero(hidden_size)

    # Attention and MLP layers
    self.attn1 = Gen3CSelfAttention(
        dim=hidden_size,
        num_heads=num_attention_heads,
        qk_norm=qk_norm,
        supported_attention_backends=supported_attention_backends,
    )
    self.attn2 = Gen3CCrossAttention(
        dim=hidden_size,
        cross_attention_dim=cross_attention_dim,
        num_heads=num_attention_heads,
        qk_norm=qk_norm,
        supported_attention_backends=supported_attention_backends,
    )
    self.mlp = MLP(hidden_size, int(hidden_size * mlp_ratio), act_type="gelu", bias=False)

    # AdaLN modulation layers
    if use_adaln_lora:
        self.adaln_modulation_self_attn = nn.ModuleList([
            nn.SiLU(),
            ReplicatedLinear(hidden_size, adaln_lora_dim, bias=False),
            ReplicatedLinear(adaln_lora_dim, 3 * hidden_size, bias=False),
        ])
        self.adaln_modulation_cross_attn = nn.ModuleList([
            nn.SiLU(),
            ReplicatedLinear(hidden_size, adaln_lora_dim, bias=False),
            ReplicatedLinear(adaln_lora_dim, 3 * hidden_size, bias=False),
        ])
        self.adaln_modulation_mlp = nn.ModuleList([
            nn.SiLU(),
            ReplicatedLinear(hidden_size, adaln_lora_dim, bias=False),
            ReplicatedLinear(adaln_lora_dim, 3 * hidden_size, bias=False),
        ])
    else:
        self.adaln_modulation_self_attn = nn.ModuleList([
            nn.SiLU(),
            ReplicatedLinear(hidden_size, 3 * hidden_size, bias=False)
        ])
        self.adaln_modulation_cross_attn = nn.ModuleList([
            nn.SiLU(),
            ReplicatedLinear(hidden_size, 3 * hidden_size, bias=False)
        ])
        self.adaln_modulation_mlp = nn.ModuleList([
            nn.SiLU(),
            ReplicatedLinear(hidden_size, 3 * hidden_size, bias=False)
        ])

Methods:

fastvideo.models.dits.gen3c.Gen3CTransformerBlock.forward
forward(hidden_states: Tensor, encoder_hidden_states: Tensor, affine_emb: Tensor, adaln_lora: Tensor | None = None, rope_emb: tuple[Tensor, Tensor] | None = None, extra_pos_emb: Tensor | None = None, original_seq_len: int | None = None) -> Tensor

Parameters:

Name Type Description Default
hidden_states Tensor

(B, S, D) where S = THW (sequence may be sharded with SP)

required
encoder_hidden_states Tensor

(B, N, D_text)

required
affine_emb Tensor

(B, D) affine embedding

required
adaln_lora Tensor | None

(B, 3D) AdaLN-LoRA parameters

None
rope_emb tuple[Tensor, Tensor] | None

Tuple of (cos, sin) for RoPE

None
extra_pos_emb Tensor | None

Optional learnable positional embeddings (B, S, D)

None
original_seq_len int | None

Original (unpadded) full sequence length

None
Source code in fastvideo/models/dits/gen3c.py
def forward(
    self,
    hidden_states: torch.Tensor,
    encoder_hidden_states: torch.Tensor,
    affine_emb: torch.Tensor,
    adaln_lora: torch.Tensor | None = None,
    rope_emb: tuple[torch.Tensor, torch.Tensor] | None = None,
    extra_pos_emb: torch.Tensor | None = None,
    original_seq_len: int | None = None,
) -> torch.Tensor:
    """
    Args:
        hidden_states: (B, S, D) where S = T*H*W (sequence may be sharded with SP)
        encoder_hidden_states: (B, N, D_text)
        affine_emb: (B, D) affine embedding
        adaln_lora: (B, 3D) AdaLN-LoRA parameters
        rope_emb: Tuple of (cos, sin) for RoPE
        extra_pos_emb: Optional learnable positional embeddings (B, S, D)
        original_seq_len: Original (unpadded) full sequence length
    """
    # Add extra positional embeddings if provided
    if extra_pos_emb is not None:
        hidden_states = hidden_states + extra_pos_emb

    B, S, D = hidden_states.shape

    # Compute modulation parameters
    if self.use_adaln_lora and adaln_lora is not None:
        shift_self_attn, scale_self_attn, gate_self_attn = (
            _run_linear_stack(self.adaln_modulation_self_attn, affine_emb)
            + adaln_lora
        ).chunk(3, dim=-1)
        shift_cross_attn, scale_cross_attn, gate_cross_attn = (
            _run_linear_stack(self.adaln_modulation_cross_attn, affine_emb)
            + adaln_lora
        ).chunk(3, dim=-1)
        shift_mlp, scale_mlp, gate_mlp = (
            _run_linear_stack(self.adaln_modulation_mlp, affine_emb)
            + adaln_lora
        ).chunk(3, dim=-1)
    else:
        shift_self_attn, scale_self_attn, gate_self_attn = _run_linear_stack(
            self.adaln_modulation_self_attn, affine_emb).chunk(3, dim=-1)
        shift_cross_attn, scale_cross_attn, gate_cross_attn = _run_linear_stack(
            self.adaln_modulation_cross_attn, affine_emb).chunk(3, dim=-1)
        shift_mlp, scale_mlp, gate_mlp = _run_linear_stack(
            self.adaln_modulation_mlp, affine_emb).chunk(3, dim=-1)

    # Reshape modulation parameters for broadcasting: (B, D) -> (B, 1, D)
    shift_self_attn = shift_self_attn.unsqueeze(1).type_as(hidden_states)
    scale_self_attn = scale_self_attn.unsqueeze(1).type_as(hidden_states)
    gate_self_attn = gate_self_attn.unsqueeze(1).type_as(hidden_states)

    shift_cross_attn = shift_cross_attn.unsqueeze(1).type_as(hidden_states)
    scale_cross_attn = scale_cross_attn.unsqueeze(1).type_as(hidden_states)
    gate_cross_attn = gate_cross_attn.unsqueeze(1).type_as(hidden_states)

    shift_mlp = shift_mlp.unsqueeze(1).type_as(hidden_states)
    scale_mlp = scale_mlp.unsqueeze(1).type_as(hidden_states)
    gate_mlp = gate_mlp.unsqueeze(1).type_as(hidden_states)

    # Self-attention block
    norm_hidden_states = self.norm1(hidden_states, shift_self_attn, scale_self_attn)

    attn_output = self.attn1(
        norm_hidden_states,
        rope_emb=rope_emb,
        original_seq_len=original_seq_len,
    )
    hidden_states = hidden_states + gate_self_attn * attn_output

    # Cross-attention block
    norm_hidden_states = self.norm2(hidden_states, shift_cross_attn, scale_cross_attn)

    attn_output = self.attn2(
        norm_hidden_states,
        encoder_hidden_states=encoder_hidden_states,
    )
    hidden_states = hidden_states + gate_cross_attn * attn_output

    # MLP block
    norm_hidden_states = self.norm3(hidden_states, shift_mlp, scale_mlp)

    mlp_output = self.mlp(norm_hidden_states)
    hidden_states = hidden_states + gate_mlp * mlp_output

    return hidden_states

Functions: