---
title: causal_fast
---

<div class="python-reference">
<a id="fastvideo.models.dits.lingbotworld2.causal_fast-classes"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast-functions"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalHead-functions"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanAttentionBlock-functions"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanSelfAttention-functions"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel-functions"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast.WanCrossAttention-functions"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast.WanLayerNorm-functions"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast.WanRMSNorm-functions"></a>
<a id="fastvideo.models.dits.lingbotworld2.causal_fast"></a>
<p>LingBot World 2 causal-fast DiT implemented inside FastVideo.</p>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.backend_name_to_enum"><code>fastvideo.models.dits.lingbotworld2.causal_fast.backend_name_to_enum</code></h2>
<pre class="doc-signature"><code>backend_name_to_enum(backend_name: str) -&gt; AttentionBackendEnum | None</code></pre>
<p>Convert a string backend name to a _Backend enum value.</p>
<p>Returns:
* _Backend: enum value if backend_name is a valid in-tree type
* None: otherwise it's an invalid in-tree type or an out-of-tree platform is
        loaded.</p>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.get_attn_backend"><code>fastvideo.models.dits.lingbotworld2.causal_fast.get_attn_backend</code></h2>
<pre class="doc-signature"><code>get_attn_backend(head_size: int, dtype: torch.dtype, supported_attention_backends: tuple&#91;AttentionBackendEnum, ...&#93; | None = None, default_backend: AttentionBackendEnum | None = None, *, requested: AttentionBackendEnum | None | _NoRequest = NO_REQUEST) -&gt; type&#91;AttentionBackend&#93;</code></pre>
<p>Resolve the attention backend class for one call site.</p>
<p><code>requested</code> is the decision made for the component this call site belongs
to — read from <code>ModelConfig._resolved_attention_backend</code>. Passing it means
the caller knows the answer, so nothing ambient is consulted:</p>
<ul>
<li><code>requested=SOME_BACKEND</code> — use it (subject to the layer's declared
  support), ignoring the construction scope and the environment;</li>
<li><code>requested=None</code> — that component resolved to <em>automatic selection</em>.
  That is an answer, not an absence, so the environment is not consulted
  behind it;</li>
<li><code>requested</code> omitted (<code>NO_REQUEST</code>) — the caller has no opinion; fall
  back to the construction scope, then the environment. This is the path
  every layer built inside a loader still takes.</li>
</ul>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastVideoConfig"><code>fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastVideoConfig</code></h2>
<pre class="doc-signature"><code>LingBotWorld2CausalFastVideoConfig(arch_config: DiTArchConfig = LingBotWorld2CausalFastArchConfig(), prefix: str = &#x27;Wan&#x27;, quant_config: QuantizationConfig | None = None, *, _resolved_attention_backend: AttentionBackendEnum | None = None)</code></pre>


<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.sequence_model_parallel_all_gather"><code>fastvideo.models.dits.lingbotworld2.causal_fast.sequence_model_parallel_all_gather</code></h2>
<pre class="doc-signature"><code>sequence_model_parallel_all_gather(input_: torch.Tensor, dim: int = -1) -&gt; torch.Tensor</code></pre>
<p>All-gather the input tensor across model parallel group.</p>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.sequence_model_parallel_all_to_all_4D"><code>fastvideo.models.dits.lingbotworld2.causal_fast.sequence_model_parallel_all_to_all_4D</code></h2>
<pre class="doc-signature"><code>sequence_model_parallel_all_to_all_4D(input_: torch.Tensor, scatter_dim: int = 2, gather_dim: int = 1) -&gt; torch.Tensor</code></pre>
<p>All-to-all communication of 4D tensors (e.g. QKV matrices) across sequence parallel group.</p>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.get_sp_parallel_rank"><code>fastvideo.models.dits.lingbotworld2.causal_fast.get_sp_parallel_rank</code></h2>
<pre class="doc-signature"><code>get_sp_parallel_rank() -&gt; int</code></pre>
<p>Return my rank for the sequence model parallel group.</p>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.get_sp_world_size"><code>fastvideo.models.dits.lingbotworld2.causal_fast.get_sp_world_size</code></h2>
<pre class="doc-signature"><code>get_sp_world_size() -&gt; int</code></pre>
<p>Return world size for the sequence model parallel group.</p>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT"><code>fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT</code></h2>
<pre class="doc-signature"><code>BaseDiT(config: DiTConfig, hf_config: dict&#91;str, Any&#93;, **kwargs)</code></pre>


<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT.forward"><code>fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT.forward</code></h3>
<pre class="doc-signature"><code>forward(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, guidance = None, **kwargs) -&gt; torch.Tensor</code></pre>

<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT.preprocess_loaded_weight"><code>fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT.preprocess_loaded_weight</code></h3>
<pre class="doc-signature"><code>preprocess_loaded_weight(name: str, tensor: torch.Tensor) -&gt; torch.Tensor</code></pre>
<p>Adapt a checkpoint tensor before sharding; default models are unchanged.</p>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT.inference_config_overrides"><code>fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT.inference_config_overrides</code></h3>
<pre class="doc-signature"><code>inference_config_overrides() -&gt; dict&#91;str, Any&#93;</code></pre>
<p>Extra <code>config.json</code> keys a deployable checkpoint of this model needs.</p>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT.inference_export_expected_shape"><code>fastvideo.models.dits.lingbotworld2.causal_fast.BaseDiT.inference_export_expected_shape</code></h3>
<pre class="doc-signature"><code>inference_export_expected_shape(output_key: str, base_shape: tuple&#91;int, ...&#93;) -&gt; tuple&#91;int, ...&#93;</code></pre>
<p>The exported shape of <em>output_key</em> given the base checkpoint's shape.</p>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.AttentionBackendEnum"><code>fastvideo.models.dits.lingbotworld2.causal_fast.AttentionBackendEnum</code></h2>
<pre class="doc-signature"><code>AttentionBackendEnum()</code></pre>

<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.get_compute_dtype"><code>fastvideo.models.dits.lingbotworld2.causal_fast.get_compute_dtype</code></h2>
<pre class="doc-signature"><code>get_compute_dtype() -&gt; torch.dtype</code></pre>
<p>Get the current compute dtype from mixed precision policy.</p>
<h3>Returns</h3>
<dl>
<dt><code>torch.dtype</code></dt><dd><p>torch.dtype: The compute dtype to use, defaults to get_default_dtype() if no policy set</p></dd>
</dl>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.is_blocks"><code>fastvideo.models.dits.lingbotworld2.causal_fast.is_blocks</code></h2>
<pre class="doc-signature"><code>is_blocks(n: str, m) -&gt; bool</code></pre>

<details><summary>Source</summary><pre><code>def is_blocks(n: str, m) -&gt; bool:
    return &quot;blocks&quot; in n and str.isdigit(n.split(&quot;.&quot;)&#91;-1&#93;)</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.sinusoidal_embedding_1d"><code>fastvideo.models.dits.lingbotworld2.causal_fast.sinusoidal_embedding_1d</code></h2>
<pre class="doc-signature"><code>sinusoidal_embedding_1d(dim: int, position: torch.Tensor) -&gt; torch.Tensor</code></pre>
<p>Build Wan/LingBot World 2 sinusoidal timestep embeddings.</p>
<details><summary>Source</summary><pre><code>def sinusoidal_embedding_1d(dim: int, position: torch.Tensor) -&gt; torch.Tensor:
    &quot;&quot;&quot;Build Wan/LingBot World 2 sinusoidal timestep embeddings.&quot;&quot;&quot;
    assert dim % 2 == 0
    half = dim // 2
    position = position.type(torch.float64)
    sinusoid = torch.outer(
        position,
        torch.pow(10000, -torch.arange(half, device=position.device).to(position).div(half)),
    )
    return torch.cat(&#91;torch.cos(sinusoid), torch.sin(sinusoid)&#93;, dim=1)</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.rope_params"><code>fastvideo.models.dits.lingbotworld2.causal_fast.rope_params</code></h2>
<pre class="doc-signature"><code>rope_params(max_seq_len: int, dim: int, theta: int = 10000) -&gt; torch.Tensor</code></pre>
<p>Return complex RoPE frequencies used by the released LingBot World 2 model.</p>
<details><summary>Source</summary><pre><code>@torch.amp.autocast(&quot;cuda&quot;, enabled=False)
def rope_params(max_seq_len: int, dim: int, theta: int = 10000) -&gt; torch.Tensor:
    &quot;&quot;&quot;Return complex RoPE frequencies used by the released LingBot World 2 model.&quot;&quot;&quot;
    assert dim % 2 == 0
    freqs = torch.outer(
        torch.arange(max_seq_len),
        1.0 / torch.pow(theta,
                        torch.arange(0, dim, 2).to(torch.float64).div(dim)),
    )
    return torch.polar(torch.ones_like(freqs), freqs)</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.flash_attention"><code>fastvideo.models.dits.lingbotworld2.causal_fast.flash_attention</code></h2>
<pre class="doc-signature"><code>flash_attention(q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, q_lens: torch.Tensor | None = None, k_lens: torch.Tensor | None = None, dropout_p: float = 0.0, softmax_scale: float | None = None, q_scale: float | None = None, causal: bool = False, window_size: tuple&#91;int, int&#93; = (-1, -1), deterministic: bool = False, dtype: torch.dtype = torch.bfloat16, version: int | None = None) -&gt; torch.Tensor</code></pre>
<p>Run LingBot World 2-compatible FlashAttention on packed varlen inputs.</p>
<details><summary>Source</summary><pre><code>def flash_attention(
    q: torch.Tensor,
    k: torch.Tensor,
    v: torch.Tensor,
    q_lens: torch.Tensor | None = None,
    k_lens: torch.Tensor | None = None,
    dropout_p: float = 0.0,
    softmax_scale: float | None = None,
    q_scale: float | None = None,
    causal: bool = False,
    window_size: tuple&#91;int, int&#93; = (-1, -1),
    deterministic: bool = False,
    dtype: torch.dtype = torch.bfloat16,
    version: int | None = None,
) -&gt; torch.Tensor:
    &quot;&quot;&quot;Run LingBot World 2-compatible FlashAttention on packed varlen inputs.&quot;&quot;&quot;
    half_dtypes = (torch.float16, torch.bfloat16)
    assert dtype in half_dtypes
    assert q.device.type == &quot;cuda&quot; and q.size(-1) &lt;= 256

    b, lq, lk, out_dtype = q.size(0), q.size(1), k.size(1), q.dtype

    def half(x: torch.Tensor) -&gt; torch.Tensor:
        return x if x.dtype in half_dtypes else x.to(dtype)

    if q_lens is None:
        q = half(q.flatten(0, 1))
        q_lens = torch.tensor(&#91;lq&#93; * b, dtype=torch.int32, device=q.device)
    else:
        q = half(torch.cat(&#91;u&#91;:v&#93; for u, v in zip(q, q_lens, strict=True)&#93;))

    if k_lens is None:
        k = half(k.flatten(0, 1))
        v = half(v.flatten(0, 1))
        k_lens = torch.tensor(&#91;lk&#93; * b, dtype=torch.int32, device=k.device)
    else:
        k = half(torch.cat(&#91;u&#91;:v&#93; for u, v in zip(k, k_lens, strict=True)&#93;))
        v = half(torch.cat(&#91;u&#91;:v&#93; for u, v in zip(v, k_lens, strict=True)&#93;))

    q = q.to(v.dtype)
    k = k.to(v.dtype)
    if q_scale is not None:
        q = q * q_scale

    if version == 3 and not FLASH_ATTN_3_AVAILABLE:
        warnings.warn(&quot;FlashAttention 3 is not available; using FlashAttention 2.&quot;)

    cu_q = torch.cat(&#91;q_lens.new_zeros(&#91;1&#93;), q_lens&#93;).cumsum(0, dtype=torch.int32).to(q.device, non_blocking=True)
    cu_k = torch.cat(&#91;k_lens.new_zeros(&#91;1&#93;), k_lens&#93;).cumsum(0, dtype=torch.int32).to(k.device, non_blocking=True)

    if (version is None or version == 3) and FLASH_ATTN_3_AVAILABLE:
        x = flash_attn_interface.flash_attn_varlen_func(
            q=q,
            k=k,
            v=v,
            cu_seqlens_q=cu_q,
            cu_seqlens_k=cu_k,
            seqused_q=None,
            seqused_k=None,
            max_seqlen_q=lq,
            max_seqlen_k=lk,
            softmax_scale=softmax_scale,
            causal=causal,
            deterministic=deterministic,
        ).unflatten(0, (b, lq))
    else:
        assert FLASH_ATTN_2_AVAILABLE
        x = flash_attn.flash_attn_varlen_func(
            q=q,
            k=k,
            v=v,
            cu_seqlens_q=cu_q,
            cu_seqlens_k=cu_k,
            max_seqlen_q=lq,
            max_seqlen_k=lk,
            dropout_p=dropout_p,
            softmax_scale=softmax_scale,
            causal=causal,
            window_size=window_size,
            deterministic=deterministic,
        ).unflatten(0, (b, lq))
    return x.type(out_dtype)</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.attention"><code>fastvideo.models.dits.lingbotworld2.causal_fast.attention</code></h2>
<pre class="doc-signature"><code>attention(q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, backend: AttentionBackendEnum, q_lens: torch.Tensor | None = None, k_lens: torch.Tensor | None = None, dropout_p: float = 0.0, softmax_scale: float | None = None, q_scale: float | None = None, causal: bool = False, window_size: tuple&#91;int, int&#93; = (-1, -1), deterministic: bool = False, dtype: torch.dtype = torch.bfloat16, fa_version: int | None = None) -&gt; torch.Tensor</code></pre>
<p>Dispatch LingBot World 2 attention through the selected backend.</p>
<details><summary>Source</summary><pre><code>def attention(
    q: torch.Tensor,
    k: torch.Tensor,
    v: torch.Tensor,
    backend: AttentionBackendEnum,
    q_lens: torch.Tensor | None = None,
    k_lens: torch.Tensor | None = None,
    dropout_p: float = 0.0,
    softmax_scale: float | None = None,
    q_scale: float | None = None,
    causal: bool = False,
    window_size: tuple&#91;int, int&#93; = (-1, -1),
    deterministic: bool = False,
    dtype: torch.dtype = torch.bfloat16,
    fa_version: int | None = None,
) -&gt; torch.Tensor:
    &quot;&quot;&quot;Dispatch LingBot World 2 attention through the selected backend.&quot;&quot;&quot;
    if backend == AttentionBackendEnum.FLASH_ATTN:
        return flash_attention(
            q=q,
            k=k,
            v=v,
            q_lens=q_lens,
            k_lens=k_lens,
            dropout_p=dropout_p,
            softmax_scale=softmax_scale,
            q_scale=q_scale,
            causal=causal,
            window_size=window_size,
            deterministic=deterministic,
            dtype=dtype,
            version=fa_version,
        )

    assert backend == AttentionBackendEnum.TORCH_SDPA
    if q_lens is not None or k_lens is not None:
        warnings.warn(&quot;Padding masks are disabled without FlashAttention.&quot;)
    q = q.transpose(1, 2).to(dtype)
    k = k.transpose(1, 2).to(dtype)
    v = v.transpose(1, 2).to(dtype)
    out = F.scaled_dot_product_attention(q, k, v, attn_mask=None, is_causal=causal, dropout_p=dropout_p)
    return out.transpose(1, 2).contiguous()</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.causal_rope_apply"><code>fastvideo.models.dits.lingbotworld2.causal_fast.causal_rope_apply</code></h2>
<pre class="doc-signature"><code>causal_rope_apply(x: torch.Tensor, grid_sizes: torch.Tensor, freqs: torch.Tensor, start_frame: int = 0) -&gt; torch.Tensor</code></pre>
<p>Apply LingBot World 2 causal RoPE with the current chunk frame offset.</p>
<details><summary>Source</summary><pre><code>@torch.amp.autocast(&quot;cuda&quot;, enabled=False)
def causal_rope_apply(
    x: torch.Tensor,
    grid_sizes: torch.Tensor,
    freqs: torch.Tensor,
    start_frame: int = 0,
) -&gt; torch.Tensor:
    &quot;&quot;&quot;Apply LingBot World 2 causal RoPE with the current chunk frame offset.&quot;&quot;&quot;
    n, c = x.size(2), x.size(3) // 2
    freqs = freqs.split(&#91;c - 2 * (c // 3), c // 3, c // 3&#93;, dim=1)
    output = &#91;&#93;
    for i, (f, h, w) in enumerate(grid_sizes.tolist()):
        seq_len = f * h * w
        x_i = torch.view_as_complex(x&#91;i, :seq_len&#93;.to(torch.float64).reshape(seq_len, n, -1, 2))
        freqs_i = torch.cat(
            &#91;
                freqs&#91;0&#93;&#91;start_frame:start_frame + f&#93;.view(f, 1, 1, -1).expand(f, h, w, -1),
                freqs&#91;1&#93;&#91;:h&#93;.view(1, h, 1, -1).expand(f, h, w, -1),
                freqs&#91;2&#93;&#91;:w&#93;.view(1, 1, w, -1).expand(f, h, w, -1),
            &#93;,
            dim=-1,
        ).reshape(seq_len, 1, -1)
        x_i = torch.view_as_real(x_i * freqs_i).flatten(2)
        x_i = torch.cat(&#91;x_i, x&#91;i, seq_len:&#93;&#93;)
        output.append(x_i)
    return torch.stack(output).type_as(x)</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.WanRMSNorm"><code>fastvideo.models.dits.lingbotworld2.causal_fast.WanRMSNorm</code></h2>
<pre class="doc-signature"><code>WanRMSNorm(dim: int, eps: float = 1e-05)</code></pre>
<p>RMSNorm used by Wan/LingBot World 2 attention projections.</p>

<details><summary>Source</summary><pre><code>class WanRMSNorm(nn.Module):
    &quot;&quot;&quot;RMSNorm used by Wan/LingBot World 2 attention projections.&quot;&quot;&quot;

    def __init__(self, dim: int, eps: float = 1e-5):
        super().__init__()
        self.dim = dim
        self.eps = eps
        self.weight = nn.Parameter(torch.ones(dim))

    def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
        &quot;&quot;&quot;Normalize the last dimension in fp32 and restore input dtype.&quot;&quot;&quot;
        return self._norm(x.float()).type_as(x) * self.weight

    def _norm(self, x: torch.Tensor) -&gt; torch.Tensor:
        return x * torch.rsqrt(x.pow(2).mean(dim=-1, keepdim=True) + self.eps)</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.WanRMSNorm.forward"><code>fastvideo.models.dits.lingbotworld2.causal_fast.WanRMSNorm.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor) -&gt; torch.Tensor</code></pre>
<p>Normalize the last dimension in fp32 and restore input dtype.</p>
<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
    &quot;&quot;&quot;Normalize the last dimension in fp32 and restore input dtype.&quot;&quot;&quot;
    return self._norm(x.float()).type_as(x) * self.weight</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.WanLayerNorm"><code>fastvideo.models.dits.lingbotworld2.causal_fast.WanLayerNorm</code></h2>
<pre class="doc-signature"><code>WanLayerNorm(dim: int, eps: float = 1e-06, elementwise_affine: bool = False)</code></pre>
<p>LayerNorm variant that computes in fp32 and returns the input dtype.</p>

<details><summary>Source</summary><pre><code>class WanLayerNorm(nn.LayerNorm):
    &quot;&quot;&quot;LayerNorm variant that computes in fp32 and returns the input dtype.&quot;&quot;&quot;

    def __init__(self, dim: int, eps: float = 1e-6, elementwise_affine: bool = False):
        super().__init__(dim, elementwise_affine=elementwise_affine, eps=eps)

    def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
        &quot;&quot;&quot;Apply layer norm in fp32 for LingBot World 2 numerical parity.&quot;&quot;&quot;
        return super().forward(x.float()).type_as(x)</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.WanLayerNorm.forward"><code>fastvideo.models.dits.lingbotworld2.causal_fast.WanLayerNorm.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor) -&gt; torch.Tensor</code></pre>
<p>Apply layer norm in fp32 for LingBot World 2 numerical parity.</p>
<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
    &quot;&quot;&quot;Apply layer norm in fp32 for LingBot World 2 numerical parity.&quot;&quot;&quot;
    return super().forward(x.float()).type_as(x)</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanSelfAttention"><code>fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanSelfAttention</code></h2>
<pre class="doc-signature"><code>CausalWanSelfAttention(dim: int, num_heads: int, local_attn_size: int = -1, sink_size: int = 0, qk_norm: bool = True, eps: float = 1e-06)</code></pre>
<p>LingBot World 2 causal self-attention with rolling KV cache.</p>

<details><summary>Source</summary><pre><code>class CausalWanSelfAttention(nn.Module):
    &quot;&quot;&quot;LingBot World 2 causal self-attention with rolling KV cache.&quot;&quot;&quot;

    def __init__(
        self,
        dim: int,
        num_heads: int,
        local_attn_size: int = -1,
        sink_size: int = 0,
        qk_norm: bool = True,
        eps: float = 1e-6,
    ):
        super().__init__()
        assert dim % num_heads == 0
        self.dim = dim
        self.num_heads = num_heads
        self.head_dim = dim // num_heads
        attn_backend = get_attn_backend(
            self.head_dim,
            get_compute_dtype(),
            supported_attention_backends=(AttentionBackendEnum.FLASH_ATTN, AttentionBackendEnum.TORCH_SDPA),
        )
        backend_name = attn_backend.get_name()
        self.backend = backend_name_to_enum(backend_name)
        assert self.backend is not None, f&quot;Unsupported attention backend: &#123;backend_name&#125;&quot;
        self.local_attn_size = local_attn_size
        self.sink_size = sink_size
        self.qk_norm = qk_norm
        self.eps = eps
        self.q = nn.Linear(dim, dim)
        self.k = nn.Linear(dim, dim)
        self.v = nn.Linear(dim, dim)
        self.o = nn.Linear(dim, dim)
        self.norm_q = WanRMSNorm(dim, eps=eps) if qk_norm else nn.Identity()
        self.norm_k = WanRMSNorm(dim, eps=eps) if qk_norm else nn.Identity()

    def forward(
        self,
        x: torch.Tensor,
        seq_lens: torch.Tensor,
        grid_sizes: torch.Tensor,
        freqs: torch.Tensor,
        kv_cache: dict,
        current_start: int = 0,
        max_attention_size: int = 1_000_000,
        frame_seqlen: int | None = None,
        seq_lens_int: int | None = None,
    ) -&gt; torch.Tensor:
        &quot;&quot;&quot;Project QKV, update the rolling cache, and attend to its active window.&quot;&quot;&quot;
        b, s, n, d = *x.shape&#91;:2&#93;, self.num_heads, self.head_dim
        q = self.norm_q(self.q(x)).view(b, s, n, d)
        k = self.norm_k(self.k(x)).view(b, s, n, d)
        v = self.v(x).view(b, s, n, d)

        if frame_seqlen is None:
            frame_seqlen = math.prod(grid_sizes&#91;0&#93;&#91;1:&#93;).item()
        current_start_frame = current_start // frame_seqlen
        if seq_lens_int is None:
            seq_lens_int = int(seq_lens&#91;0&#93;.item() if seq_lens.dim() &gt; 0 else seq_lens.item())

        sp_size = get_sp_world_size()
        if sp_size &gt; 1:
            q = sequence_model_parallel_all_to_all_4D(q, scatter_dim=2, gather_dim=1)
            k = sequence_model_parallel_all_to_all_4D(k, scatter_dim=2, gather_dim=1)
            v = sequence_model_parallel_all_to_all_4D(v, scatter_dim=2, gather_dim=1)
            padded_seq_len = s * sp_size
            roped_query = causal_rope_apply(q, grid_sizes, freqs, start_frame=current_start_frame).type_as(v)
            roped_key = causal_rope_apply(k, grid_sizes, freqs, start_frame=current_start_frame).type_as(v)
            roped_query = roped_query&#91;:, :seq_lens_int&#93;
            roped_key = roped_key&#91;:, :seq_lens_int&#93;
            v = v&#91;:, :seq_lens_int&#93;
            num_new_tokens = seq_lens_int
        else:
            padded_seq_len = s
            roped_query = causal_rope_apply(q, grid_sizes, freqs, start_frame=current_start_frame).type_as(v)
            roped_key = causal_rope_apply(k, grid_sizes, freqs, start_frame=current_start_frame).type_as(v)
            num_new_tokens = roped_query.shape&#91;1&#93;

        current_end = current_start + num_new_tokens
        sink_tokens = self.sink_size * frame_seqlen
        kv_cache_size = kv_cache&#91;&quot;k&quot;&#93;.shape&#91;1&#93;

        if self.local_attn_size == -1:
            local_end_index = current_start + num_new_tokens
            local_start_index = current_start
            kv_cache&#91;&quot;k&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = roped_key
            kv_cache&#91;&quot;v&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = v
        elif (current_end
              &gt; kv_cache&#91;&quot;global_end_index&quot;&#93;.item()) and (num_new_tokens + kv_cache&#91;&quot;local_end_index&quot;&#93;.item()
                                                          &gt; kv_cache_size):
            num_evicted_tokens = num_new_tokens + kv_cache&#91;&quot;local_end_index&quot;&#93;.item() - kv_cache_size
            num_rolled_tokens = kv_cache&#91;&quot;local_end_index&quot;&#93;.item() - num_evicted_tokens - sink_tokens
            kv_cache&#91;&quot;k&quot;&#93;&#91;:, sink_tokens:sink_tokens +
                          num_rolled_tokens&#93; = kv_cache&#91;&quot;k&quot;&#93;&#91;:, sink_tokens + num_evicted_tokens:sink_tokens +
                                                             num_evicted_tokens + num_rolled_tokens&#93;.clone()
            kv_cache&#91;&quot;v&quot;&#93;&#91;:, sink_tokens:sink_tokens +
                          num_rolled_tokens&#93; = kv_cache&#91;&quot;v&quot;&#93;&#91;:, sink_tokens + num_evicted_tokens:sink_tokens +
                                                             num_evicted_tokens + num_rolled_tokens&#93;.clone()
            local_end_index = kv_cache&#91;&quot;local_end_index&quot;&#93;.item() + current_end - kv_cache&#91;&quot;global_end_index&quot;&#93;.item(
            ) - num_evicted_tokens
            local_start_index = local_end_index - num_new_tokens
            kv_cache&#91;&quot;k&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = roped_key
            kv_cache&#91;&quot;v&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = v
        else:
            local_end_index = kv_cache&#91;&quot;local_end_index&quot;&#93;.item() + current_end - kv_cache&#91;&quot;global_end_index&quot;&#93;.item()
            local_start_index = local_end_index - num_new_tokens
            kv_cache&#91;&quot;k&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = roped_key
            kv_cache&#91;&quot;v&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = v

        k_cache = kv_cache&#91;&quot;k&quot;&#93;&#91;:, max(0, local_end_index - max_attention_size):local_end_index&#93;
        v_cache = kv_cache&#91;&quot;v&quot;&#93;&#91;:, max(0, local_end_index - max_attention_size):local_end_index&#93;
        x = attention(roped_query, k_cache, v_cache, self.backend)
        kv_cache&#91;&quot;global_end_index&quot;&#93;.fill_(current_end)
        kv_cache&#91;&quot;local_end_index&quot;&#93;.fill_(local_end_index)

        if sp_size &gt; 1:
            sp_pad = padded_seq_len - seq_lens_int
            if sp_pad &gt; 0:
                x = torch.cat(&#91;x, x.new_zeros(b, sp_pad, x.size(2), d)&#93;, dim=1)
            x = sequence_model_parallel_all_to_all_4D(x, scatter_dim=1, gather_dim=2)
        return self.o(x.flatten(2))</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanSelfAttention.forward"><code>fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanSelfAttention.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor, seq_lens: torch.Tensor, grid_sizes: torch.Tensor, freqs: torch.Tensor, kv_cache: dict, current_start: int = 0, max_attention_size: int = 1000000, frame_seqlen: int | None = None, seq_lens_int: int | None = None) -&gt; torch.Tensor</code></pre>
<p>Project QKV, update the rolling cache, and attend to its active window.</p>
<details><summary>Source</summary><pre><code>def forward(
    self,
    x: torch.Tensor,
    seq_lens: torch.Tensor,
    grid_sizes: torch.Tensor,
    freqs: torch.Tensor,
    kv_cache: dict,
    current_start: int = 0,
    max_attention_size: int = 1_000_000,
    frame_seqlen: int | None = None,
    seq_lens_int: int | None = None,
) -&gt; torch.Tensor:
    &quot;&quot;&quot;Project QKV, update the rolling cache, and attend to its active window.&quot;&quot;&quot;
    b, s, n, d = *x.shape&#91;:2&#93;, self.num_heads, self.head_dim
    q = self.norm_q(self.q(x)).view(b, s, n, d)
    k = self.norm_k(self.k(x)).view(b, s, n, d)
    v = self.v(x).view(b, s, n, d)

    if frame_seqlen is None:
        frame_seqlen = math.prod(grid_sizes&#91;0&#93;&#91;1:&#93;).item()
    current_start_frame = current_start // frame_seqlen
    if seq_lens_int is None:
        seq_lens_int = int(seq_lens&#91;0&#93;.item() if seq_lens.dim() &gt; 0 else seq_lens.item())

    sp_size = get_sp_world_size()
    if sp_size &gt; 1:
        q = sequence_model_parallel_all_to_all_4D(q, scatter_dim=2, gather_dim=1)
        k = sequence_model_parallel_all_to_all_4D(k, scatter_dim=2, gather_dim=1)
        v = sequence_model_parallel_all_to_all_4D(v, scatter_dim=2, gather_dim=1)
        padded_seq_len = s * sp_size
        roped_query = causal_rope_apply(q, grid_sizes, freqs, start_frame=current_start_frame).type_as(v)
        roped_key = causal_rope_apply(k, grid_sizes, freqs, start_frame=current_start_frame).type_as(v)
        roped_query = roped_query&#91;:, :seq_lens_int&#93;
        roped_key = roped_key&#91;:, :seq_lens_int&#93;
        v = v&#91;:, :seq_lens_int&#93;
        num_new_tokens = seq_lens_int
    else:
        padded_seq_len = s
        roped_query = causal_rope_apply(q, grid_sizes, freqs, start_frame=current_start_frame).type_as(v)
        roped_key = causal_rope_apply(k, grid_sizes, freqs, start_frame=current_start_frame).type_as(v)
        num_new_tokens = roped_query.shape&#91;1&#93;

    current_end = current_start + num_new_tokens
    sink_tokens = self.sink_size * frame_seqlen
    kv_cache_size = kv_cache&#91;&quot;k&quot;&#93;.shape&#91;1&#93;

    if self.local_attn_size == -1:
        local_end_index = current_start + num_new_tokens
        local_start_index = current_start
        kv_cache&#91;&quot;k&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = roped_key
        kv_cache&#91;&quot;v&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = v
    elif (current_end
          &gt; kv_cache&#91;&quot;global_end_index&quot;&#93;.item()) and (num_new_tokens + kv_cache&#91;&quot;local_end_index&quot;&#93;.item()
                                                      &gt; kv_cache_size):
        num_evicted_tokens = num_new_tokens + kv_cache&#91;&quot;local_end_index&quot;&#93;.item() - kv_cache_size
        num_rolled_tokens = kv_cache&#91;&quot;local_end_index&quot;&#93;.item() - num_evicted_tokens - sink_tokens
        kv_cache&#91;&quot;k&quot;&#93;&#91;:, sink_tokens:sink_tokens +
                      num_rolled_tokens&#93; = kv_cache&#91;&quot;k&quot;&#93;&#91;:, sink_tokens + num_evicted_tokens:sink_tokens +
                                                         num_evicted_tokens + num_rolled_tokens&#93;.clone()
        kv_cache&#91;&quot;v&quot;&#93;&#91;:, sink_tokens:sink_tokens +
                      num_rolled_tokens&#93; = kv_cache&#91;&quot;v&quot;&#93;&#91;:, sink_tokens + num_evicted_tokens:sink_tokens +
                                                         num_evicted_tokens + num_rolled_tokens&#93;.clone()
        local_end_index = kv_cache&#91;&quot;local_end_index&quot;&#93;.item() + current_end - kv_cache&#91;&quot;global_end_index&quot;&#93;.item(
        ) - num_evicted_tokens
        local_start_index = local_end_index - num_new_tokens
        kv_cache&#91;&quot;k&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = roped_key
        kv_cache&#91;&quot;v&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = v
    else:
        local_end_index = kv_cache&#91;&quot;local_end_index&quot;&#93;.item() + current_end - kv_cache&#91;&quot;global_end_index&quot;&#93;.item()
        local_start_index = local_end_index - num_new_tokens
        kv_cache&#91;&quot;k&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = roped_key
        kv_cache&#91;&quot;v&quot;&#93;&#91;:, local_start_index:local_end_index&#93; = v

    k_cache = kv_cache&#91;&quot;k&quot;&#93;&#91;:, max(0, local_end_index - max_attention_size):local_end_index&#93;
    v_cache = kv_cache&#91;&quot;v&quot;&#93;&#91;:, max(0, local_end_index - max_attention_size):local_end_index&#93;
    x = attention(roped_query, k_cache, v_cache, self.backend)
    kv_cache&#91;&quot;global_end_index&quot;&#93;.fill_(current_end)
    kv_cache&#91;&quot;local_end_index&quot;&#93;.fill_(local_end_index)

    if sp_size &gt; 1:
        sp_pad = padded_seq_len - seq_lens_int
        if sp_pad &gt; 0:
            x = torch.cat(&#91;x, x.new_zeros(b, sp_pad, x.size(2), d)&#93;, dim=1)
        x = sequence_model_parallel_all_to_all_4D(x, scatter_dim=1, gather_dim=2)
    return self.o(x.flatten(2))</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.WanCrossAttention"><code>fastvideo.models.dits.lingbotworld2.causal_fast.WanCrossAttention</code></h2>
<pre class="doc-signature"><code>WanCrossAttention(dim: int, num_heads: int, local_attn_size: int = -1, sink_size: int = 0, qk_norm: bool = True, eps: float = 1e-06)</code></pre>
<p>LingBot World 2 cross-attention with reusable text K/V cache.</p>
<details><summary>Source</summary><pre><code>class WanCrossAttention(CausalWanSelfAttention):
    &quot;&quot;&quot;LingBot World 2 cross-attention with reusable text K/V cache.&quot;&quot;&quot;

    def forward(
        self,
        x: torch.Tensor,
        context: torch.Tensor,
        context_lens: torch.Tensor | None,
        crossattn_cache: dict | None = None,
        cross_attn_first_call: bool | None = None,
    ) -&gt; torch.Tensor:
        &quot;&quot;&quot;Attend hidden states to text context, populating cache on first use.&quot;&quot;&quot;
        b, n, d = x.size(0), self.num_heads, self.head_dim
        q = self.norm_q(self.q(x)).view(b, -1, n, d)
        if crossattn_cache is not None:
            is_first = crossattn_cache&#91;&quot;is_init&quot;&#93;.item(
            ) == 0 if cross_attn_first_call is None else cross_attn_first_call
            if is_first:
                crossattn_cache&#91;&quot;is_init&quot;&#93;.fill_(1)
                k = self.norm_k(self.k(context)).view(b, -1, n, d)
                v = self.v(context).view(b, -1, n, d)
                crossattn_cache&#91;&quot;k&quot;&#93;.copy_(k)
                crossattn_cache&#91;&quot;v&quot;&#93;.copy_(v)
            else:
                k = crossattn_cache&#91;&quot;k&quot;&#93;
                v = crossattn_cache&#91;&quot;v&quot;&#93;
        else:
            k = self.norm_k(self.k(context)).view(b, -1, n, d)
            v = self.v(context).view(b, -1, n, d)
        # Dispatch through `attention` so the TORCH_SDPA backend this model
        # advertises actually works; self-attention already does the same. The
        # SDPA path ignores `k_lens`, which is safe here because the caller
        # always passes `context_lens=None`.
        x = attention(q, k, v, self.backend, k_lens=context_lens)
        return self.o(x.flatten(2))</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.WanCrossAttention.forward"><code>fastvideo.models.dits.lingbotworld2.causal_fast.WanCrossAttention.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor, context: torch.Tensor, context_lens: torch.Tensor | None, crossattn_cache: dict | None = None, cross_attn_first_call: bool | None = None) -&gt; torch.Tensor</code></pre>
<p>Attend hidden states to text context, populating cache on first use.</p>
<details><summary>Source</summary><pre><code>def forward(
    self,
    x: torch.Tensor,
    context: torch.Tensor,
    context_lens: torch.Tensor | None,
    crossattn_cache: dict | None = None,
    cross_attn_first_call: bool | None = None,
) -&gt; torch.Tensor:
    &quot;&quot;&quot;Attend hidden states to text context, populating cache on first use.&quot;&quot;&quot;
    b, n, d = x.size(0), self.num_heads, self.head_dim
    q = self.norm_q(self.q(x)).view(b, -1, n, d)
    if crossattn_cache is not None:
        is_first = crossattn_cache&#91;&quot;is_init&quot;&#93;.item(
        ) == 0 if cross_attn_first_call is None else cross_attn_first_call
        if is_first:
            crossattn_cache&#91;&quot;is_init&quot;&#93;.fill_(1)
            k = self.norm_k(self.k(context)).view(b, -1, n, d)
            v = self.v(context).view(b, -1, n, d)
            crossattn_cache&#91;&quot;k&quot;&#93;.copy_(k)
            crossattn_cache&#91;&quot;v&quot;&#93;.copy_(v)
        else:
            k = crossattn_cache&#91;&quot;k&quot;&#93;
            v = crossattn_cache&#91;&quot;v&quot;&#93;
    else:
        k = self.norm_k(self.k(context)).view(b, -1, n, d)
        v = self.v(context).view(b, -1, n, d)
    # Dispatch through `attention` so the TORCH_SDPA backend this model
    # advertises actually works; self-attention already does the same. The
    # SDPA path ignores `k_lens`, which is safe here because the caller
    # always passes `context_lens=None`.
    x = attention(q, k, v, self.backend, k_lens=context_lens)
    return self.o(x.flatten(2))</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanAttentionBlock"><code>fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanAttentionBlock</code></h2>
<pre class="doc-signature"><code>CausalWanAttentionBlock(dim: int, ffn_dim: int, num_heads: int, local_attn_size: int = -1, sink_size: int = 0, qk_norm: bool = True, cross_attn_norm: bool = False, eps: float = 1e-06)</code></pre>
<p>One LingBot World 2 causal transformer block including camera injection.</p>

<details><summary>Source</summary><pre><code>class CausalWanAttentionBlock(nn.Module):
    &quot;&quot;&quot;One LingBot World 2 causal transformer block including camera injection.&quot;&quot;&quot;

    def __init__(
        self,
        dim: int,
        ffn_dim: int,
        num_heads: int,
        local_attn_size: int = -1,
        sink_size: int = 0,
        qk_norm: bool = True,
        cross_attn_norm: bool = False,
        eps: float = 1e-6,
    ):
        super().__init__()
        self.dim = dim
        self.ffn_dim = ffn_dim
        self.num_heads = num_heads
        self.local_attn_size = local_attn_size
        self.qk_norm = qk_norm
        self.cross_attn_norm = cross_attn_norm
        self.eps = eps
        self.norm1 = WanLayerNorm(dim, eps)
        self.self_attn = CausalWanSelfAttention(dim, num_heads, local_attn_size, sink_size, qk_norm, eps)
        self.norm3 = WanLayerNorm(dim, eps, elementwise_affine=True) if cross_attn_norm else nn.Identity()
        self.cross_attn = WanCrossAttention(dim, num_heads, qk_norm=qk_norm, eps=eps)
        self.norm2 = WanLayerNorm(dim, eps)
        self.ffn = nn.Sequential(nn.Linear(dim, ffn_dim), nn.GELU(approximate=&quot;tanh&quot;), nn.Linear(ffn_dim, dim))
        self.modulation = nn.Parameter(torch.randn(1, 6, dim) / dim**0.5)
        self.cam_injector_layer1 = nn.Linear(dim, dim)
        self.cam_injector_layer2 = nn.Linear(dim, dim)
        self.cam_scale_layer = nn.Linear(dim, dim)
        self.cam_shift_layer = nn.Linear(dim, dim)

    def forward(
        self,
        x: torch.Tensor,
        e: torch.Tensor,
        seq_lens: torch.Tensor,
        grid_sizes: torch.Tensor,
        freqs: torch.Tensor,
        context: torch.Tensor,
        context_lens: torch.Tensor | None,
        dit_cond_dict: dict&#91;str, Any&#93; | None = None,
        kv_cache: dict | None = None,
        crossattn_cache: dict | None = None,
        current_start: int = 0,
        max_attention_size: int = 1_000_000,
        frame_seqlen: int | None = None,
        cross_attn_first_call: bool | None = None,
        seq_lens_int: int | None = None,
    ) -&gt; torch.Tensor:
        &quot;&quot;&quot;Apply self-attention, camera modulation, cross-attention, and FFN.&quot;&quot;&quot;
        assert kv_cache is not None
        assert e.dtype == torch.float32
        with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
            e = (self.modulation.unsqueeze(0) + e).chunk(6, dim=2)

        y = self.self_attn(
            self.norm1(x).float() * (1 + e&#91;1&#93;.squeeze(2)) + e&#91;0&#93;.squeeze(2),
            seq_lens,
            grid_sizes,
            freqs,
            kv_cache,
            current_start,
            max_attention_size,
            frame_seqlen=frame_seqlen,
            seq_lens_int=seq_lens_int,
        )
        with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
            x = x + y * e&#91;2&#93;.squeeze(2)

        if dit_cond_dict is not None and &quot;c2ws_plucker_emb&quot; in dit_cond_dict:
            c2ws_plucker_emb = dit_cond_dict&#91;&quot;c2ws_plucker_emb&quot;&#93;
            c2ws_hidden_states = self.cam_injector_layer2(F.silu(self.cam_injector_layer1(c2ws_plucker_emb)))
            c2ws_hidden_states = c2ws_hidden_states + c2ws_plucker_emb
            x = (1.0 + self.cam_scale_layer(c2ws_hidden_states)) * x + self.cam_shift_layer(c2ws_hidden_states)

        x = x + self.cross_attn(
            self.norm3(x),
            context,
            context_lens,
            crossattn_cache=crossattn_cache,
            cross_attn_first_call=cross_attn_first_call,
        )
        y = self.ffn(self.norm2(x).float() * (1 + e&#91;4&#93;.squeeze(2)) + e&#91;3&#93;.squeeze(2))
        with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
            x = x + y * e&#91;5&#93;.squeeze(2)
        return x</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanAttentionBlock.forward"><code>fastvideo.models.dits.lingbotworld2.causal_fast.CausalWanAttentionBlock.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor, e: torch.Tensor, seq_lens: torch.Tensor, grid_sizes: torch.Tensor, freqs: torch.Tensor, context: torch.Tensor, context_lens: torch.Tensor | None, dit_cond_dict: dict&#91;str, Any&#93; | None = None, kv_cache: dict | None = None, crossattn_cache: dict | None = None, current_start: int = 0, max_attention_size: int = 1000000, frame_seqlen: int | None = None, cross_attn_first_call: bool | None = None, seq_lens_int: int | None = None) -&gt; torch.Tensor</code></pre>
<p>Apply self-attention, camera modulation, cross-attention, and FFN.</p>
<details><summary>Source</summary><pre><code>def forward(
    self,
    x: torch.Tensor,
    e: torch.Tensor,
    seq_lens: torch.Tensor,
    grid_sizes: torch.Tensor,
    freqs: torch.Tensor,
    context: torch.Tensor,
    context_lens: torch.Tensor | None,
    dit_cond_dict: dict&#91;str, Any&#93; | None = None,
    kv_cache: dict | None = None,
    crossattn_cache: dict | None = None,
    current_start: int = 0,
    max_attention_size: int = 1_000_000,
    frame_seqlen: int | None = None,
    cross_attn_first_call: bool | None = None,
    seq_lens_int: int | None = None,
) -&gt; torch.Tensor:
    &quot;&quot;&quot;Apply self-attention, camera modulation, cross-attention, and FFN.&quot;&quot;&quot;
    assert kv_cache is not None
    assert e.dtype == torch.float32
    with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
        e = (self.modulation.unsqueeze(0) + e).chunk(6, dim=2)

    y = self.self_attn(
        self.norm1(x).float() * (1 + e&#91;1&#93;.squeeze(2)) + e&#91;0&#93;.squeeze(2),
        seq_lens,
        grid_sizes,
        freqs,
        kv_cache,
        current_start,
        max_attention_size,
        frame_seqlen=frame_seqlen,
        seq_lens_int=seq_lens_int,
    )
    with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
        x = x + y * e&#91;2&#93;.squeeze(2)

    if dit_cond_dict is not None and &quot;c2ws_plucker_emb&quot; in dit_cond_dict:
        c2ws_plucker_emb = dit_cond_dict&#91;&quot;c2ws_plucker_emb&quot;&#93;
        c2ws_hidden_states = self.cam_injector_layer2(F.silu(self.cam_injector_layer1(c2ws_plucker_emb)))
        c2ws_hidden_states = c2ws_hidden_states + c2ws_plucker_emb
        x = (1.0 + self.cam_scale_layer(c2ws_hidden_states)) * x + self.cam_shift_layer(c2ws_hidden_states)

    x = x + self.cross_attn(
        self.norm3(x),
        context,
        context_lens,
        crossattn_cache=crossattn_cache,
        cross_attn_first_call=cross_attn_first_call,
    )
    y = self.ffn(self.norm2(x).float() * (1 + e&#91;4&#93;.squeeze(2)) + e&#91;3&#93;.squeeze(2))
    with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
        x = x + y * e&#91;5&#93;.squeeze(2)
    return x</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalHead"><code>fastvideo.models.dits.lingbotworld2.causal_fast.CausalHead</code></h2>
<pre class="doc-signature"><code>CausalHead(dim: int, out_dim: int, patch_size: tuple&#91;int, int, int&#93;, eps: float = 1e-06)</code></pre>
<p>Output projection head for LingBot World 2 causal-fast DiT.</p>

<details><summary>Source</summary><pre><code>class CausalHead(nn.Module):
    &quot;&quot;&quot;Output projection head for LingBot World 2 causal-fast DiT.&quot;&quot;&quot;

    def __init__(self, dim: int, out_dim: int, patch_size: tuple&#91;int, int, int&#93;, eps: float = 1e-6):
        super().__init__()
        self.dim = dim
        self.out_dim = out_dim
        self.patch_size = patch_size
        self.eps = eps
        self.norm = WanLayerNorm(dim, eps)
        self.head = nn.Linear(dim, math.prod(patch_size) * out_dim)
        self.modulation = nn.Parameter(torch.randn(1, 2, dim) / dim**0.5)

    def forward(self, x: torch.Tensor, e: torch.Tensor) -&gt; torch.Tensor:
        &quot;&quot;&quot;Normalize, modulate, and project hidden states to latent patches.&quot;&quot;&quot;
        assert e.dtype == torch.float32
        with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
            e = (self.modulation.unsqueeze(0) + e.unsqueeze(2)).chunk(2, dim=2)
            x = self.head(self.norm(x) * (1 + e&#91;1&#93;.squeeze(2)) + e&#91;0&#93;.squeeze(2))
        return x</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.CausalHead.forward"><code>fastvideo.models.dits.lingbotworld2.causal_fast.CausalHead.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor, e: torch.Tensor) -&gt; torch.Tensor</code></pre>
<p>Normalize, modulate, and project hidden states to latent patches.</p>
<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor, e: torch.Tensor) -&gt; torch.Tensor:
    &quot;&quot;&quot;Normalize, modulate, and project hidden states to latent patches.&quot;&quot;&quot;
    assert e.dtype == torch.float32
    with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
        e = (self.modulation.unsqueeze(0) + e.unsqueeze(2)).chunk(2, dim=2)
        x = self.head(self.norm(x) * (1 + e&#91;1&#93;.squeeze(2)) + e&#91;0&#93;.squeeze(2))
    return x</code></pre></details>
<h2 id="fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel"><code>fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel</code></h2>
<pre class="doc-signature"><code>LingBotWorld2CausalFastTransformer3DModel(config: LingBotWorld2CausalFastVideoConfig, hf_config: dict&#91;str, Any&#93;)</code></pre>
<p>Released LingBot World 2 14B causal-fast model with native FastVideo loading.</p>

<details><summary>Source</summary><pre><code>class LingBotWorld2CausalFastTransformer3DModel(BaseDiT):
    &quot;&quot;&quot;Released LingBot World 2 14B causal-fast model with native FastVideo loading.&quot;&quot;&quot;

    _fsdp_shard_conditions = &#91;is_blocks&#93;
    _compile_conditions: list = &#91;&#93;
    _supported_attention_backends = (
        AttentionBackendEnum.FLASH_ATTN,
        AttentionBackendEnum.TORCH_SDPA,
    )
    param_names_mapping: dict = &#123;&#125;
    reverse_param_names_mapping: dict = &#123;&#125;
    lora_param_names_mapping: dict = &#123;&#125;

    def __init__(self, config: LingBotWorld2CausalFastVideoConfig, hf_config: dict&#91;str, Any&#93;) -&gt; None:
        super().__init__(config=config, hf_config=hf_config)
        self.model_type = config.model_type
        self.patch_size = tuple(config.patch_size)
        self.text_len = config.text_len
        self.in_dim = config.in_dim
        self.dim = config.dim
        self.hidden_size = config.dim
        self.ffn_dim = config.ffn_dim
        self.freq_dim = config.freq_dim
        self.text_dim = config.text_dim
        self.out_dim = config.out_dim
        self.out_channels = config.out_dim
        self.num_heads = config.num_heads
        self.num_attention_heads = config.num_heads
        self.attention_head_dim = config.dim // config.num_heads
        self.num_layers = config.num_layers
        self.local_attn_size = config.local_attn_size
        self.sink_size = config.sink_size
        self.qk_norm = config.qk_norm
        self.cross_attn_norm = config.cross_attn_norm
        self.eps = config.eps
        self.num_channels_latents = config.out_dim

        control_dim = 6
        self.patch_embedding = nn.Conv3d(self.in_dim, self.dim, kernel_size=self.patch_size, stride=self.patch_size)
        self.patch_embedding_wancamctrl = nn.Linear(
            control_dim * 64 * self.patch_size&#91;0&#93; * self.patch_size&#91;1&#93; * self.patch_size&#91;2&#93;,
            self.dim,
        )
        self.c2ws_hidden_states_layer1 = nn.Linear(self.dim, self.dim)
        self.c2ws_hidden_states_layer2 = nn.Linear(self.dim, self.dim)
        self.text_embedding = nn.Sequential(
            nn.Linear(self.text_dim, self.dim),
            nn.GELU(approximate=&quot;tanh&quot;),
            nn.Linear(self.dim, self.dim),
        )
        self.time_embedding = nn.Sequential(
            nn.Linear(self.freq_dim, self.dim),
            nn.SiLU(),
            nn.Linear(self.dim, self.dim),
        )
        self.time_projection = nn.Sequential(nn.SiLU(), nn.Linear(self.dim, self.dim * 6))
        self.blocks = nn.ModuleList(&#91;
            CausalWanAttentionBlock(
                self.dim,
                self.ffn_dim,
                self.num_heads,
                self.local_attn_size,
                self.sink_size,
                self.qk_norm,
                self.cross_attn_norm,
                self.eps,
            ) for _ in range(self.num_layers)
        &#93;)
        self.head = CausalHead(self.dim, self.out_dim, self.patch_size, self.eps)
        self.freqs: torch.Tensor | None = None
        self.init_weights()
        self.__post_init__()

    def _get_freqs(self, device: torch.device) -&gt; torch.Tensor:
        &quot;&quot;&quot;Materialize the non-persistent RoPE frequency table outside meta init.&quot;&quot;&quot;
        if self.freqs is None or self.freqs.is_meta or self.freqs.device != device:
            d = self.dim // self.num_heads
            self.freqs = torch.cat(
                &#91;
                    rope_params(1024, d - 4 * (d // 6)),
                    rope_params(1024, 2 * (d // 6)),
                    rope_params(1024, 2 * (d // 6)),
                &#93;,
                dim=1,
            ).to(device)
        return self.freqs

    def forward(
        self,
        hidden_states: torch.Tensor | list&#91;torch.Tensor&#93; | None = None,
        encoder_hidden_states: torch.Tensor | list&#91;torch.Tensor&#93; | None = None,
        timestep: torch.Tensor | None = None,
        encoder_hidden_states_image: torch.Tensor | list&#91;torch.Tensor&#93; | None = None,
        guidance=None,
        *,
        x: list&#91;torch.Tensor&#93; | None = None,
        t: torch.Tensor | None = None,
        context: list&#91;torch.Tensor&#93; | torch.Tensor | None = None,
        seq_len: int | None = None,
        y: list&#91;torch.Tensor&#93; | None = None,
        dit_cond_dict: dict&#91;str, Any&#93; | None = None,
        kv_cache: list&#91;dict&#93; | None = None,
        crossattn_cache: list&#91;dict&#93; | None = None,
        current_start: int = 0,
        max_attention_size: int = 1_000_000,
        frame_seqlen: int | None = None,
        cross_attn_first_call: bool | None = None,
        **kwargs,
    ) -&gt; list&#91;torch.Tensor&#93;:
        &quot;&quot;&quot;Run one cached causal-fast DiT forward using the released LingBot World 2 ABI.&quot;&quot;&quot;
        del encoder_hidden_states_image, guidance, kwargs
        if x is None:
            assert isinstance(hidden_states, torch.Tensor)
            x = &#91;hidden_states&#91;0&#93;&#93;
        if t is None:
            assert timestep is not None
            t = timestep
        if context is None:
            context = encoder_hidden_states
        if isinstance(context, torch.Tensor):
            context = &#91;u for u in context&#93;
        assert context is not None
        assert seq_len is not None
        assert kv_cache is not None
        assert crossattn_cache is not None
        if self.model_type == &quot;i2v&quot;:
            assert y is not None

        device = self.patch_embedding.weight.device
        freqs = self._get_freqs(device)
        if y is not None:
            x = &#91;torch.cat(&#91;u, v&#93;, dim=0) for u, v in zip(x, y, strict=True)&#93;

        x = &#91;self.patch_embedding(u.unsqueeze(0)) for u in x&#93;
        grid_sizes = torch.stack(&#91;torch.tensor(u.shape&#91;2:&#93;, dtype=torch.long, device=u.device) for u in x&#93;)
        x = &#91;u.flatten(2).transpose(1, 2) for u in x&#93;
        seq_lens = torch.tensor(&#91;u.size(1) for u in x&#93;, dtype=torch.long, device=device)
        assert seq_lens.max() &lt;= seq_len
        x = torch.cat(x)
        seq_lens_int = int(seq_lens&#91;0&#93;.item())
        sp_size = get_sp_world_size()
        sp_rank = get_sp_parallel_rank()
        padded_seq_len = ((seq_lens_int + sp_size - 1) // sp_size) * sp_size
        sp_pad_len = padded_seq_len - seq_lens_int
        if sp_pad_len &gt; 0:
            x = torch.cat(&#91;x, x.new_zeros(x.size(0), sp_pad_len, x.size(2))&#93;, dim=1)

        if t.dim() == 1:
            t = t.expand(t.size(0), padded_seq_len)
        with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
            bt = t.size(0)
            t = t.flatten()
            e = self.time_embedding(
                sinusoidal_embedding_1d(self.freq_dim, t).unflatten(0, (bt, padded_seq_len)).float())
            e0 = self.time_projection(e).unflatten(2, (6, self.dim))

        context_lens = None
        context = self.text_embedding(
            torch.stack(&#91;torch.cat(&#91;u, u.new_zeros(self.text_len - u.size(0), u.size(1))&#93;) for u in context&#93;))

        if dit_cond_dict is not None and &quot;c2ws_plucker_emb&quot; in dit_cond_dict:
            c2ws_plucker_emb = dit_cond_dict&#91;&quot;c2ws_plucker_emb&quot;&#93;
            c2ws_plucker_emb = &#91;
                rearrange(
                    i,
                    &quot;1 c (f c1) (h c2) (w c3) -&gt; 1 (f h w) (c c1 c2 c3)&quot;,
                    c1=self.patch_size&#91;0&#93;,
                    c2=self.patch_size&#91;1&#93;,
                    c3=self.patch_size&#91;2&#93;,
                ) for i in c2ws_plucker_emb
            &#93;
            c2ws_plucker_emb = torch.cat(c2ws_plucker_emb, dim=1)
            c2ws_plucker_emb = self.patch_embedding_wancamctrl(c2ws_plucker_emb)
            c2ws_hidden_states = self.c2ws_hidden_states_layer2(F.silu(
                self.c2ws_hidden_states_layer1(c2ws_plucker_emb)))
            c2ws_plucker_emb = c2ws_plucker_emb + c2ws_hidden_states
            cam_len = c2ws_plucker_emb.size(1)
            if cam_len &lt; padded_seq_len:
                c2ws_plucker_emb = torch.cat(
                    &#91;
                        c2ws_plucker_emb,
                        c2ws_plucker_emb.new_zeros(
                            c2ws_plucker_emb.size(0),
                            padded_seq_len - cam_len,
                            c2ws_plucker_emb.size(2),
                        ),
                    &#93;,
                    dim=1,
                )
            elif cam_len &gt; padded_seq_len:
                c2ws_plucker_emb = c2ws_plucker_emb&#91;:, :padded_seq_len, :&#93;
            if sp_size &gt; 1:
                c2ws_plucker_emb = torch.chunk(c2ws_plucker_emb, sp_size, dim=1)&#91;sp_rank&#93;
            dit_cond_dict = dict(dit_cond_dict)
            dit_cond_dict&#91;&quot;c2ws_plucker_emb&quot;&#93; = c2ws_plucker_emb

        if sp_size &gt; 1:
            x = torch.chunk(x, sp_size, dim=1)&#91;sp_rank&#93;
            e = torch.chunk(e, sp_size, dim=1)&#91;sp_rank&#93;
            e0 = torch.chunk(e0, sp_size, dim=1)&#91;sp_rank&#93;

        for block_index, block in enumerate(self.blocks):
            x = block(
                x,
                e=e0,
                seq_lens=seq_lens,
                grid_sizes=grid_sizes,
                freqs=freqs,
                context=context,
                context_lens=context_lens,
                dit_cond_dict=dit_cond_dict,
                kv_cache=kv_cache&#91;block_index&#93;,
                crossattn_cache=crossattn_cache&#91;block_index&#93;,
                current_start=current_start,
                max_attention_size=max_attention_size,
                frame_seqlen=frame_seqlen,
                cross_attn_first_call=cross_attn_first_call,
                seq_lens_int=seq_lens_int,
            )

        x = self.head(x, e)
        if sp_size &gt; 1:
            x = sequence_model_parallel_all_gather(x, dim=1)
        return &#91;u.float() for u in self.unpatchify(x, grid_sizes)&#93;

    def unpatchify(self, x: torch.Tensor, grid_sizes: torch.Tensor) -&gt; list&#91;torch.Tensor&#93;:
        &quot;&quot;&quot;Reconstruct latent videos from flattened patch tokens.&quot;&quot;&quot;
        c = self.out_dim
        out = &#91;&#93;
        for u, v in zip(x, grid_sizes.tolist(), strict=True):
            u = u&#91;:math.prod(v)&#93;.view(*v, *self.patch_size, c)
            u = torch.einsum(&quot;fhwpqrc-&gt;cfphqwr&quot;, u)
            u = u.reshape(c, *&#91;i * j for i, j in zip(v, self.patch_size, strict=True)&#93;)
            out.append(u)
        return out

    def init_weights(self) -&gt; None:
        &quot;&quot;&quot;Initialize modules for non-meta construction; checkpoint load overwrites them.&quot;&quot;&quot;
        if self.patch_embedding.weight.is_meta:
            return
        for m in self.modules():
            if isinstance(m, nn.Linear):
                nn.init.xavier_uniform_(m.weight)
                if m.bias is not None:
                    nn.init.zeros_(m.bias)
        nn.init.xavier_uniform_(self.patch_embedding.weight.flatten(1))
        for m in self.text_embedding.modules():
            if isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, std=0.02)
        for m in self.time_embedding.modules():
            if isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, std=0.02)
        nn.init.zeros_(self.head.head.weight)</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel.forward"><code>fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel.forward</code></h3>
<pre class="doc-signature"><code>forward(hidden_states: torch.Tensor | list&#91;torch.Tensor&#93; | None = None, encoder_hidden_states: torch.Tensor | list&#91;torch.Tensor&#93; | None = None, timestep: torch.Tensor | None = None, encoder_hidden_states_image: torch.Tensor | list&#91;torch.Tensor&#93; | None = None, guidance = None, *, x: list&#91;torch.Tensor&#93; | None = None, t: torch.Tensor | None = None, context: list&#91;torch.Tensor&#93; | torch.Tensor | None = None, seq_len: int | None = None, y: list&#91;torch.Tensor&#93; | None = None, dit_cond_dict: dict&#91;str, Any&#93; | None = None, kv_cache: list&#91;dict&#93; | None = None, crossattn_cache: list&#91;dict&#93; | None = None, current_start: int = 0, max_attention_size: int = 1000000, frame_seqlen: int | None = None, cross_attn_first_call: bool | None = None, **kwargs) -&gt; list&#91;torch.Tensor&#93;</code></pre>
<p>Run one cached causal-fast DiT forward using the released LingBot World 2 ABI.</p>
<details><summary>Source</summary><pre><code>def forward(
    self,
    hidden_states: torch.Tensor | list&#91;torch.Tensor&#93; | None = None,
    encoder_hidden_states: torch.Tensor | list&#91;torch.Tensor&#93; | None = None,
    timestep: torch.Tensor | None = None,
    encoder_hidden_states_image: torch.Tensor | list&#91;torch.Tensor&#93; | None = None,
    guidance=None,
    *,
    x: list&#91;torch.Tensor&#93; | None = None,
    t: torch.Tensor | None = None,
    context: list&#91;torch.Tensor&#93; | torch.Tensor | None = None,
    seq_len: int | None = None,
    y: list&#91;torch.Tensor&#93; | None = None,
    dit_cond_dict: dict&#91;str, Any&#93; | None = None,
    kv_cache: list&#91;dict&#93; | None = None,
    crossattn_cache: list&#91;dict&#93; | None = None,
    current_start: int = 0,
    max_attention_size: int = 1_000_000,
    frame_seqlen: int | None = None,
    cross_attn_first_call: bool | None = None,
    **kwargs,
) -&gt; list&#91;torch.Tensor&#93;:
    &quot;&quot;&quot;Run one cached causal-fast DiT forward using the released LingBot World 2 ABI.&quot;&quot;&quot;
    del encoder_hidden_states_image, guidance, kwargs
    if x is None:
        assert isinstance(hidden_states, torch.Tensor)
        x = &#91;hidden_states&#91;0&#93;&#93;
    if t is None:
        assert timestep is not None
        t = timestep
    if context is None:
        context = encoder_hidden_states
    if isinstance(context, torch.Tensor):
        context = &#91;u for u in context&#93;
    assert context is not None
    assert seq_len is not None
    assert kv_cache is not None
    assert crossattn_cache is not None
    if self.model_type == &quot;i2v&quot;:
        assert y is not None

    device = self.patch_embedding.weight.device
    freqs = self._get_freqs(device)
    if y is not None:
        x = &#91;torch.cat(&#91;u, v&#93;, dim=0) for u, v in zip(x, y, strict=True)&#93;

    x = &#91;self.patch_embedding(u.unsqueeze(0)) for u in x&#93;
    grid_sizes = torch.stack(&#91;torch.tensor(u.shape&#91;2:&#93;, dtype=torch.long, device=u.device) for u in x&#93;)
    x = &#91;u.flatten(2).transpose(1, 2) for u in x&#93;
    seq_lens = torch.tensor(&#91;u.size(1) for u in x&#93;, dtype=torch.long, device=device)
    assert seq_lens.max() &lt;= seq_len
    x = torch.cat(x)
    seq_lens_int = int(seq_lens&#91;0&#93;.item())
    sp_size = get_sp_world_size()
    sp_rank = get_sp_parallel_rank()
    padded_seq_len = ((seq_lens_int + sp_size - 1) // sp_size) * sp_size
    sp_pad_len = padded_seq_len - seq_lens_int
    if sp_pad_len &gt; 0:
        x = torch.cat(&#91;x, x.new_zeros(x.size(0), sp_pad_len, x.size(2))&#93;, dim=1)

    if t.dim() == 1:
        t = t.expand(t.size(0), padded_seq_len)
    with torch.amp.autocast(&quot;cuda&quot;, dtype=torch.float32):
        bt = t.size(0)
        t = t.flatten()
        e = self.time_embedding(
            sinusoidal_embedding_1d(self.freq_dim, t).unflatten(0, (bt, padded_seq_len)).float())
        e0 = self.time_projection(e).unflatten(2, (6, self.dim))

    context_lens = None
    context = self.text_embedding(
        torch.stack(&#91;torch.cat(&#91;u, u.new_zeros(self.text_len - u.size(0), u.size(1))&#93;) for u in context&#93;))

    if dit_cond_dict is not None and &quot;c2ws_plucker_emb&quot; in dit_cond_dict:
        c2ws_plucker_emb = dit_cond_dict&#91;&quot;c2ws_plucker_emb&quot;&#93;
        c2ws_plucker_emb = &#91;
            rearrange(
                i,
                &quot;1 c (f c1) (h c2) (w c3) -&gt; 1 (f h w) (c c1 c2 c3)&quot;,
                c1=self.patch_size&#91;0&#93;,
                c2=self.patch_size&#91;1&#93;,
                c3=self.patch_size&#91;2&#93;,
            ) for i in c2ws_plucker_emb
        &#93;
        c2ws_plucker_emb = torch.cat(c2ws_plucker_emb, dim=1)
        c2ws_plucker_emb = self.patch_embedding_wancamctrl(c2ws_plucker_emb)
        c2ws_hidden_states = self.c2ws_hidden_states_layer2(F.silu(
            self.c2ws_hidden_states_layer1(c2ws_plucker_emb)))
        c2ws_plucker_emb = c2ws_plucker_emb + c2ws_hidden_states
        cam_len = c2ws_plucker_emb.size(1)
        if cam_len &lt; padded_seq_len:
            c2ws_plucker_emb = torch.cat(
                &#91;
                    c2ws_plucker_emb,
                    c2ws_plucker_emb.new_zeros(
                        c2ws_plucker_emb.size(0),
                        padded_seq_len - cam_len,
                        c2ws_plucker_emb.size(2),
                    ),
                &#93;,
                dim=1,
            )
        elif cam_len &gt; padded_seq_len:
            c2ws_plucker_emb = c2ws_plucker_emb&#91;:, :padded_seq_len, :&#93;
        if sp_size &gt; 1:
            c2ws_plucker_emb = torch.chunk(c2ws_plucker_emb, sp_size, dim=1)&#91;sp_rank&#93;
        dit_cond_dict = dict(dit_cond_dict)
        dit_cond_dict&#91;&quot;c2ws_plucker_emb&quot;&#93; = c2ws_plucker_emb

    if sp_size &gt; 1:
        x = torch.chunk(x, sp_size, dim=1)&#91;sp_rank&#93;
        e = torch.chunk(e, sp_size, dim=1)&#91;sp_rank&#93;
        e0 = torch.chunk(e0, sp_size, dim=1)&#91;sp_rank&#93;

    for block_index, block in enumerate(self.blocks):
        x = block(
            x,
            e=e0,
            seq_lens=seq_lens,
            grid_sizes=grid_sizes,
            freqs=freqs,
            context=context,
            context_lens=context_lens,
            dit_cond_dict=dit_cond_dict,
            kv_cache=kv_cache&#91;block_index&#93;,
            crossattn_cache=crossattn_cache&#91;block_index&#93;,
            current_start=current_start,
            max_attention_size=max_attention_size,
            frame_seqlen=frame_seqlen,
            cross_attn_first_call=cross_attn_first_call,
            seq_lens_int=seq_lens_int,
        )

    x = self.head(x, e)
    if sp_size &gt; 1:
        x = sequence_model_parallel_all_gather(x, dim=1)
    return &#91;u.float() for u in self.unpatchify(x, grid_sizes)&#93;</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel.unpatchify"><code>fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel.unpatchify</code></h3>
<pre class="doc-signature"><code>unpatchify(x: torch.Tensor, grid_sizes: torch.Tensor) -&gt; list&#91;torch.Tensor&#93;</code></pre>
<p>Reconstruct latent videos from flattened patch tokens.</p>
<details><summary>Source</summary><pre><code>def unpatchify(self, x: torch.Tensor, grid_sizes: torch.Tensor) -&gt; list&#91;torch.Tensor&#93;:
    &quot;&quot;&quot;Reconstruct latent videos from flattened patch tokens.&quot;&quot;&quot;
    c = self.out_dim
    out = &#91;&#93;
    for u, v in zip(x, grid_sizes.tolist(), strict=True):
        u = u&#91;:math.prod(v)&#93;.view(*v, *self.patch_size, c)
        u = torch.einsum(&quot;fhwpqrc-&gt;cfphqwr&quot;, u)
        u = u.reshape(c, *&#91;i * j for i, j in zip(v, self.patch_size, strict=True)&#93;)
        out.append(u)
    return out</code></pre></details>
<h3 id="fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel.init_weights"><code>fastvideo.models.dits.lingbotworld2.causal_fast.LingBotWorld2CausalFastTransformer3DModel.init_weights</code></h3>
<pre class="doc-signature"><code>init_weights() -&gt; None</code></pre>
<p>Initialize modules for non-meta construction; checkpoint load overwrites them.</p>
<details><summary>Source</summary><pre><code>def init_weights(self) -&gt; None:
    &quot;&quot;&quot;Initialize modules for non-meta construction; checkpoint load overwrites them.&quot;&quot;&quot;
    if self.patch_embedding.weight.is_meta:
        return
    for m in self.modules():
        if isinstance(m, nn.Linear):
            nn.init.xavier_uniform_(m.weight)
            if m.bias is not None:
                nn.init.zeros_(m.bias)
    nn.init.xavier_uniform_(self.patch_embedding.weight.flatten(1))
    for m in self.text_embedding.modules():
        if isinstance(m, nn.Linear):
            nn.init.normal_(m.weight, std=0.02)
    for m in self.time_embedding.modules():
        if isinstance(m, nn.Linear):
            nn.init.normal_(m.weight, std=0.02)
    nn.init.zeros_(self.head.head.weight)</code></pre></details>
</div>
