madebyollin/taeqi2_1

🤗 Hugging Face 来源mit31 MBother✓ 1 个校验和今天更新
一条命令提交

在你的模型文件夹旁边运行它。它会制作种子、将文件与 Hugging Face 比对,然后提交。你只需开始做种,并粘贴你账户中的密钥。它只读取你的文件,绝不修改。如果愿意,可以先阅读脚本。

curl -fsSL https://pirateface.co/package.sh | bash -s -- --repo madebyollin/taeqi2_1 ./model-folder
需要做种者 →

🍰 Tiny AutoEncoder for Qwen Image 2.1

TAEQI2.1 is very tiny autoencoder which uses the same "latent API" as Qwen Image 2.1's VAE. TAEQI2.1 is useful for real-time previewing of the Qwen Image 2.1 generation process, as well as general resource-constrained encoding/decoding. Like the Qwen Image 2.1 VAE, TAEQI2.1 uses 16x spatial compression, 64 latent channels, and RGBA images.

This repo contains .safetensors versions of the TAEQI2.1 weights.

Using in 🧨 diffusers

NOTE: Like TAEF2, TAEQI2.1's architecture isn't properly integrated into Diffusers yet. So for now you'll want some wrapper code:

pip install git+https://www.github.com/huggingface/diffusers # needed for Qwen Image 2.1 support
wget -nc -nv https://raw.githubusercontent.com/madebyollin/taesd/refs/heads/main/taesd.py -O taesd.py
wget -nc -nv https://huggingface.co/madebyollin/taeqi2_1/resolve/main/taeqi2_1.safetensors -O taeqi2_1.safetensors
# Construction
from taesd import TAESD
import torch
import safetensors.torch as stt
from diffusers.utils.accelerate_utils import apply_forward_hook

def convert_diffusers_sd_to_taesd(sd):
    out = {}
    for k, v in sd.items():
        encdec, _layers, index, *suffix = k.split(".")
        offset = 0
        if encdec == "decoder":
            offset = +1
        out[".".join([encdec, str(int(index)+offset), *suffix])] = v
    return out

class DotDict(dict):
    __getattr__ = dict.__getitem__
    __setattr__ = dict.__setitem__

class DiffusersTAEQI21Wrapper(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.dtype = torch.bfloat16
        self.taesd = TAESD(encoder_path=None, decoder_path=None, latent_channels=64, arch_variant="f16", image_channels=4).to(self.dtype)
        self.taesd.load_state_dict(convert_diffusers_sd_to_taesd(stt.load_file("taeqi2_1.safetensors")))
        # TAEQI2.1 consumes / produces normalized latents directly, so the pipeline's latent scale / shift should be a no-op
        self.config = DotDict(z_dim=64, latents_mean=[0.0] * 64, latents_std=[1.0] * 64)

    @apply_forward_hook
    def encode(self, x):
        # x is (B, 4, 1, H, W) RGBA in [-1, 1]; latents are (B, 64, 1, H/16, W/16)
        x = x.squeeze(2)
        latents = self.taesd.encoder(x.to(self.dtype).mul(0.5).add_(0.5)).to(x.dtype).unsqueeze(2)
        return DotDict(latent_dist=DotDict(sample=lambda generator=None: latents, mode=lambda: latents))

    @apply_forward_hook
    def decode(self, x, return_dict=True):
        # x is (B, 64, 1, H/16, W/16); output is (B, 4, 1, H, W) RGBA in [-1, 1]
        x = self.taesd.decoder(x.squeeze(2).to(self.dtype)).mul(2).sub_(1).clamp_(-1, 1).to(x.dtype).unsqueeze(2)
        return dict(sample=x) if return_dict else (x,)

taeqi2_1_diffusers = DiffusersTAEQI21Wrapper().eval().requires_grad_(False)

# Usage
from diffusers import QwenImage21Pipeline

device = "cuda"
dtype = torch.bfloat16

pipe = QwenImage21Pipeline.from_pretrained("Qwen/Qwen-Image-2.1", torch_dtype=dtype)
pipe.vae = taeqi2_1_diffusers
pipe.enable_model_cpu_offload() # pipe = pipe.to(device)

prompt = "A slice of delicious New York-style berry cheesecake"
image = pipe(
    prompt=prompt,
    height=1024,
    width=1024,
    generator=torch.Generator(device="cpu").manual_seed(0)
).images[0]
image.save("qwen-image-2.1.png")
image

Quality comparisons (see thread)