Model Merge ZIT
Blend 30 transformer layers by hand
- model1
- model2
- MODEL
SDXL has ModelMergeBlocks - a node that lets you blend two checkpoints per-block, so you can take the composition from model A and the aesthetics from model B without a blunt 50/50. Z-Image Turbo (the 6B model the community crowned as SDXL's successor) never had an equivalent, because its architecture is a 30-layer transformer, not a UNet with named input/middle/output blocks. ModelMergeZIT is that equivalent: per-block merging for Z-Image Turbo / Lumina2 models, with the 30 layers bundled into four meaningful groups so you don't have to know what layer 19 does to use it.
How it works
You wire in two models and a set of ratios. The ratio is the language of the whole node: 0.0 = use model1, 1.0 = use model2, anything between is a blend. The layers are grouped by what they actually do in a diffusion transformer:
- early (layers 0–5) - translation/encoding: turning your prompt into the model's internal representation.
- lowmid (layers 6–14) - composition/layout: where the structure of the image lives.
- upmid (layers 15–23) - details/attributes: fine-grained features.
- late (layers 24–29) - refinement/aesthetics: style and final polish.
Plus the non-layer pieces: x_embedder (patch embedding), t_embedder (timestep embedding), cap_embedder (text embedding), refiners (context + noise refiner), final (final layer + norm), and other (padding tokens etc.). Every one has a ratio slider, default 1.0 - which in this node's convention means "use model2 for this block." So the first thing you'll do is flip the ones you care about.
There's a granularity selector that changes the whole personality: grouped (default) gives you the four group sliders plus the component sliders - the original ModelMergeZIT behavior; blocks exposes all 30 layer_0…layer_29 sliders individually - the original ModelMergeZITBlocks behavior, folded into the same node. Start grouped; drop to blocks when you've identified a specific layer range and want to move just one.
Output: MODEL, ready for a KSampler - or better, a DonutModelSave node, because per-block merges are worth keeping.
Practical strategy
The standard recipe for a Z-Image merge: put your base (usually Z-Image Turbo) on model1 and your style/character model on model2, then think in terms of the four groups. Want the base's structure with the other model's look? Pull lowmid toward 0 (keep model1's composition) and leave late at 1 (model2's aesthetics). The group tooltips map the architecture's real job to each range, which is the entire reason to use this over a blind average.
Two caveats. Merging Z-Image models is still more art than science - the community consensus on ZiT merging is younger and thinner than SDXL's, so expect to iterate and A/B. And it's memory-hungry to have two 6B models loaded at once; if you're on a 12GB card, expect to be tight. Start with granularity = grouped so you're only moving four levers, and only descend to per-layer when the grouped result tells you where the problem lives.
Install
Part of ComfyUI-DonutNodes: ComfyUI Manager → search "DonutNodes" → install → restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/DonutsDelivery/ComfyUI-DonutNodes.git donutnodes
cd donutnodes
python -m pip install -r requirements.txt
Pack dependencies (opencv-python-headless, scipy, matplotlib, psutil, tqdm, requests) only - the merge itself is pure tensor math on models you already have. No model downloads.
Inputs (47)
| Name | Type | Default | Description |
|---|---|---|---|
| model1 | MODEL | — | |
| model2 | MODEL | — | |
| early | FLOAT | 1.000–1 | Layers 0-5: Translation/encoding |
| lowmid | FLOAT | 1.000–1 | Layers 6-14: Composition/layout |
| upmid | FLOAT | 1.000–1 | Layers 15-23: Details/attributes |
| late | FLOAT | 1.000–1 | Layers 24-29: Refinement/aesthetics |
| x_embedder | FLOAT | 1.000–1 | Patch embedding (converts image patches to tokens) |
| t_embedder | FLOAT | 1.000–1 | Timestep embedding |
| cap_embedder | FLOAT | 1.000–1 | Caption/text embedding |
| refiners | FLOAT | 1.000–1 | context_refiner + noise_refiner |
| final | FLOAT | 1.000–1 | final_layer + norm_final |
| other | FLOAT | 1.000–1 | Remaining (pad tokens, etc.) |
| granularityopt | COMBO | grouped | grouped: per-group ratios (original ModelMergeZIT). blocks: per-layer ratios (original ModelMergeZITBlocks). |
| layer_0opt | FLOAT | 1.000–1 | Layer 0: Translation/encoding |
| layer_1opt | FLOAT | 1.000–1 | Layer 1: Translation/encoding |
| layer_2opt | FLOAT | 1.000–1 | Layer 2: Translation/encoding |
| layer_3opt | FLOAT | 1.000–1 | Layer 3: Translation/encoding |
| layer_4opt | FLOAT | 1.000–1 | Layer 4: Translation/encoding |
| layer_5opt | FLOAT | 1.000–1 | Layer 5: Translation/encoding |
| layer_6opt | FLOAT | 1.000–1 | Layer 6: Composition/layout |
| layer_7opt | FLOAT | 1.000–1 | Layer 7: Composition/layout |
| layer_8opt | FLOAT | 1.000–1 | Layer 8: Composition/layout |
| layer_9opt | FLOAT | 1.000–1 | Layer 9: Composition/layout |
| layer_10opt | FLOAT | 1.000–1 | Layer 10: Composition/layout |
| layer_11opt | FLOAT | 1.000–1 | Layer 11: Composition/layout |
| layer_12opt | FLOAT | 1.000–1 | Layer 12: Composition/layout |
| layer_13opt | FLOAT | 1.000–1 | Layer 13: Composition/layout |
| layer_14opt | FLOAT | 1.000–1 | Layer 14: Composition/layout |
| layer_15opt | FLOAT | 1.000–1 | Layer 15: Details/attributes |
| layer_16opt | FLOAT | 1.000–1 | Layer 16: Details/attributes |
| layer_17opt | FLOAT | 1.000–1 | Layer 17: Details/attributes |
| layer_18opt | FLOAT | 1.000–1 | Layer 18: Details/attributes |
| layer_19opt | FLOAT | 1.000–1 | Layer 19: Details/attributes |
| layer_20opt | FLOAT | 1.000–1 | Layer 20: Details/attributes |
| layer_21opt | FLOAT | 1.000–1 | Layer 21: Details/attributes |
| layer_22opt | FLOAT | 1.000–1 | Layer 22: Details/attributes |
| layer_23opt | FLOAT | 1.000–1 | Layer 23: Details/attributes |
| layer_24opt | FLOAT | 1.000–1 | Layer 24: Refinement/aesthetics |
| layer_25opt | FLOAT | 1.000–1 | Layer 25: Refinement/aesthetics |
| layer_26opt | FLOAT | 1.000–1 | Layer 26: Refinement/aesthetics |
| layer_27opt | FLOAT | 1.000–1 | Layer 27: Refinement/aesthetics |
| layer_28opt | FLOAT | 1.000–1 | Layer 28: Refinement/aesthetics |
| layer_29opt | FLOAT | 1.000–1 | Layer 29: Refinement/aesthetics |
| context_refineropt | FLOAT | 1.000–1 | Context refinement |
| noise_refineropt | FLOAT | 1.000–1 | Noise refinement |
| final_layeropt | FLOAT | 1.000–1 | Final output layer |
| norm_finalopt | FLOAT | 1.000–1 | Final normalization |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |