DonutWidenMergeCLIP
Merge text encoders the same way you merge the UNet
- clip_base
- clip_other
- lora_stack
- clip_3
- clip_4
- clip_5
- clip_6
- clip_7
- clip_8
- clip_9
- clip_10
- clip_11
- clip_12
- clip
- merge_results
- parameter_info
People merge checkpoints all day and forget half the model: the UNet gets blended, but the text encoder is just… whichever one the loader grabbed. That mismatch is why merged models so often feel like the prompt stopped working - the image side is a blend of two aesthetics, but the text side is still speaking pure model A. DonutWidenMergeCLIP is the missing half. It's the CLIP/text-encoder counterpart to the pack's DonutWidenMergeUNet, applying the same WIDEN importance-weighted logic to the text encoder so the merged CLIP actually matches the merged UNet.
What it does
Same shape as the UNet version, different payload. You give it a base CLIP and another CLIP, it classifies the encoder's parameters by role, computes compatibility scores, and blends each weight by importance instead of blindly averaging. The inputs mirror DonutWidenMergeUNet almost one-to-one:
- clip_base, clip_other - the two encoders (usually loaded from the same checkpoints you're merging on the image side).
- merge_strength (0–5, default 1) - overall intensity.
- min_strength / max_strength - the per-parameter blend range. Default 0–1 is the sane setting.
- normalization_mode -
magnitude(default),calibrate, ornone. - importance_threshold, importance_boost, rank_sensitivity, skip_threshold - the same importance/compatibility machinery as the UNet node.
skip_threshold> 0 starts leaving low-compatibility parameters untouched.
Optional: lora_stack (blend a LoRA into the CLIP during the merge) and up to 10 more CLIPs (clip_3…clip_12) for multi-encoder merges, plus scale_to_min_max and invert_strengths.
Outputs: clip (the merged encoder - wire it into your CLIP Text Encode node) plus merge_results and parameter_info diagnostics strings.
How to actually use it
The recipe for a WIDEN full-checkpoint merge looks like:
Load Checkpoint A ──┬─► UNet ──► DonutWidenMergeUNet ──► model
└─► CLIP ──► DonutWidenMergeCLIP ──► clip
Load both checkpoints with a single loader each (or a dual loader), split their outputs, and merge the two halves with matching merge_strength values. Use merge_results / parameter_info to confirm both sides actually moved - a common failure is realizing the CLIP merge silently did nothing because one side never got wired.
Two practical warnings. First, only merge text encoders of the same architecture - blending an SDXL CLIP with a different encoder family is meaningless. Second, normalization_mode matters more here than on the UNet: text encoders are small and sensitive, and magnitude drift shows up fast as weird prompt behavior. Leave it on magnitude unless you have a specific reason not to.
The honest take
This is a specialist node for checkpoint authors, not a daily-driver. If you never merge models, you'll never touch it. If you do merge, it fixes a real, under-discussed failure - the UNet-CLIP mismatch - and it does it with the same controls you already learned on the UNet side. The DonutModelSave node in the same pack is the natural way to persist the result.
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 are opencv-python-headless, scipy, matplotlib, psutil, tqdm, requests - scipy handles the alignment math. Nothing model-sized to download.
Inputs (23)
| Name | Type | Default | Description |
|---|---|---|---|
| clip_base | CLIP | — | |
| clip_other | CLIP | — | |
| merge_strength | FLOAT | 1.000–5 | — |
| min_strength | FLOAT | 0.00–5 | — |
| max_strength | FLOAT | 1.00.1–5 | — |
| normalization_mode | COMBO | magnitude | 3 options: magnitude, calibrate, none |
| importance_threshold | FLOAT | 1.00–500 | — |
| importance_boost | FLOAT | 1.00–3 | — |
| rank_sensitivity | FLOAT | 2.00–10 | — |
| skip_threshold | FLOAT | 0.00000–1 | — |
| lora_stackopt | LORA_STACK | — | |
| clip_3opt | CLIP | — | |
| clip_4opt | CLIP | — | |
| clip_5opt | CLIP | — | |
| clip_6opt | CLIP | — | |
| clip_7opt | CLIP | — | |
| clip_8opt | CLIP | — | |
| clip_9opt | CLIP | — | |
| clip_10opt | CLIP | — | |
| clip_11opt | CLIP | — | |
| clip_12opt | CLIP | — | |
| scale_to_min_maxopt | BOOLEAN | false | — |
| invert_strengthsopt | BOOLEAN | false | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| clip | CLIP | — |
| merge_results | STRING | — |
| parameter_info | STRING | — |