ArtificialGuyBR

Home / Blog / Models of 2026

Z-Image Turbo: Local Setup & Training

Learn to run Z-Image Turbo locally, build img2img and inpainting workflows in ComfyUI, and train character LoRAs with the ostris training adapter.

10 sources cited Models of 2026

TL;DR


Z-Image Turbo is a 6-billion-parameter distilled model from Tongyi-MAI that generates images in 8 NFEs (number of function evaluations) while matching or exceeding larger competitors on quality benchmarks. It ranks #1 among open-source models on the Artificial Analysis leaderboard and renders bilingual Chinese/English text natively. This guide covers local inference, ComfyUI img2img and inpainting workflows that avoid ControlNet, and a reproducible LoRA training recipe using the ostris de-distillation adapter.

Local inference setup

pip install git+https://github.com/huggingface/diffusers
import torch
from diffusers import ZImagePipeline

pipe = ZImagePipeline.from_pretrained(
    "Tongyi-MAI/Z-Image-Turbo",
    torch_dtype=torch.bfloat16,
).to("cuda")

prompt = "Young woman in red Hanfu, intricate embroidery, neon lightning-bolt lamp above palm, pagoda silhouette at night"

image = pipe(
    prompt=prompt,
    height=1024,
    width=1024,
    num_inference_steps=9,
    guidance_scale=0.0,
    generator=torch.Generator("cuda").manual_seed(42),
).images[0]

image.save("zimage_turbo.png")

Key settings: guidance_scale=0.0, num_inference_steps=9 (yields 8 forwards), bfloat16 on CUDA. The model fits in 16 GB VRAM; enable pipe.enable_model_cpu_offload() if you need to run on less.

Text encoder Qwen 3 Diffusion model z_image_turbo Sampler few steps VAE decode Distilled model: the guidance scale sits at 0 — there is no CFG pass to run. The three files live in different folders (text_encoders/, diffusion_models/, vae/); a "model not found" error is almost always a file in the wrong one.
Z-Image Turbo: what loads and in what order


ComfyUI img2img workflow (no ControlNet)

The Civitai community has converged on a lightweight img2img graph that controls input/output resolution without ControlNet. Start from the default ZiT Text to Image template and rewire as follows.

Nodes to add

NodePurpose
Load ImageSource image input
ImageScaleToMaxDimensionResize to a max edge while preserving aspect ratio
VAE EncodeEncode pixels to latent
Repeat Latent BatchMatch batch size for KSampler

Connections

  1. Load VAEVAE input of VAE Encode
  2. Load ImageImage input of ImageScaleToMaxDimension
  3. ImageScaleToMaxDimensionPixels input of VAE Encode
  4. VAE EncodeSamples input of Repeat Latent Batch
  5. Repeat Latent Batchlatent_image input of KSampler

ImageScaleToMaxDimension defaults to 512 max edge; raise it to 1024 or 1536 for higher fidelity. Supported upscale_method values: area, lanczos, bilinear, nearest-exact, bicubic.

Denoise sweet spot

Community testing reports the best img2img results with denoise 0.75–0.90 on the KSampler:

DenoiseBehaviorSource
< 0.75Strict adherence to source; only minor prompt-driven changeshttps://civitai.com/articles/24793/lightweight-image-to-image-workflow-for-z-image-turbo-no-controlnet-wip
0.75 – 0.90Balanced: keeps composition, follows prompt stronglyhttps://civitai.com/articles/24793/lightweight-image-to-image-workflow-for-z-image-turbo-no-controlnet-wip
> 0.90Drifts toward pure text-to-image; source influence fadeshttps://civitai.com/articles/24793/lightweight-image-to-image-workflow-for-z-image-turbo-no-controlnet-wip

Lower denoise = more source fidelity; higher = more prompt adherence. Start at 0.85 and adjust.


ComfyUI inpainting workflow

Inpainting uses the VAE Encode (for inpainting) node, which accepts both the image and a mask. The same ImageScaleToMaxDimension node can drive resolution.

Nodes to add

NodePurpose
Load ImageSource image + mask (alpha channel or separate mask input)
VAE Encode (for inpainting)Encodes pixels + mask to latent
Repeat Latent BatchBatch alignment for KSampler
ImageScaleToMaxDimension (optional)Resolution control

Connections

  1. Load ImagePixels + MaskVAE Encode (for inpainting)
  2. Load ImagePixelsImageScaleToMaxDimensionimageVAE Encode (for inpainting)
  3. Load VAEvaeVAE Encode (for inpainting)
  4. VAE Encode (for inpainting)Latent → **Repeat Latent BatchSamples`
  5. **Repeat Latent BatchLatent → **KSampler** → latent_image`

Optional: add the Image Compare node (via ComfyUI Manager) to preview image_a (scaled input) vs image_b (VAE Decode output) side-by-side.


Training a character LoRA with AI Toolkit

Z-Image Turbo is a distilled model; training a LoRA directly on it breaks the 8-step speed ("Turbo Drift"). The ostris zimage_turbo_training_adapter_v2 solves this: it is a 324 MB de-distillation LoRA trained on thousands of Z-Image Turbo outputs at lr 1e-5. You train your LoRA on top of this adapter, then **remove the adapter at inference` — your LoRA retains 8-step speed.

Prerequisites

ItemSpecSource
GPU (NVIDIA)12 GB VRAM minimum, 24 GB recommendedhttps://kawaiipromptlab.com/en/tutorials/lora-training-guide/
GPU (Apple Silicon)32 GB unified minimum, 64 GB recommendedhttps://kawaiipromptlab.com/en/tutorials/lora-training-guide/
Disk50 GB free (100 GB recommended)https://github.com/ostris/ai-toolkit
Python3.10+https://github.com/ostris/ai-toolkit
PyTorch2.0+ (2.8+ for MPS)https://github.com/ostris/ai-toolkit

Install AI Toolkit:

git clone https://github.com/ostris/ai-toolkit.git
cd ai-toolkit
git submodule update --init --recursive
pip install -r requirements.txt

Download the adapter:

huggingface-cli download ostris/zimage_turbo_training_adapter zimage_turbo_training_adapter_v2.safetensors
# Place in your weights folder, e.g. ./weights/zimage_turbo_training_adapter_v2.safetensors

Dataset preparation

Folder layout:

datasets/
└── my_character/
    ├── img_001.jpg
    ├── img_001.txt   # contains only: sks
    ├── img_002.jpg
    ├── img_002.txt   # contains only: sks
    └── ...

Training config (YAML)

Save as config/my_zimage_lora.yaml:

job: extension
config:
  name: "my_zimage_lora_v1"
  process:
    - type: "sd_trainer"
      training_folder: "output"
      device: "cuda:0"
      trigger_word: "sks"
      network:
        type: "lora"
        linear: 16
        linear_alpha: 16
      save:
        dtype: "float16"
        save_every: 250
        max_step_saves_to_keep: 4
      datasets:
        - folder_path: "/path/to/datasets/my_character"
          caption_ext: "txt"
          caption_dropout_rate: 0.05
          cache_latents_to_disk: true
          resolution: [512, 768, 1024]
      train:
        batch_size: 1
        steps: 3000
        gradient_accumulation_steps: 1
        train_unet: true
        train_text_encoder: false
        gradient_checkpointing: true
        noise_scheduler: "flowmatch"
        optimizer: "adamw8bit"
        lr: 1e-4
        ema_config:
          use_ema: true
          ema_decay: 0.99
        dtype: "bf16"
      model:
        name_or_path: "Tongyi-MAI/Z-Image-Turbo"
        arch: "zimage"
        assistant_lora_path: "./weights/zimage_turbo_training_adapter_v2.safetensors"
        quantize: true
      sample:
        sampler: "flowmatch"
        sample_every: 250
        width: 1024
        height: 1024
        prompts:
          - "sks, portrait photo, natural lighting"
        seed: 42
        guidance_scale: 1
        sample_steps: 8

Apple Silicon (MPS) adjustments: change device: &quot;mps:0&quot;, optimizer: &quot;adamw&quot; (adamw8bit is CUDA-only), quantize: false, add num_workers: 0 under datasets.

Run training

cd ai-toolkit
python run.py config/my_zimage_lora.yaml

Expected wall-clock times (3,000 steps):

HardwareTimeSource
RTX 5090 (RunPod)~15–22 min ($0.89/hr)https://x.com/ostrisai/status/1995504226295009558
RTX 4090~8–12 hourshttps://kawaiipromptlab.com/en/tutorials/lora-training-guide/
Apple M4 Pro (64 GB)~21 hourshttps://kawaiipromptlab.com/en/tutorials/lora-training-guide/

Monitor loss decay and sample images every 250 steps. Stop early if identity stabilizes; push to 5,000 steps only with clean data and captions.

Inference with the trained LoRA

ComfyUI: place my_zimage_lora_v1.safetensors in ComfyUI/models/loras/, add a Load LoRA node between the model loader and KSampler, set strength 0.8–1.0.

Python (Diffusers):

from diffusers import ZImagePipeline
import torch

pipe = ZImagePipeline.from_pretrained(
    "Tongyi-MAI/Z-Image-Turbo",
    torch_dtype=torch.bfloat16,
).to("cuda")

pipe.load_lora_weights("./output/my_zimage_lora_v1.safetensors", adapter_name="character")
pipe.set_adapters(["character"], adapter_weights=[0.9])

image = pipe(
    prompt="sks, portrait photo, natural lighting, 85mm lens",
    num_inference_steps=9,
    guidance_scale=0.0,
    width=1024,
    height=1024,
    generator=torch.Generator("cuda").manual_seed(42),
).images[0]
image.save("lora_result.png")

Critical: do not load the training adapter at inference. Your LoRA alone preserves the distilled 8-step speed.


Sources

URLContribution
https://github.com/Tongyi-MAI/Z-Image/blob/main/README.mdZ-Image Turbo model specs: 6B parameters, 8 NFEs, bilingual text rendering, sub-second latency
https://huggingface.co/ostris/zimage_turbo_training_adapterTraining adapter v2: 324 MB de-distillation LoRA, essential for LoRA training
https://huggingface.co/blog/content-and-code/training-a-lora-for-z-image-turboLoRA training config template, single-word captions for Z-Image Turbo
https://kawaiipromptlab.com/en/tutorials/lora-training-guide/Training recommendations: 70–80 images for character LoRAs, 1024×1024 resolution
https://docs.comfy.org/built-in-nodes/ImageScaleToMaxDimensionComfyUI node documentation for resolution control in img2img/inpainting
https://github.com/ostris/ai-toolkitAI Toolkit installation, YAML config format, training scheduler settings
https://x.com/ostrisai/status/1995504226295009558Training time benchmarks: 15–22 min on RTX 5090, $0.89/hr
https://civitai.com/articles/23863/z-image-turbo-lora-training-setup-full-precision-adapter-v2-massive-quality-jumpFull precision training benefits, v2 adapter quality improvements
https://civitai.com/articles/24764/simple-inpainting-workflow-for-z-image-turbo-comfyuiInpainting workflow node connections (VAE Encode for inpainting)
https://civitai.com/articles/24793/lightweight-image-to-image-workflow-for-z-image-turbo-no-controlnet-wipimg2img workflow: denoise 0.75–0.90 sweet spot, ImageScaleToMaxDimension usage

Common errors and fixes

SymptomLikely causeFixSource
LoRA has no visible effectTrigger word missing or misspelled in promptUse exact trigger token from captions (e.g., sks)https://huggingface.co/blog/content-and-code/training-a-lora-for-z-image-turbo
Faces look melted / "mushy"Over-captioning (descriptive sentences)Switch to single-word captions; re-trainhttps://huggingface.co/blog/content-and-code/training-a-lora-for-z-image-turbo
VRAM OOM on 12–16 GB cardsquantize: true not set, or batch > 1Enable quantization, batch_size: 1, gradient_checkpointing: truehttps://github.com/ostris/ai-toolkit
Training stalls at step 0Adapter path wrong or file missingVerify assistant_lora_path points to zimage_turbo_training_adapter_v2.safetensorshttps://huggingface.co/ostris/zimage_turbo_training_adapter
Generated images ignore promptDenoise too low (< 0.7) on img2imgRaise KSampler denoise to 0.75–0.90https://civitai.com/articles/24793/lightweight-image-to-image-workflow-for-z-image-turbo-no-controlnet-wip
Inpainting ignores maskMask not connected to VAE Encode (for inpainting)Wire Load ImageMaskVAE Encode (for inpainting)https://civitai.com/articles/24764/simple-inpainting-workflow-for-z-image-turbo-comfyui
LoRA file huge (> 500 MB)Rank set too high (e.g., 64)Use linear: 16, linear_alpha: 16https://huggingface.co/blog/content-and-code/training-a-lora-for-z-image-turbo
Training adapter not downloadedUsed v1 URL instead of v2Download zimage_turbo_training_adapter_v2.safetensors (324 MB) from ostris repohttps://huggingface.co/ostris/zimage_turbo_training_adapter

FAQ

How many images do I need for a character LoRA? 15+ images and 1,000+ steps for a working test; 70–80 images at 1024×1024 for production quality that reproduces skin texture.

What denoise value should I use for img2img? Start at 0.85. Below 0.75 keeps the source nearly unchanged; above 0.90 drifts toward pure text-to-image.

Do I need ControlNet for img2img or inpainting? No. The lightweight workflows above use only native ComfyUI nodes (ImageScaleToMaxDimension, VAE Encode, Repeat Latent Batch) and match ControlNet-style control for most use cases.

Why does my LoRA training produce artifacts after 4,000+ steps? The training adapter's de-distillation effect wears off over long runs. Stay at 3,000 steps unless you have pristine data and captions; beyond 5,000 steps distillation breakdown causes artifacts.

Can I train on Apple Silicon? Yes. Use device: mps:0, optimizer: adamw, quantize: false, num_workers: 0. Expect ~21 hours for 3,000 steps on M4 Pro 64 GB.

What resolution should I train at? Multi-resolution buckets [512, 768, 1024] with 1024×1024 as the target. The 512 bucket is the training bucket size, not a downscale of your dataset.

Is fp32 (full precision) required? Community reports fp32 saves eliminate hallucinations and boost quality at 5,000+ steps. If VRAM allows, keep quantize: false and save in fp32; otherwise bf16 with quantization is the practical default.

How do I remove the training adapter at inference? Simply don't load it. Your trained LoRA is the only extra weight you load on top of the base Z-Image Turbo model.