VAE Merge
Merge VAEs like you merge checkpoints — 13 strategies, block by block
- vae_a
- vae_b
- vae_c
- reference_image
- vae
- info
- recipe_json
- probe_report
Checkpoint merging is a whole cottage industry in Stable Diffusion; VAE merging is the neglected cousin. VAEMergeMEC is the node that finally gives it the same treatment: merge two or three VAEs with thirteen blend strategies, per-block weight sliders, a data-driven auto-alpha, a latent-space probe that reports reconstruction quality, and a recipe system so a good merge is reproducible. It's the heavyweight of the ComfyUI-CustomNodePacks pack's VAE Tools corner.
Before you get excited, the honest framing: VAE merging is a narrow tool. The KB's VAE panel notes that modern checkpoints bake their VAE in, and swapping or mixing decoders is mostly a relic of the SD 1.5 era (where the 840k decoder was a real upgrade) and a small set of specialist cases since. Where this genuinely earns its keep: you have two fine-tuned decoders - one renders better skin, one better text - and you want a blend, or you've found a VAE that decodes colors beautifully but smears texture, and want to keep the good part. That's exactly what per-block merging is for.
How it works
vae_a acts as the base (a deep-copied clone is returned, so your originals stay untouched), and vae_b (plus optional vae_c) is blended in. The merge_mode dropdown is where the strategies live - weighted_sum, add_difference, tensor_sum, triple_sum, slerp, sigmoid, geometric, max_abs, smooth_add_diff, distribution_xover, dare_ties (sparse delta + sign election), block_swap, and clamp_interp. add_difference, triple_sum, and smooth_add_diff need the third VAE.
Two features make it more than a glorified lerp:
use_blocks- per-block sliders (block_conv_in,block_0…block_3,block_mid, etc.) so you can, say, keep encoder blocks from A and decoder blocks from B. The block names correspond to the encoder/decoder structure the pack's Block Inspector reports on.auto_alpha- computes per-block cosine similarity between A and B, then biases weights toward A wherever the blocks disagree. It's a sensible default for "I don't know which blocks matter."
You also get brightness/contrast post-shifts on the decoder output (a quick way to fix a merged VAE that decodes slightly dark), and device (cpu default - safe; cuda is faster but eats VRAM).
The QA loop that makes it usable
The genuinely nice part is the reporting:
dry_run- skip the actual merge and get only the recipe + similarity report. Run this first: it's fast, and it tells you whether your two VAEs are even compatible before you commit.reference_image- connect one and the node encodes/decodes it through A, B, and the merged VAE, reporting MSE/PSNR per VAE inprobe_report. That's an actual number telling you which merge settings are hurting reconstruction, instead of guessing by eye.recipe_json/recipe_in- a merge's full settings serialize to a recipe JSON that you can feed back in to reproduce the exact merge. Screenshot-free reproducibility.
Inputs and outputs that matter
vae_a/vae_b(+ optionalvae_c) - the inputs.merge_mode,alpha,beta- the blend.alphais the primary weight (0 = all A, 1 = all B in weighted_sum).use_blocks,auto_alpha, and theblock_*sliders - per-block control.dry_run,reference_image,recipe_in- the QA loop.
Outputs: vae (the merged result), info, recipe_json, and probe_report.
Installing it
Standard pack install:
cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git
restart ComfyUI or use Manager → "CustomNodePacks". No extra dependencies - pure weight math on already-loaded VAEs.
The trap
A "merge" that preserves the good parts is not automatic - weighted_sum with a naive alpha is the fastest way to average two things into mediocrity. Do the dry run, look at the similarity report, and let auto_alpha pick where B actually contributes. And keep expectations calibrated: this node gives you tools and measurement, not magic. If the base VAE was already bad, merging doesn't fix that.
Inputs (22)
| Name | Type | Default | Description |
|---|---|---|---|
| vae_a | VAE | Primary VAE (acts as base; deep-copied clone is returned). | |
| vae_b | VAE | Secondary VAE blended into vae_a. | |
| merge_mode | COMBO | weighted_sum | Blend strategy. add_difference / triple_sum / smooth_add_diff need vae_c. sigmoid + geometric mimic TechnoByte/meh behaviour. distribution_xover keeps A unless B has higher detail energy. dare_ties = sparse delta + sign election. |
| alpha | FLOAT | 0.300–1 | Primary blend weight. weighted_sum: 0=A, 1=B. |
| beta | FLOAT | 0.700–1 | Secondary blend weight (used by add_difference / 3-VAE modes). |
| brightness | FLOAT | 0.00-1–1 | Post-merge brightness shift on decoder.conv_out. |
| contrast | FLOAT | 0.00-1–1 | Post-merge contrast gain on decoder.conv_out. |
| use_blocks | BOOLEAN | false | Enable per-block sliders. When False all keys use 'alpha'. |
| auto_alpha | BOOLEAN | false | Data-driven block weights. When True, computes per-block cosine similarity between A and B; dissimilar blocks bias toward A. Overrides the manual block sliders. |
| block_conv_in | FLOAT | 0.500–1 | Weight for encoder/decoder conv_in. |
| block_conv_out | FLOAT | 0.500–1 | Weight for encoder/decoder conv_out. |
| block_norm_out | FLOAT | 0.500–1 | Weight for encoder/decoder norm_out. |
| block_0 | FLOAT | 0.500–1 | First down/up block pair. |
| block_1 | FLOAT | 0.500–1 | Second down/up block pair. |
| block_2 | FLOAT | 0.500–1 | Third down/up block pair. |
| block_3 | FLOAT | 0.500–1 | Fourth down/up block pair (SDXL). |
| block_mid | FLOAT | 0.500–1 | Mid block. |
| device | COMBO | cpu | Compute device. CPU is safe (default); CUDA is faster but uses VRAM. |
| dry_run | BOOLEAN | false | If True, skip the merge and return only the recipe + similarity report. Use this for fast block-similarity inspection without waiting for the merge. |
| vae_copt | VAE | Optional third VAE for add_difference / triple_sum / smooth_add_diff. | |
| reference_imageopt | IMAGE | Optional reference image. If connected, encodes/decodes it through A, B, and the merged VAE; reports MSE/PSNR per VAE in probe_report. | |
| recipe_inopt | STRING | Optional recipe JSON from a previous run. When provided, overrides every widget value above so the exact merge is reproduced. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| vae | VAE | Merged VAE (or vae_a clone when dry_run=True). |
| info | STRING | Human-readable info string summarising mode, alpha, blocks, and timing. |
| recipe_json | STRING | Reproducible recipe JSON; feed back into recipe_in to repeat the exact merge. |
| probe_report | STRING | Probe report with MSE/PSNR per VAE when reference_image is connected. |