Nodes/Visual Model Merge/Visual Model Merge SDXL
ComfyUI Node

Visual Model Merge SDXL

Merge two SDXL models by dragging a curve, not 21 sliders

By jeremy-strang·Created 7 months ago·Updated 7 months ago· 11
Visual Model Merge SDXL
  • model1
  • model2
  • MODEL
time_embed100
label_emb100
out100
weights_json[100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100]

ComfyUI has always been able to merge two checkpoints, but the built-in path makes you babysit a wall of sliders. Visual Model Merge SDXL swaps that for a curve you drag with your mouse - one smooth line across the 21 blocks of an SDXL UNet instead of 21 numbers you have to hold in your head. The name is a little fancy, but the pitch is simple: you can finally see the merge you're building.

The catch up front: this is SDXL-only. The node maps weights to input_blocks.0 through input_blocks.8, middle_block.0 through 2, and output_blocks.0 through 8 - hardcoded SDXL key names. Drop an SD 1.5 or Flux checkpoint in and nothing lines up. It's a tool for blending two SDXL models you already like, not a universal merge gadget.

How it works

Under the hood it does exactly what ComfyUI's ModelMergeSimple and ModelMergeBlocks do. It clones model1, pulls the diffusion-model key patches off model2, then calls add_patches() with a blend ratio per block: 100 means model1's weights win outright, 0 means model2's do, and anything between is a proportional blend. No training, no extra data - it's linear interpolation over existing weights, which is why a merge can be built in seconds.

What's genuinely different is the frontend. Drag on the curve and a Gaussian smoothing kernel spreads your change across neighboring blocks - grab the "Smoothing Radius" slider (1 = tight, 8 = wide) to control how far it ripples. Shift+drag edits only the single block under the cursor, and "Reset Weights" snaps all 21 back to 100. The canvas is color-coded: blue for input, orange for middle, green for output, so you can see at a glance where the style is coming from.

One behavior worth knowing: the numbers are inverted from what you might guess. 100 = model 1's weights, 0 = model 2's. If you want mostly model 2, drag the curve down.

Inputs and outputs that matter

  • model1 / model2 - the two MODEL checkpoints you're blending (wire them out of two Checkpoint Loaders).
  • time_embed, label_emb, out - the SDXL conditioning embedders most merge nodes ignore. These control the timestep embedding, the pooled-text embedding, and the output projection. If you're blending one model for prompt adherence and one for aesthetics, these are the dials that actually move behavior.
  • weights_json - a 21-element array of ints that's the machine-readable version of your curve. It's hidden in the UI once you start dragging, but it's there if you want to paste in a known-good merge.

Output is a single MODEL - wire it straight into a KSampler. This is a runtime merge: nothing gets saved to disk, so it's perfect for A/B experimenting but not a replacement for merging once and saving a .safetensors with a dedicated tool if you'll reuse the result.

Installation

Via ComfyUI Manager, search "Visual Model Merge", or just clone it:

cd ComfyUI/custom_nodes
git clone https://github.com/jeremy-strang/ComfyUI-VisualModelMerge.git

Then restart ComfyUI. There's no requirements.txt and no model to download - it's one Python file plus a JS extension using only the standard library, so installs don't break your environment. It shows up under advanced/model_merging/visual.

Where people get burned

The silent-fallback trap: weights_json is parsed with a try/except that snaps to all-100s (i.e. plain model 1) if the JSON is malformed - and the JS curve editor won't load the array at all unless it has exactly 21 values, so a 20-number paste just leaves the curve at 100. If a merge "isn't working," count your array: valid JSON with the wrong length won't throw in the editor, it'll quietly hand you model 1.

And the bigger, community-proven one: merging incompatible families dilutes both. Blend a realism model with a Pony/Illustrious anime model and you get a checkpoint weaker at each - smoother curves don't fix incompatible training distributions. Use this to fine-tune a blend of two models that already share a base. For that job, the curve is a genuinely pleasant way to work.

Categoryadvanced/model_merging/visual

Inputs (6)

NameTypeDefaultDescription
model1MODEL
model2MODEL
time_embedINT1000–100
label_embINT1000–100
outINT1000–100
weights_jsonoptSTRING[100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100]

Outputs (1)

NameTypeDescription
MODELMODEL