Merge Checkpoints (3 Models)
A third input for when two-way blending isn't enough
- output_filename
- documentation
This is CheckpointTwoMerger with a third source slot bolted on - model_a, model_b, and now model_c, all merged in one pass instead of chaining two separate two-way merges. If you've ever tried to combine three checkpoints by merging A+B first, saving, then merging that result with C, you already know why a proper three-way node is worth having: every intermediate save is disk space and rounding error you didn't need, and you lose the ability to weight all three sources against each other in one calculation.
What it actually does
Same engine as the two-input version, extended. calc_mode picks the merge algorithm from a dropdown (the option list isn't spelled out in the node's metadata - check it in-canvas). Six numeric knobs feed the algorithm: alpha, beta, and gamma all default to 0.5 here - a flat three-way split is the obvious read, one knob per source - while delta, epsilon, and zeta default to 2, 0.01, and 0 respectively, which look like secondary controls for a more specific algorithm rather than anything you'd touch on a basic blend. None of the six carry tooltips, so treat the defaults as your best signal, not documentation.
Everything else matches the checkpoint-merger family exactly: mismatch_mode (default skip) for tensors that don't exist across all three files, alignment_mode (default pad/crop) for tensors that exist everywhere but at different shapes, exclude_patterns/discard_patterns (regex, or glob if you flip glob_patterns) to keep specific layers out of the result, lazy_load to stream tensors instead of holding three checkpoints in memory at once, force_clear_cache to trade speed for VRAM headroom, save_dtype/override_dtype for output precision, and process_device for where the math runs. seed is present too, which is the tell that at least one available calc_mode involves some randomness - pin it if you need a repeatable result. Output is output_filename (defaults to merged_3_checkpoint) and a documentation string.
Installing it
ComfyUI Manager: search Model Utility Toolkit, install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/silveroxides/ComfyUI-ModelUtils
Restart ComfyUI. Nothing else to download - this operates entirely on checkpoints already sitting in your models folder.
The honest take
Three-way merging isn't a bigger version of two-way merging, it's a riskier one. The community's own experience with checkpoint merges - documented at length around the Pony/Illustrious merge explosion on CivitAI - is that averaging models doesn't add their strengths together, it tends to dilute all of them toward a blander middle. Every additional source you throw into the average is another chance to pull the result further from any one model's coherent style. That's not a reason to avoid this node; three-way merges absolutely produce interesting results and it's a real, useful capability to have in one node instead of two chained ones. It's a reason to actually look at what comes out before you build a workflow on top of it, and to lean on exclude_patterns if one of your three sources is contributing a specific block (say, its VAE or a particular attention layer) rather than its whole self.
Where people get burned
Same landmines as the two-model version, just with a third variable. Mixing checkpoints from genuinely different base architectures - not just different fine-tunes of the same base - is the fastest way to a merge that loads fine and generates noise; mismatch_mode and alignment_mode exist to keep the tensor shapes reconcilable, not to make the result make sense. And three full checkpoints in flight is meaningfully heavier on VRAM than two - if you're hitting OOM, lazy_load and force_clear_cache are your first move, process_device: cpu your second (slower, but it'll finish).
Inputs (23)
| Name | Type | Default | Description |
|---|---|---|---|
| execution_mode | COMBO | 2 options: MERGE, DOCUMENTATION ONLY | |
| model_a | COMBO | 1 options: None | |
| model_b | COMBO | 1 options: None | |
| model_c | COMBO | 1 options: None | |
| calc_mode | COMBO | 4 options: Add-Difference, Train-Difference, Extract-Features, Add-Dissimilarities | |
| mismatch_mode | COMBO | skip | 3 options: skip, zeros, error |
| alignment_mode | COMBO | pad/crop | 2 options: pad/crop, interpolate |
| alpha | FLOAT | 0.50-10–10 | — |
| beta | FLOAT | 0.50-10–10 | — |
| gamma | FLOAT | 0.50-10–10 | — |
| delta | FLOAT | 2.00-10–10 | — |
| epsilon | FLOAT | 0.01-10–10 | — |
| zeta | FLOAT | 0.00-10–10 | — |
| seed | INT | 00–18446744073709550000 | — |
| output_filename | STRING | merged_3_checkpoint | — |
| save_dtype | COMBO | 3 options: fp32, fp16, bf16 | |
| process_device | COMBO | 2 options: cuda, cpu | |
| exclude_patterns | STRING | — | |
| discard_patterns | STRING | — | |
| glob_patterns | BOOLEAN | false | When True, exclude/discard patterns use glob syntax (* = any sequence, dots are literal). When False (default), patterns are Python regex matched as substrings. |
| lazy_load | BOOLEAN | true | Low memory mode: load tensors from disk on demand |
| force_clear_cache | BOOLEAN | true | Clear CUDA cache after each layer |
| override_dtype | BOOLEAN | false | Force the entire model to be saved as the selected save_dtype. If False (default), higher precision dtypes are preserved. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| output_filename | STRING | — |
| documentation | STRING | — |