---
title: lingbotworld2_wanvae
---

<div class="python-reference">
<a id="fastvideo.models.vaes.lingbotworld2_wanvae-classes"></a>
<a id="fastvideo.models.vaes.lingbotworld2_wanvae.LingBotWorld2WanVAE-functions"></a>
<a id="fastvideo.models.vaes.lingbotworld2_wanvae.Upsample-functions"></a>
<a id="fastvideo.models.vaes.lingbotworld2_wanvae.Wan2_1_VAE-functions"></a>
<a id="fastvideo.models.vaes.lingbotworld2_wanvae"></a>

<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.CausalConv3d"><code>fastvideo.models.vaes.lingbotworld2_wanvae.CausalConv3d</code></h2>
<pre class="doc-signature"><code>CausalConv3d(*args, **kwargs)</code></pre>
<p>Causal 3d convolusion.</p>

<details><summary>Source</summary><pre><code>class CausalConv3d(nn.Conv3d):
    &quot;&quot;&quot;
    Causal 3d convolusion.
    &quot;&quot;&quot;

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._padding = (self.padding&#91;2&#93;, self.padding&#91;2&#93;, self.padding&#91;1&#93;, self.padding&#91;1&#93;, 2 * self.padding&#91;0&#93;, 0)
        self.padding = (0, 0, 0)

    def forward(self, x, cache_x=None):
        padding = list(self._padding)
        if cache_x is not None and self._padding&#91;4&#93; &gt; 0:
            cache_x = cache_x.to(x.device)
            x = torch.cat(&#91;cache_x, x&#93;, dim=2)
            padding&#91;4&#93; -= cache_x.shape&#91;2&#93;
        x = F.pad(x, padding)

        return super().forward(x)</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.CausalConv3d.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.CausalConv3d.forward</code></h3>
<pre class="doc-signature"><code>forward(x, cache_x = None)</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x, cache_x=None):
    padding = list(self._padding)
    if cache_x is not None and self._padding&#91;4&#93; &gt; 0:
        cache_x = cache_x.to(x.device)
        x = torch.cat(&#91;cache_x, x&#93;, dim=2)
        padding&#91;4&#93; -= cache_x.shape&#91;2&#93;
    x = F.pad(x, padding)

    return super().forward(x)</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.RMS_norm"><code>fastvideo.models.vaes.lingbotworld2_wanvae.RMS_norm</code></h2>
<pre class="doc-signature"><code>RMS_norm(dim, channel_first = True, images = True, bias = False)</code></pre>


<details><summary>Source</summary><pre><code>class RMS_norm(nn.Module):

    def __init__(self, dim, channel_first=True, images=True, bias=False):
        super().__init__()
        broadcastable_dims = (1, 1, 1) if not images else (1, 1)
        shape = (dim, *broadcastable_dims) if channel_first else (dim, )

        self.channel_first = channel_first
        self.scale = dim**0.5
        self.gamma = nn.Parameter(torch.ones(shape))
        self.bias = nn.Parameter(torch.zeros(shape)) if bias else 0.

    def forward(self, x):
        return F.normalize(x, dim=(1 if self.channel_first else -1)) * self.scale * self.gamma + self.bias</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.RMS_norm.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.RMS_norm.forward</code></h3>
<pre class="doc-signature"><code>forward(x)</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x):
    return F.normalize(x, dim=(1 if self.channel_first else -1)) * self.scale * self.gamma + self.bias</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.Upsample"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Upsample</code></h2>
<pre class="doc-signature"><code>Upsample()</code></pre>

<details><summary>Source</summary><pre><code>class Upsample(nn.Upsample):

    def forward(self, x):
        &quot;&quot;&quot;
        Fix bfloat16 support for nearest neighbor interpolation.
        &quot;&quot;&quot;
        return super().forward(x.float()).type_as(x)</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.Upsample.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Upsample.forward</code></h3>
<pre class="doc-signature"><code>forward(x)</code></pre>
<p>Fix bfloat16 support for nearest neighbor interpolation.</p>
<details><summary>Source</summary><pre><code>def forward(self, x):
    &quot;&quot;&quot;
    Fix bfloat16 support for nearest neighbor interpolation.
    &quot;&quot;&quot;
    return super().forward(x.float()).type_as(x)</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.Resample"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Resample</code></h2>
<pre class="doc-signature"><code>Resample(dim, mode)</code></pre>


<details><summary>Source</summary><pre><code>class Resample(nn.Module):

    def __init__(self, dim, mode):
        assert mode in (&#x27;none&#x27;, &#x27;upsample2d&#x27;, &#x27;upsample3d&#x27;, &#x27;downsample2d&#x27;, &#x27;downsample3d&#x27;)
        super().__init__()
        self.dim = dim
        self.mode = mode

        # layers
        if mode == &#x27;upsample2d&#x27;:
            self.resample = nn.Sequential(Upsample(scale_factor=(2., 2.), mode=&#x27;nearest-exact&#x27;),
                                          nn.Conv2d(dim, dim // 2, 3, padding=1))
        elif mode == &#x27;upsample3d&#x27;:
            self.resample = nn.Sequential(Upsample(scale_factor=(2., 2.), mode=&#x27;nearest-exact&#x27;),
                                          nn.Conv2d(dim, dim // 2, 3, padding=1))
            self.time_conv = CausalConv3d(dim, dim * 2, (3, 1, 1), padding=(1, 0, 0))

        elif mode == &#x27;downsample2d&#x27;:
            self.resample = nn.Sequential(nn.ZeroPad2d((0, 1, 0, 1)), nn.Conv2d(dim, dim, 3, stride=(2, 2)))
        elif mode == &#x27;downsample3d&#x27;:
            self.resample = nn.Sequential(nn.ZeroPad2d((0, 1, 0, 1)), nn.Conv2d(dim, dim, 3, stride=(2, 2)))
            self.time_conv = CausalConv3d(dim, dim, (3, 1, 1), stride=(2, 1, 1), padding=(0, 0, 0))

        else:
            self.resample = nn.Identity()

    def forward(self, x, feat_cache=None, feat_idx=&#91;0&#93;):
        b, c, t, h, w = x.size()
        if self.mode == &#x27;upsample3d&#x27;:
            if feat_cache is not None:
                idx = feat_idx&#91;0&#93;
                if feat_cache&#91;idx&#93; is None:
                    feat_cache&#91;idx&#93; = &#x27;Rep&#x27;
                    feat_idx&#91;0&#93; += 1
                else:

                    cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
                    if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None and feat_cache&#91;idx&#93; != &#x27;Rep&#x27;:
                        # cache last frame of last two chunk
                        cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;,
                                            dim=2)
                    if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None and feat_cache&#91;idx&#93; == &#x27;Rep&#x27;:
                        cache_x = torch.cat(&#91;torch.zeros_like(cache_x).to(cache_x.device), cache_x&#93;, dim=2)
                    if feat_cache&#91;idx&#93; == &#x27;Rep&#x27;:
                        x = self.time_conv(x)
                    else:
                        x = self.time_conv(x, feat_cache&#91;idx&#93;)
                    feat_cache&#91;idx&#93; = cache_x
                    feat_idx&#91;0&#93; += 1

                    x = x.reshape(b, 2, c, t, h, w)
                    x = torch.stack((x&#91;:, 0, :, :, :, :&#93;, x&#91;:, 1, :, :, :, :&#93;), 3)
                    x = x.reshape(b, c, t * 2, h, w)
        t = x.shape&#91;2&#93;
        x = rearrange(x, &#x27;b c t h w -&gt; (b t) c h w&#x27;)
        x = self.resample(x)
        x = rearrange(x, &#x27;(b t) c h w -&gt; b c t h w&#x27;, t=t)

        if self.mode == &#x27;downsample3d&#x27;:
            if feat_cache is not None:
                idx = feat_idx&#91;0&#93;
                if feat_cache&#91;idx&#93; is None:
                    feat_cache&#91;idx&#93; = x.clone()
                    feat_idx&#91;0&#93; += 1
                else:

                    cache_x = x&#91;:, :, -1:, :, :&#93;.clone()
                    # if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None and feat_cache&#91;idx&#93;!=&#x27;Rep&#x27;:
                    #     # cache last frame of last two chunk
                    #     cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;, dim=2)

                    x = self.time_conv(torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1:, :, :&#93;, x&#93;, 2))
                    feat_cache&#91;idx&#93; = cache_x
                    feat_idx&#91;0&#93; += 1
        return x

    def init_weight(self, conv):
        conv_weight = conv.weight
        nn.init.zeros_(conv_weight)
        c1, c2, t, h, w = conv_weight.size()
        one_matrix = torch.eye(c1, c2)
        init_matrix = one_matrix
        nn.init.zeros_(conv_weight)
        #conv_weight.data&#91;:,:,-1,1,1&#93; = init_matrix * 0.5
        conv_weight.data&#91;:, :, 1, 0, 0&#93; = init_matrix  #* 0.5
        conv.weight.data.copy_(conv_weight)
        nn.init.zeros_(conv.bias.data)

    def init_weight2(self, conv):
        conv_weight = conv.weight.data
        nn.init.zeros_(conv_weight)
        c1, c2, t, h, w = conv_weight.size()
        init_matrix = torch.eye(c1 // 2, c2)
        #init_matrix = repeat(init_matrix, &#x27;o ... -&gt; (o 2) ...&#x27;).permute(1,0,2).contiguous().reshape(c1,c2)
        conv_weight&#91;:c1 // 2, :, -1, 0, 0&#93; = init_matrix
        conv_weight&#91;c1 // 2:, :, -1, 0, 0&#93; = init_matrix
        conv.weight.data.copy_(conv_weight)
        nn.init.zeros_(conv.bias.data)</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.Resample.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Resample.forward</code></h3>
<pre class="doc-signature"><code>forward(x, feat_cache = None, feat_idx = &#91;0&#93;)</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x, feat_cache=None, feat_idx=&#91;0&#93;):
    b, c, t, h, w = x.size()
    if self.mode == &#x27;upsample3d&#x27;:
        if feat_cache is not None:
            idx = feat_idx&#91;0&#93;
            if feat_cache&#91;idx&#93; is None:
                feat_cache&#91;idx&#93; = &#x27;Rep&#x27;
                feat_idx&#91;0&#93; += 1
            else:

                cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
                if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None and feat_cache&#91;idx&#93; != &#x27;Rep&#x27;:
                    # cache last frame of last two chunk
                    cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;,
                                        dim=2)
                if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None and feat_cache&#91;idx&#93; == &#x27;Rep&#x27;:
                    cache_x = torch.cat(&#91;torch.zeros_like(cache_x).to(cache_x.device), cache_x&#93;, dim=2)
                if feat_cache&#91;idx&#93; == &#x27;Rep&#x27;:
                    x = self.time_conv(x)
                else:
                    x = self.time_conv(x, feat_cache&#91;idx&#93;)
                feat_cache&#91;idx&#93; = cache_x
                feat_idx&#91;0&#93; += 1

                x = x.reshape(b, 2, c, t, h, w)
                x = torch.stack((x&#91;:, 0, :, :, :, :&#93;, x&#91;:, 1, :, :, :, :&#93;), 3)
                x = x.reshape(b, c, t * 2, h, w)
    t = x.shape&#91;2&#93;
    x = rearrange(x, &#x27;b c t h w -&gt; (b t) c h w&#x27;)
    x = self.resample(x)
    x = rearrange(x, &#x27;(b t) c h w -&gt; b c t h w&#x27;, t=t)

    if self.mode == &#x27;downsample3d&#x27;:
        if feat_cache is not None:
            idx = feat_idx&#91;0&#93;
            if feat_cache&#91;idx&#93; is None:
                feat_cache&#91;idx&#93; = x.clone()
                feat_idx&#91;0&#93; += 1
            else:

                cache_x = x&#91;:, :, -1:, :, :&#93;.clone()
                # if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None and feat_cache&#91;idx&#93;!=&#x27;Rep&#x27;:
                #     # cache last frame of last two chunk
                #     cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;, dim=2)

                x = self.time_conv(torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1:, :, :&#93;, x&#93;, 2))
                feat_cache&#91;idx&#93; = cache_x
                feat_idx&#91;0&#93; += 1
    return x</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.Resample.init_weight"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Resample.init_weight</code></h3>
<pre class="doc-signature"><code>init_weight(conv)</code></pre>

<details><summary>Source</summary><pre><code>def init_weight(self, conv):
    conv_weight = conv.weight
    nn.init.zeros_(conv_weight)
    c1, c2, t, h, w = conv_weight.size()
    one_matrix = torch.eye(c1, c2)
    init_matrix = one_matrix
    nn.init.zeros_(conv_weight)
    #conv_weight.data&#91;:,:,-1,1,1&#93; = init_matrix * 0.5
    conv_weight.data&#91;:, :, 1, 0, 0&#93; = init_matrix  #* 0.5
    conv.weight.data.copy_(conv_weight)
    nn.init.zeros_(conv.bias.data)</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.Resample.init_weight2"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Resample.init_weight2</code></h3>
<pre class="doc-signature"><code>init_weight2(conv)</code></pre>

<details><summary>Source</summary><pre><code>def init_weight2(self, conv):
    conv_weight = conv.weight.data
    nn.init.zeros_(conv_weight)
    c1, c2, t, h, w = conv_weight.size()
    init_matrix = torch.eye(c1 // 2, c2)
    #init_matrix = repeat(init_matrix, &#x27;o ... -&gt; (o 2) ...&#x27;).permute(1,0,2).contiguous().reshape(c1,c2)
    conv_weight&#91;:c1 // 2, :, -1, 0, 0&#93; = init_matrix
    conv_weight&#91;c1 // 2:, :, -1, 0, 0&#93; = init_matrix
    conv.weight.data.copy_(conv_weight)
    nn.init.zeros_(conv.bias.data)</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.ResidualBlock"><code>fastvideo.models.vaes.lingbotworld2_wanvae.ResidualBlock</code></h2>
<pre class="doc-signature"><code>ResidualBlock(in_dim, out_dim, dropout = 0.0)</code></pre>


<details><summary>Source</summary><pre><code>class ResidualBlock(nn.Module):

    def __init__(self, in_dim, out_dim, dropout=0.0):
        super().__init__()
        self.in_dim = in_dim
        self.out_dim = out_dim

        # layers
        self.residual = nn.Sequential(RMS_norm(in_dim, images=False), nn.SiLU(),
                                      CausalConv3d(in_dim, out_dim, 3, padding=1), RMS_norm(out_dim, images=False),
                                      nn.SiLU(), nn.Dropout(dropout), CausalConv3d(out_dim, out_dim, 3, padding=1))
        self.shortcut = CausalConv3d(in_dim, out_dim, 1) \
            if in_dim != out_dim else nn.Identity()

    def forward(self, x, feat_cache=None, feat_idx=&#91;0&#93;):
        h = self.shortcut(x)
        for layer in self.residual:
            if isinstance(layer, CausalConv3d) and feat_cache is not None:
                idx = feat_idx&#91;0&#93;
                cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
                if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
                    # cache last frame of last two chunk
                    cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;,
                                        dim=2)
                x = layer(x, feat_cache&#91;idx&#93;)
                feat_cache&#91;idx&#93; = cache_x
                feat_idx&#91;0&#93; += 1
            else:
                x = layer(x)
        return x + h</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.ResidualBlock.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.ResidualBlock.forward</code></h3>
<pre class="doc-signature"><code>forward(x, feat_cache = None, feat_idx = &#91;0&#93;)</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x, feat_cache=None, feat_idx=&#91;0&#93;):
    h = self.shortcut(x)
    for layer in self.residual:
        if isinstance(layer, CausalConv3d) and feat_cache is not None:
            idx = feat_idx&#91;0&#93;
            cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
            if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
                # cache last frame of last two chunk
                cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;,
                                    dim=2)
            x = layer(x, feat_cache&#91;idx&#93;)
            feat_cache&#91;idx&#93; = cache_x
            feat_idx&#91;0&#93; += 1
        else:
            x = layer(x)
    return x + h</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.AttentionBlock"><code>fastvideo.models.vaes.lingbotworld2_wanvae.AttentionBlock</code></h2>
<pre class="doc-signature"><code>AttentionBlock(dim)</code></pre>
<p>Causal self-attention with a single head.</p>

<details><summary>Source</summary><pre><code>class AttentionBlock(nn.Module):
    &quot;&quot;&quot;
    Causal self-attention with a single head.
    &quot;&quot;&quot;

    def __init__(self, dim):
        super().__init__()
        self.dim = dim

        # layers
        self.norm = RMS_norm(dim)
        self.to_qkv = nn.Conv2d(dim, dim * 3, 1)
        self.proj = nn.Conv2d(dim, dim, 1)

        # zero out the last layer params
        nn.init.zeros_(self.proj.weight)

    def forward(self, x):
        identity = x
        b, c, t, h, w = x.size()
        x = rearrange(x, &#x27;b c t h w -&gt; (b t) c h w&#x27;)
        x = self.norm(x)
        # compute query, key, value
        q, k, v = self.to_qkv(x).reshape(b * t, 1, c * 3, -1).permute(0, 1, 3, 2).contiguous().chunk(3, dim=-1)

        # apply attention
        x = F.scaled_dot_product_attention(
            q,
            k,
            v,
        )
        x = x.squeeze(1).permute(0, 2, 1).reshape(b * t, c, h, w)

        # output
        x = self.proj(x)
        x = rearrange(x, &#x27;(b t) c h w-&gt; b c t h w&#x27;, t=t)
        return x + identity</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.AttentionBlock.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.AttentionBlock.forward</code></h3>
<pre class="doc-signature"><code>forward(x)</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x):
    identity = x
    b, c, t, h, w = x.size()
    x = rearrange(x, &#x27;b c t h w -&gt; (b t) c h w&#x27;)
    x = self.norm(x)
    # compute query, key, value
    q, k, v = self.to_qkv(x).reshape(b * t, 1, c * 3, -1).permute(0, 1, 3, 2).contiguous().chunk(3, dim=-1)

    # apply attention
    x = F.scaled_dot_product_attention(
        q,
        k,
        v,
    )
    x = x.squeeze(1).permute(0, 2, 1).reshape(b * t, c, h, w)

    # output
    x = self.proj(x)
    x = rearrange(x, &#x27;(b t) c h w-&gt; b c t h w&#x27;, t=t)
    return x + identity</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.Encoder3d"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Encoder3d</code></h2>
<pre class="doc-signature"><code>Encoder3d(dim = 128, z_dim = 4, dim_mult = &#91;1, 2, 4, 4&#93;, num_res_blocks = 2, attn_scales = &#91;&#93;, temperal_downsample = &#91;True, True, False&#93;, dropout = 0.0)</code></pre>


<details><summary>Source</summary><pre><code>class Encoder3d(nn.Module):

    def __init__(self,
                 dim=128,
                 z_dim=4,
                 dim_mult=&#91;1, 2, 4, 4&#93;,
                 num_res_blocks=2,
                 attn_scales=&#91;&#93;,
                 temperal_downsample=&#91;True, True, False&#93;,
                 dropout=0.0):
        super().__init__()
        self.dim = dim
        self.z_dim = z_dim
        self.dim_mult = dim_mult
        self.num_res_blocks = num_res_blocks
        self.attn_scales = attn_scales
        self.temperal_downsample = temperal_downsample

        # dimensions
        dims = &#91;dim * u for u in &#91;1&#93; + dim_mult&#93;
        scale = 1.0

        # init block
        self.conv1 = CausalConv3d(3, dims&#91;0&#93;, 3, padding=1)

        # downsample blocks
        downsamples = &#91;&#93;
        for i, (in_dim, out_dim) in enumerate(zip(dims&#91;:-1&#93;, dims&#91;1:&#93;)):
            # residual (+attention) blocks
            for _ in range(num_res_blocks):
                downsamples.append(ResidualBlock(in_dim, out_dim, dropout))
                if scale in attn_scales:
                    downsamples.append(AttentionBlock(out_dim))
                in_dim = out_dim

            # downsample block
            if i != len(dim_mult) - 1:
                mode = &#x27;downsample3d&#x27; if temperal_downsample&#91;i&#93; else &#x27;downsample2d&#x27;
                downsamples.append(Resample(out_dim, mode=mode))
                scale /= 2.0
        self.downsamples = nn.Sequential(*downsamples)

        # middle blocks
        self.middle = nn.Sequential(ResidualBlock(out_dim, out_dim, dropout), AttentionBlock(out_dim),
                                    ResidualBlock(out_dim, out_dim, dropout))

        # output blocks
        self.head = nn.Sequential(RMS_norm(out_dim, images=False), nn.SiLU(), CausalConv3d(out_dim, z_dim, 3,
                                                                                           padding=1))

    def forward(self, x, feat_cache=None, feat_idx=&#91;0&#93;):
        if feat_cache is not None:
            idx = feat_idx&#91;0&#93;
            cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
            if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
                # cache last frame of last two chunk
                cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;, dim=2)
            x = self.conv1(x, feat_cache&#91;idx&#93;)
            feat_cache&#91;idx&#93; = cache_x
            feat_idx&#91;0&#93; += 1
        else:
            x = self.conv1(x)

        ## downsamples
        for layer in self.downsamples:
            if feat_cache is not None:
                x = layer(x, feat_cache, feat_idx)
            else:
                x = layer(x)

        ## middle
        for layer in self.middle:
            if isinstance(layer, ResidualBlock) and feat_cache is not None:
                x = layer(x, feat_cache, feat_idx)
            else:
                x = layer(x)

        ## head
        for layer in self.head:
            if isinstance(layer, CausalConv3d) and feat_cache is not None:
                idx = feat_idx&#91;0&#93;
                cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
                if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
                    # cache last frame of last two chunk
                    cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;,
                                        dim=2)
                x = layer(x, feat_cache&#91;idx&#93;)
                feat_cache&#91;idx&#93; = cache_x
                feat_idx&#91;0&#93; += 1
            else:
                x = layer(x)
        return x</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.Encoder3d.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Encoder3d.forward</code></h3>
<pre class="doc-signature"><code>forward(x, feat_cache = None, feat_idx = &#91;0&#93;)</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x, feat_cache=None, feat_idx=&#91;0&#93;):
    if feat_cache is not None:
        idx = feat_idx&#91;0&#93;
        cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
        if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
            # cache last frame of last two chunk
            cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;, dim=2)
        x = self.conv1(x, feat_cache&#91;idx&#93;)
        feat_cache&#91;idx&#93; = cache_x
        feat_idx&#91;0&#93; += 1
    else:
        x = self.conv1(x)

    ## downsamples
    for layer in self.downsamples:
        if feat_cache is not None:
            x = layer(x, feat_cache, feat_idx)
        else:
            x = layer(x)

    ## middle
    for layer in self.middle:
        if isinstance(layer, ResidualBlock) and feat_cache is not None:
            x = layer(x, feat_cache, feat_idx)
        else:
            x = layer(x)

    ## head
    for layer in self.head:
        if isinstance(layer, CausalConv3d) and feat_cache is not None:
            idx = feat_idx&#91;0&#93;
            cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
            if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
                # cache last frame of last two chunk
                cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;,
                                    dim=2)
            x = layer(x, feat_cache&#91;idx&#93;)
            feat_cache&#91;idx&#93; = cache_x
            feat_idx&#91;0&#93; += 1
        else:
            x = layer(x)
    return x</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.Decoder3d"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Decoder3d</code></h2>
<pre class="doc-signature"><code>Decoder3d(dim = 128, z_dim = 4, dim_mult = &#91;1, 2, 4, 4&#93;, num_res_blocks = 2, attn_scales = &#91;&#93;, temperal_upsample = &#91;False, True, True&#93;, dropout = 0.0)</code></pre>


<details><summary>Source</summary><pre><code>class Decoder3d(nn.Module):

    def __init__(self,
                 dim=128,
                 z_dim=4,
                 dim_mult=&#91;1, 2, 4, 4&#93;,
                 num_res_blocks=2,
                 attn_scales=&#91;&#93;,
                 temperal_upsample=&#91;False, True, True&#93;,
                 dropout=0.0):
        super().__init__()
        self.dim = dim
        self.z_dim = z_dim
        self.dim_mult = dim_mult
        self.num_res_blocks = num_res_blocks
        self.attn_scales = attn_scales
        self.temperal_upsample = temperal_upsample

        # dimensions
        dims = &#91;dim * u for u in &#91;dim_mult&#91;-1&#93;&#93; + dim_mult&#91;::-1&#93;&#93;
        scale = 1.0 / 2**(len(dim_mult) - 2)

        # init block
        self.conv1 = CausalConv3d(z_dim, dims&#91;0&#93;, 3, padding=1)

        # middle blocks
        self.middle = nn.Sequential(ResidualBlock(dims&#91;0&#93;, dims&#91;0&#93;, dropout), AttentionBlock(dims&#91;0&#93;),
                                    ResidualBlock(dims&#91;0&#93;, dims&#91;0&#93;, dropout))

        # upsample blocks
        upsamples = &#91;&#93;
        for i, (in_dim, out_dim) in enumerate(zip(dims&#91;:-1&#93;, dims&#91;1:&#93;)):
            # residual (+attention) blocks
            if i == 1 or i == 2 or i == 3:
                in_dim = in_dim // 2
            for _ in range(num_res_blocks + 1):
                upsamples.append(ResidualBlock(in_dim, out_dim, dropout))
                if scale in attn_scales:
                    upsamples.append(AttentionBlock(out_dim))
                in_dim = out_dim

            # upsample block
            if i != len(dim_mult) - 1:
                mode = &#x27;upsample3d&#x27; if temperal_upsample&#91;i&#93; else &#x27;upsample2d&#x27;
                upsamples.append(Resample(out_dim, mode=mode))
                scale *= 2.0
        self.upsamples = nn.Sequential(*upsamples)

        # output blocks
        self.head = nn.Sequential(RMS_norm(out_dim, images=False), nn.SiLU(), CausalConv3d(out_dim, 3, 3, padding=1))

    def forward(self, x, feat_cache=None, feat_idx=&#91;0&#93;):
        ## conv1
        if feat_cache is not None:
            idx = feat_idx&#91;0&#93;
            cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
            if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
                # cache last frame of last two chunk
                cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;, dim=2)
            x = self.conv1(x, feat_cache&#91;idx&#93;)
            feat_cache&#91;idx&#93; = cache_x
            feat_idx&#91;0&#93; += 1
        else:
            x = self.conv1(x)

        ## middle
        for layer in self.middle:
            if isinstance(layer, ResidualBlock) and feat_cache is not None:
                x = layer(x, feat_cache, feat_idx)
            else:
                x = layer(x)

        ## upsamples
        for layer in self.upsamples:
            if feat_cache is not None:
                x = layer(x, feat_cache, feat_idx)
            else:
                x = layer(x)

        ## head
        for layer in self.head:
            if isinstance(layer, CausalConv3d) and feat_cache is not None:
                idx = feat_idx&#91;0&#93;
                cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
                if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
                    # cache last frame of last two chunk
                    cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;,
                                        dim=2)
                x = layer(x, feat_cache&#91;idx&#93;)
                feat_cache&#91;idx&#93; = cache_x
                feat_idx&#91;0&#93; += 1
            else:
                x = layer(x)
        return x</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.Decoder3d.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Decoder3d.forward</code></h3>
<pre class="doc-signature"><code>forward(x, feat_cache = None, feat_idx = &#91;0&#93;)</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x, feat_cache=None, feat_idx=&#91;0&#93;):
    ## conv1
    if feat_cache is not None:
        idx = feat_idx&#91;0&#93;
        cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
        if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
            # cache last frame of last two chunk
            cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;, dim=2)
        x = self.conv1(x, feat_cache&#91;idx&#93;)
        feat_cache&#91;idx&#93; = cache_x
        feat_idx&#91;0&#93; += 1
    else:
        x = self.conv1(x)

    ## middle
    for layer in self.middle:
        if isinstance(layer, ResidualBlock) and feat_cache is not None:
            x = layer(x, feat_cache, feat_idx)
        else:
            x = layer(x)

    ## upsamples
    for layer in self.upsamples:
        if feat_cache is not None:
            x = layer(x, feat_cache, feat_idx)
        else:
            x = layer(x)

    ## head
    for layer in self.head:
        if isinstance(layer, CausalConv3d) and feat_cache is not None:
            idx = feat_idx&#91;0&#93;
            cache_x = x&#91;:, :, -CACHE_T:, :, :&#93;.clone()
            if cache_x.shape&#91;2&#93; &lt; 2 and feat_cache&#91;idx&#93; is not None:
                # cache last frame of last two chunk
                cache_x = torch.cat(&#91;feat_cache&#91;idx&#93;&#91;:, :, -1, :, :&#93;.unsqueeze(2).to(cache_x.device), cache_x&#93;,
                                    dim=2)
            x = layer(x, feat_cache&#91;idx&#93;)
            feat_cache&#91;idx&#93; = cache_x
            feat_idx&#91;0&#93; += 1
        else:
            x = layer(x)
    return x</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.count_conv3d"><code>fastvideo.models.vaes.lingbotworld2_wanvae.count_conv3d</code></h2>
<pre class="doc-signature"><code>count_conv3d(model)</code></pre>

<details><summary>Source</summary><pre><code>def count_conv3d(model):
    count = 0
    for m in model.modules():
        if isinstance(m, CausalConv3d):
            count += 1
    return count</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_"><code>fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_</code></h2>
<pre class="doc-signature"><code>WanVAE_(dim = 128, z_dim = 4, dim_mult = &#91;1, 2, 4, 4&#93;, num_res_blocks = 2, attn_scales = &#91;&#93;, temperal_downsample = &#91;True, True, False&#93;, dropout = 0.0)</code></pre>


<details><summary>Source</summary><pre><code>class WanVAE_(nn.Module):

    def __init__(self,
                 dim=128,
                 z_dim=4,
                 dim_mult=&#91;1, 2, 4, 4&#93;,
                 num_res_blocks=2,
                 attn_scales=&#91;&#93;,
                 temperal_downsample=&#91;True, True, False&#93;,
                 dropout=0.0):
        super().__init__()
        self.dim = dim
        self.z_dim = z_dim
        self.dim_mult = dim_mult
        self.num_res_blocks = num_res_blocks
        self.attn_scales = attn_scales
        self.temperal_downsample = temperal_downsample
        self.temperal_upsample = temperal_downsample&#91;::-1&#93;

        # modules
        self.encoder = Encoder3d(dim, z_dim * 2, dim_mult, num_res_blocks, attn_scales, self.temperal_downsample,
                                 dropout)
        self.conv1 = CausalConv3d(z_dim * 2, z_dim * 2, 1)
        self.conv2 = CausalConv3d(z_dim, z_dim, 1)
        self.decoder = Decoder3d(dim, z_dim, dim_mult, num_res_blocks, attn_scales, self.temperal_upsample, dropout)

    def forward(self, x):
        mu, log_var = self.encode(x)
        z = self.reparameterize(mu, log_var)
        x_recon = self.decode(z)
        return x_recon, mu, log_var

    def encode(self, x, scale):
        self.clear_cache()
        ## cache
        t = x.shape&#91;2&#93;
        iter_ = 1 + (t - 1) // 4
        for i in range(iter_):
            self._enc_conv_idx = &#91;0&#93;
            if i == 0:
                out = self.encoder(x&#91;:, :, :1, :, :&#93;, feat_cache=self._enc_feat_map, feat_idx=self._enc_conv_idx)
            else:
                out_ = self.encoder(x&#91;:, :, 1 + 4 * (i - 1):1 + 4 * i, :, :&#93;,
                                    feat_cache=self._enc_feat_map,
                                    feat_idx=self._enc_conv_idx)
                out = torch.cat(&#91;out, out_&#93;, 2)
        mu, log_var = self.conv1(out).chunk(2, dim=1)
        if isinstance(scale&#91;0&#93;, torch.Tensor):
            mu = (mu - scale&#91;0&#93;.view(1, self.z_dim, 1, 1, 1)) * scale&#91;1&#93;.view(1, self.z_dim, 1, 1, 1)
        else:
            mu = (mu - scale&#91;0&#93;) * scale&#91;1&#93;
        self.clear_cache()
        return mu

    def decode(self, z, scale):
        self.clear_cache()
        # z: &#91;b,c,t,h,w&#93;
        if isinstance(scale&#91;0&#93;, torch.Tensor):
            z = z / scale&#91;1&#93;.view(1, self.z_dim, 1, 1, 1) + scale&#91;0&#93;.view(1, self.z_dim, 1, 1, 1)
        else:
            z = z / scale&#91;1&#93; + scale&#91;0&#93;
        iter_ = z.shape&#91;2&#93;
        x = self.conv2(z)
        for i in range(iter_):
            self._conv_idx = &#91;0&#93;
            if i == 0:
                out = self.decoder(x&#91;:, :, i:i + 1, :, :&#93;, feat_cache=self._feat_map, feat_idx=self._conv_idx)
            else:
                out_ = self.decoder(x&#91;:, :, i:i + 1, :, :&#93;, feat_cache=self._feat_map, feat_idx=self._conv_idx)
                out = torch.cat(&#91;out, out_&#93;, 2)
        self.clear_cache()
        return out

    def reparameterize(self, mu, log_var):
        std = torch.exp(0.5 * log_var)
        eps = torch.randn_like(std)
        return eps * std + mu

    def sample(self, imgs, deterministic=False):
        mu, log_var = self.encode(imgs)
        if deterministic:
            return mu
        std = torch.exp(0.5 * log_var.clamp(-30.0, 20.0))
        return mu + std * torch.randn_like(std)

    def clear_cache(self):
        self._conv_num = count_conv3d(self.decoder)
        self._conv_idx = &#91;0&#93;
        self._feat_map = &#91;None&#93; * self._conv_num
        #cache encode
        self._enc_conv_num = count_conv3d(self.encoder)
        self._enc_conv_idx = &#91;0&#93;
        self._enc_feat_map = &#91;None&#93; * self._enc_conv_num</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.forward"><code>fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.forward</code></h3>
<pre class="doc-signature"><code>forward(x)</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x):
    mu, log_var = self.encode(x)
    z = self.reparameterize(mu, log_var)
    x_recon = self.decode(z)
    return x_recon, mu, log_var</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.encode"><code>fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.encode</code></h3>
<pre class="doc-signature"><code>encode(x, scale)</code></pre>

<details><summary>Source</summary><pre><code>def encode(self, x, scale):
    self.clear_cache()
    ## cache
    t = x.shape&#91;2&#93;
    iter_ = 1 + (t - 1) // 4
    for i in range(iter_):
        self._enc_conv_idx = &#91;0&#93;
        if i == 0:
            out = self.encoder(x&#91;:, :, :1, :, :&#93;, feat_cache=self._enc_feat_map, feat_idx=self._enc_conv_idx)
        else:
            out_ = self.encoder(x&#91;:, :, 1 + 4 * (i - 1):1 + 4 * i, :, :&#93;,
                                feat_cache=self._enc_feat_map,
                                feat_idx=self._enc_conv_idx)
            out = torch.cat(&#91;out, out_&#93;, 2)
    mu, log_var = self.conv1(out).chunk(2, dim=1)
    if isinstance(scale&#91;0&#93;, torch.Tensor):
        mu = (mu - scale&#91;0&#93;.view(1, self.z_dim, 1, 1, 1)) * scale&#91;1&#93;.view(1, self.z_dim, 1, 1, 1)
    else:
        mu = (mu - scale&#91;0&#93;) * scale&#91;1&#93;
    self.clear_cache()
    return mu</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.decode"><code>fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.decode</code></h3>
<pre class="doc-signature"><code>decode(z, scale)</code></pre>

<details><summary>Source</summary><pre><code>def decode(self, z, scale):
    self.clear_cache()
    # z: &#91;b,c,t,h,w&#93;
    if isinstance(scale&#91;0&#93;, torch.Tensor):
        z = z / scale&#91;1&#93;.view(1, self.z_dim, 1, 1, 1) + scale&#91;0&#93;.view(1, self.z_dim, 1, 1, 1)
    else:
        z = z / scale&#91;1&#93; + scale&#91;0&#93;
    iter_ = z.shape&#91;2&#93;
    x = self.conv2(z)
    for i in range(iter_):
        self._conv_idx = &#91;0&#93;
        if i == 0:
            out = self.decoder(x&#91;:, :, i:i + 1, :, :&#93;, feat_cache=self._feat_map, feat_idx=self._conv_idx)
        else:
            out_ = self.decoder(x&#91;:, :, i:i + 1, :, :&#93;, feat_cache=self._feat_map, feat_idx=self._conv_idx)
            out = torch.cat(&#91;out, out_&#93;, 2)
    self.clear_cache()
    return out</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.reparameterize"><code>fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.reparameterize</code></h3>
<pre class="doc-signature"><code>reparameterize(mu, log_var)</code></pre>

<details><summary>Source</summary><pre><code>def reparameterize(self, mu, log_var):
    std = torch.exp(0.5 * log_var)
    eps = torch.randn_like(std)
    return eps * std + mu</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.sample"><code>fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.sample</code></h3>
<pre class="doc-signature"><code>sample(imgs, deterministic = False)</code></pre>

<details><summary>Source</summary><pre><code>def sample(self, imgs, deterministic=False):
    mu, log_var = self.encode(imgs)
    if deterministic:
        return mu
    std = torch.exp(0.5 * log_var.clamp(-30.0, 20.0))
    return mu + std * torch.randn_like(std)</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.clear_cache"><code>fastvideo.models.vaes.lingbotworld2_wanvae.WanVAE_.clear_cache</code></h3>
<pre class="doc-signature"><code>clear_cache()</code></pre>

<details><summary>Source</summary><pre><code>def clear_cache(self):
    self._conv_num = count_conv3d(self.decoder)
    self._conv_idx = &#91;0&#93;
    self._feat_map = &#91;None&#93; * self._conv_num
    #cache encode
    self._enc_conv_num = count_conv3d(self.encoder)
    self._enc_conv_idx = &#91;0&#93;
    self._enc_feat_map = &#91;None&#93; * self._enc_conv_num</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.Wan2_1_VAE"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Wan2_1_VAE</code></h2>
<pre class="doc-signature"><code>Wan2_1_VAE(z_dim = 16, vae_pth = &#x27;cache/vae_step_411000.pth&#x27;, dtype = torch.float, device = &#x27;cuda&#x27;)</code></pre>


<details><summary>Source</summary><pre><code>class Wan2_1_VAE:

    def __init__(self, z_dim=16, vae_pth=&#x27;cache/vae_step_411000.pth&#x27;, dtype=torch.float, device=&quot;cuda&quot;):
        self.dtype = dtype
        self.device = device

        mean = &#91;
            -0.7571, -0.7089, -0.9113, 0.1075, -0.1745, 0.9653, -0.1517, 1.5508, 0.4134, -0.0715, 0.5517, -0.3632,
            -0.1922, -0.9497, 0.2503, -0.2921
        &#93;
        std = &#91;
            2.8184, 1.4541, 2.3275, 2.6558, 1.2196, 1.7708, 2.6052, 2.0743, 3.2687, 2.1526, 2.8652, 1.5579, 1.6382,
            1.1253, 2.8251, 1.9160
        &#93;
        self.mean = torch.tensor(mean, dtype=dtype, device=device)
        self.std = torch.tensor(std, dtype=dtype, device=device)
        self.scale = &#91;self.mean, 1.0 / self.std&#93;

        # init model
        self.model = _video_vae(
            pretrained_path=vae_pth,
            z_dim=z_dim,
        ).eval().requires_grad_(False).to(device)

    def encode(self, videos):
        &quot;&quot;&quot;
        videos: A list of videos each with shape &#91;C, T, H, W&#93;.
        &quot;&quot;&quot;
        with amp.autocast(dtype=self.dtype):
            return &#91;self.model.encode(u.unsqueeze(0), self.scale).float().squeeze(0) for u in videos&#93;

    def decode(self, zs):
        with amp.autocast(dtype=self.dtype):
            return &#91;self.model.decode(u.unsqueeze(0), self.scale).float().clamp_(-1, 1).squeeze(0) for u in zs&#93;</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.Wan2_1_VAE.encode"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Wan2_1_VAE.encode</code></h3>
<pre class="doc-signature"><code>encode(videos)</code></pre>
<p>videos: A list of videos each with shape [C, T, H, W].</p>
<details><summary>Source</summary><pre><code>def encode(self, videos):
    &quot;&quot;&quot;
    videos: A list of videos each with shape &#91;C, T, H, W&#93;.
    &quot;&quot;&quot;
    with amp.autocast(dtype=self.dtype):
        return &#91;self.model.encode(u.unsqueeze(0), self.scale).float().squeeze(0) for u in videos&#93;</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.Wan2_1_VAE.decode"><code>fastvideo.models.vaes.lingbotworld2_wanvae.Wan2_1_VAE.decode</code></h3>
<pre class="doc-signature"><code>decode(zs)</code></pre>

<details><summary>Source</summary><pre><code>def decode(self, zs):
    with amp.autocast(dtype=self.dtype):
        return &#91;self.model.decode(u.unsqueeze(0), self.scale).float().clamp_(-1, 1).squeeze(0) for u in zs&#93;</code></pre></details>
<h2 id="fastvideo.models.vaes.lingbotworld2_wanvae.LingBotWorld2WanVAE"><code>fastvideo.models.vaes.lingbotworld2_wanvae.LingBotWorld2WanVAE</code></h2>
<pre class="doc-signature"><code>LingBotWorld2WanVAE(config, checkpoint_path = None, dtype = torch.float)</code></pre>
<p>FastVideo-facing wrapper around the exact LingBot World 2 Wan2.1 VAE computation.</p>
<p>Load the official LingBot World 2 VAE weights and expose FastVideo VAE APIs.</p>
<details><summary>Source</summary><pre><code>class LingBotWorld2WanVAE(nn.Module):
    &quot;&quot;&quot;FastVideo-facing wrapper around the exact LingBot World 2 Wan2.1 VAE computation.&quot;&quot;&quot;

    handles_latent_denorm = True

    def __init__(self, config, checkpoint_path=None, dtype=torch.float):
        &quot;&quot;&quot;Load the official LingBot World 2 VAE weights and expose FastVideo VAE APIs.&quot;&quot;&quot;
        super().__init__()
        self.config = config
        self.dtype = dtype
        z_dim = int(getattr(config, &quot;z_dim&quot;, 16))
        mean = torch.tensor(getattr(config, &quot;latents_mean&quot;), dtype=dtype)
        std = torch.tensor(getattr(config, &quot;latents_std&quot;), dtype=dtype)
        self.register_buffer(&quot;shift_factor&quot;, mean.view(1, z_dim, 1, 1, 1), persistent=False)
        self.register_buffer(&quot;scaling_factor&quot;, (1.0 / std).view(1, z_dim, 1, 1, 1), persistent=False)
        self.scale = &#91;mean, 1.0 / std&#93;

        if checkpoint_path is None:
            self.model = WanVAE_(dim=96,
                                 z_dim=z_dim,
                                 dim_mult=&#91;1, 2, 4, 4&#93;,
                                 num_res_blocks=2,
                                 attn_scales=&#91;&#93;,
                                 temperal_downsample=&#91;False, True, True&#93;,
                                 dropout=0.0)
        else:
            self.model = _video_vae(pretrained_path=checkpoint_path, z_dim=z_dim)
        self.model.eval().requires_grad_(False)

    def _scale_for(self, device: torch.device) -&gt; list&#91;torch.Tensor&#93;:
        &quot;&quot;&quot;Return source VAE scale tensors on the active device.&quot;&quot;&quot;
        return &#91;u.to(device) for u in self.scale&#93;

    def encode(self, videos: torch.Tensor):
        &quot;&quot;&quot;Encode `&#91;B,C,T,H,W&#93;` videos and return a FastVideo-style mean tensor.&quot;&quot;&quot;
        if videos.ndim != 5:
            raise ValueError(f&quot;LingBotWorld2WanVAE.encode expects 5D input, got &#123;videos.shape&#125;&quot;)
        scale = self._scale_for(videos.device)
        latents = &#91;&#93;
        with amp.autocast(dtype=self.dtype):
            for video in videos:
                latent = self.model.encode(video.unsqueeze(0), scale).float().squeeze(0)
                latents.append(latent)
        normalized = torch.stack(latents, dim=0)
        return SimpleNamespace(mean=normalized)

    def decode(self, latents: torch.Tensor) -&gt; torch.Tensor:
        &quot;&quot;&quot;Decode normalized LingBot World 2 latents to clamped `&#91;-1,1&#93;` video tensors.&quot;&quot;&quot;
        if latents.ndim != 5:
            raise ValueError(f&quot;LingBotWorld2WanVAE.decode expects 5D input, got &#123;latents.shape&#125;&quot;)
        scale = self._scale_for(latents.device)
        videos = &#91;&#93;
        with amp.autocast(dtype=self.dtype):
            for latent in latents:
                video = self.model.decode(latent.unsqueeze(0), scale).float().clamp_(-1, 1).squeeze(0)
                videos.append(video)
        return torch.stack(videos, dim=0)</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.LingBotWorld2WanVAE.encode"><code>fastvideo.models.vaes.lingbotworld2_wanvae.LingBotWorld2WanVAE.encode</code></h3>
<pre class="doc-signature"><code>encode(videos: torch.Tensor)</code></pre>
<p>Encode <code>[B,C,T,H,W]</code> videos and return a FastVideo-style mean tensor.</p>
<details><summary>Source</summary><pre><code>def encode(self, videos: torch.Tensor):
    &quot;&quot;&quot;Encode `&#91;B,C,T,H,W&#93;` videos and return a FastVideo-style mean tensor.&quot;&quot;&quot;
    if videos.ndim != 5:
        raise ValueError(f&quot;LingBotWorld2WanVAE.encode expects 5D input, got &#123;videos.shape&#125;&quot;)
    scale = self._scale_for(videos.device)
    latents = &#91;&#93;
    with amp.autocast(dtype=self.dtype):
        for video in videos:
            latent = self.model.encode(video.unsqueeze(0), scale).float().squeeze(0)
            latents.append(latent)
    normalized = torch.stack(latents, dim=0)
    return SimpleNamespace(mean=normalized)</code></pre></details>
<h3 id="fastvideo.models.vaes.lingbotworld2_wanvae.LingBotWorld2WanVAE.decode"><code>fastvideo.models.vaes.lingbotworld2_wanvae.LingBotWorld2WanVAE.decode</code></h3>
<pre class="doc-signature"><code>decode(latents: torch.Tensor) -&gt; torch.Tensor</code></pre>
<p>Decode normalized LingBot World 2 latents to clamped <code>[-1,1]</code> video tensors.</p>
<details><summary>Source</summary><pre><code>def decode(self, latents: torch.Tensor) -&gt; torch.Tensor:
    &quot;&quot;&quot;Decode normalized LingBot World 2 latents to clamped `&#91;-1,1&#93;` video tensors.&quot;&quot;&quot;
    if latents.ndim != 5:
        raise ValueError(f&quot;LingBotWorld2WanVAE.decode expects 5D input, got &#123;latents.shape&#125;&quot;)
    scale = self._scale_for(latents.device)
    videos = &#91;&#93;
    with amp.autocast(dtype=self.dtype):
        for latent in latents:
            video = self.model.decode(latent.unsqueeze(0), scale).float().clamp_(-1, 1).squeeze(0)
            videos.append(video)
    return torch.stack(videos, dim=0)</code></pre></details>
</div>
