Model Math
A custom merge where every layer gets its own expression
- a
- b
- c
- d
- MODEL
Model Math is the pack's take on model merging: it takes up to four checkpoints and evaluates an expression over their weights, producing a merged model. Where core ComfyUI's ModelMergeSimple gives you one blend weight for the whole model, this node lets the expression change per layer - and per tensor inside a layer. a*(1-w)+b*w merges models a and b by weight w, which is a bog-standard merge; the interesting stuff happens when the expression starts referencing layer indices.
How it works
The node iterates over the union of every weight (state_dict) key across all input models. For each layer it binds the weights to a, b, c, d (models missing that layer get zeros), the floats w, x, y, z, and a few special variables:
L/layer- the layer index (0, 1, 2, ...)LC/layer_count- total layersK/key- the layer's state_dict key string
Your expression is evaluated per layer, the result is compared to the base model's weight, and only the differences become patches applied to a clone of a. That's how merges are supposed to work under the hood - ComfyUI stores model edits as patch diffs, and this node hands you the merge math directly. Want to blend only the attention layers? Filter on key containing "attn". Want a merge weight that ramps with depth? Use L.
The inputs that matter
a- the main model (base), required.b,c,d- optional additional models.Model- the expression applied to weights, defaulta*(1-w)+b*w.length_mismatch-tile/error/pad, defaulterror. (For models, the tooltip notes this usually ends up broadcasting.)w,x,y,z- floats.
Output is a single MODEL.
Installing it
Part of More Math (mcDandy/more_math). ComfyUI Manager - search "More Math" - or:
cd ComfyUI/custom_nodes
git clone https://github.com/mcDandy/more_math
cd more_math
pip install -r requirements.txt
Restart. Dependencies are antlr4-python3-runtime and torch - no downloads. Needs a current ComfyUI.
Where people get burned
This is the slow one. Evaluating an expression against every layer of a multi-gigabyte checkpoint takes real time - this is not a lightweight node, and you'll see the run grind on big models. It's CPU-side tensor work, so RAM and patience matter more than VRAM.
Second, merging across mismatched architectures produces garbage. The zero-filling for missing layers means a 1.5 model merged with an SDXL model will have huge invented zeros in places - technically no crash, practically nonsense. Merge models that share an architecture.
And remember what the KB has to say about merges generally: they're fast and need no training, but they trade away coherence, and over-merged models all start to look alike. a*(1-w)+b*w at sane w values is fine; chasing extreme mixes is how you end up with a model that can't do faces. Also, the classic form is deprecated in favor of an autogrow variant with the same "Model Math" name - both ship, and the classic described here is perfectly usable.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| a | MODEL | Main model (base) | |
| Model | STRING | a*(1-w)+b*w | Expression to apply on weights |
| length_mismatch | COMBO | error | How to handle mismatched layer counts. For models, this usually defaults to broadcast (zero for missing layers). |
| bopt | MODEL | Optional 2nd model | |
| copt | MODEL | Optional 3rd model | |
| dopt | MODEL | Optional 4th model | |
| wopt | FLOAT | 0.00 | — |
| xopt | FLOAT | 0.00 | — |
| yopt | FLOAT | 0.00 | — |
| zopt | FLOAT | 0.00 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |