🧬 XS · DARE TIES Merge Models
DARE, TIES, and a merge report you can actually read
- reference_model
- reference_clip
- reference_vae
- model_stack
- model
- clip
- vae
- merge_report
Most of the checkpoints on CivitAI aren't trained - they're merged, which is exactly why so many merged models start to look like the same person. DARE TIES Merge Models is the "do it properly" version: it merges an SDXL or Illustrious-family stack against a reference using task arithmetic, with optional DARE dropout and TIES sign-alignment - the two language-model merging techniques that stop N-way blends from fighting each other. If you've ever combined two checkpoints and gotten something weaker than both parents, this node lets you debug why instead of crossing your fingers.
How it works
For each child in the stack, the node computes delta = child − reference - the direction that child pushes. Then, depending on merge_mode:
- weighted_delta - plain task arithmetic. Sum the deltas, done. Stable, but this is exactly the "average everything" approach that muddies both parents.
- dare_delta - DARE: each delta element is randomly dropped with probability
drop_rate, survivors rescaled by1/(1-drop_rate). Sounds destructive; it isn't - most of a fine-tune's delta is redundant noise, and DARE keeps the signal while killing cross-model conflict. - ties_delta - TIES: each child delta is trimmed to its largest-magnitude
ties_densityfraction, then a two-pass sign election resolves conflicts where children push the same weight opposite ways. - dare_ties_delta - both, in that order. The author's recommended starting recipe:
drop_rate=0.10,ties_density=0.50.
The merged delta is scaled by delta_strength, then applied to a clone of the reference as a single diff patch per weight key. Children load one at a time and are discarded - RAM stays flat, but a merge is not instant. Grab a drink.
The inputs that matter
The first three inputs are a complete reference triplet from the checkpoint loader: reference_model, reference_clip, reference_vae. The VAE passes through untouched; the CLIP does too, unless you opt into merge_clip (leave it at off - SDXL text encoders are famously sensitive to merging, and a broken one makes every prompt feel wrong).
- model_stack - the child list, from one or more DARE TIES Model Stack nodes.
- merge_mode - the four-way enum above. The whole personality of the merge.
- drop_rate - DARE drop probability. 0.05–0.25 is the sane band; larger stacks tolerate less.
- ties_density - how much of each child's delta survives trimming. 0.4–0.7 is normal.
- delta_strength - overall influence. 1.0 = full merge, <1.0 stays near reference, >1.0 extrapolates, negative inverts.
- normalize_model_weights - on by default; rescales weights to sum to 1.0 so equal weights mean equal shares.
- seed - seeds DARE's random mask per key and child slot via blake2b; same seed + stack order = identical merge.
- merge_math_gpu - off by default; keep it off unless CPU is painfully slow. Faster on CUDA, but the TIES two-pass holds big fp32 tensors in VRAM and OOMs easily.
Outputs
model and clip feed straight into your KSampler; vae is your reference VAE back. The fourth output is the sleeper feature: merge_report, a plain-text rundown of the stack, weights, drop rate, density, strengths, and merged/skipped/mismatch key counts. If a child's keys don't match the reference (wrong architecture, mismatched text encoder), that's where you'll see it. Wire it to a text node and read it before blaming your prompt.
Install
Through ComfyUI Manager, search "ComfyUI XS DARE TIES". Or the manual way:
cd ComfyUI/custom_nodes
git clone https://github.com/x-stride/ComfyUI_XS_DARE_TIES
Restart ComfyUI. There's no requirements.txt and nothing to download - just ComfyUI's own torch/numpy/Pillow. What you do need is your own SDXL/Illustrious-family checkpoints in models/checkpoints. Nodes live under Advanced → model_merging → dare_ties; a two-child example workflow ships in examples/dare_ties_two_child_merge.json.
Where people get burned
- OOM during the merge, especially with
ties_delta/dare_ties_deltaormerge_math_gpuon. Flip GPU math off; the node warns it's the highest-VRAM path. - Empty stack -
ValueError: model_stack is empty. A disabled, "None", or zero-zero slot gets dropped silently; make sure at least one child survives. - Order sensitivity. Unlike plain weighted averaging, the dare/ties modes are deterministic for a fixed stack order - reorder and the merge changes. By design (masks bind to slot index), but it surprises people.
- Slow. A multi-child TIES merge is minutes, not seconds. Run the Stack Visualizer first, or you'll redo it twice.
Quick recipe
Reference: your base Illustrious or SDXL. Two or three children, equal weights. merge_mode=dare_ties_delta, drop_rate=0.10, ties_density=0.50, delta_strength=1.0. If it feels closer to the base than you'd like, nudge delta_strength to 1.1 before touching anything else - and read the merge report once.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| reference_model | MODEL | Base / origin model. Children are merged in as deltas relative to this. Typically the base Illustrious or SDXL checkpoint. | |
| reference_clip | CLIP | Reference CLIP. Used as origin for CLIP delta computation, or passed straight through if merge_clip='off'. | |
| reference_vae | VAE | Reference VAE. Always passed through unchanged; included so the node can return a complete (MODEL, CLIP, VAE) triplet. | |
| model_stack | DARE_TIES_MODEL_STACK | Stack of child checkpoints from one or more DARE TIES Model Stack nodes. | |
| merge_mode | COMBO | dare_delta | weighted_delta: plain weighted task arithmetic. Stable baseline; ignores drop_rate/ties_density. dare_delta: DARE drop-and-rescale per child delta, then sum. Uses drop_rate. ties_delta: TIES trim per child, then two-pass sign-aligned sum. Uses ties_density. Resolves sign conflicts between checkpoints (style vs anatomy fights, opposing directions). dare_ties_delta: DARE then TIES trim, then two-pass sign-aligned sum. Uses both. Recommended starting recipe: drop_rate=0.10, ties_density=0.50. |
| drop_rate | FLOAT | 0.100–0.95 | DARE drop probability p. Each delta element is dropped with prob p, survivors rescaled by 1/(1-p), preserving expectation. Used when merge_mode or merge_clip is dare_delta or dare_ties_delta. Ignored otherwise. Sane ranges: 0.05-0.10 conservative, 0.10-0.25 normal, 0.25-0.40 aggressive, 0.50+ experimental. Larger stacks tolerate less drop: 9 children -> start at 0.05-0.10. |
| delta_strength | FLOAT | 1.00-2–2 | Scalar multiplier on the summed model delta. Applied after DARE/TIES, before patching. 1.0 = full merge (with normalize_model_weights=True this is a true weighted average), <1.0 stays closer to reference, >1.0 extrapolates beyond children, negative values invert the merge direction. Sane ranges: 0.7-1.0 closer to base, 1.0 normal, 1.0-1.25 stronger child influence. |
| seed | INT | 12340–18446744073709550000 | Seed for the DARE Bernoulli mask. Combined per-key and per-child slot index via blake2b for deterministic, reproducible masks. Same seed + same stack order -> identical merge. Only affects modes that use DARE (dare_delta, dare_ties_delta). |
| normalize_model_weights | BOOLEAN | true | If True, model_weight values across the active stack entries are rescaled to sum to 1.0 (true weighted average; combined with delta_strength=1.0 this is a clean N-way blend). If False, raw weights are used as multipliers (sums can exceed 1.0; effectively boosts child influence). |
| merge_clip | COMBO | off | off: pass reference CLIP through unchanged (recommended default for SDXL; text encoders are sensitive to merging). weighted_delta / dare_delta / ties_delta / dare_ties_delta: same semantics as merge_mode, applied to the text encoder stack. Reuses drop_rate and ties_density from above. Test only when prompts feel too close to base or children clearly altered text behavior. |
| normalize_clip_weights | BOOLEAN | true | Same as normalize_model_weights but applied to clip_weight values across active stack entries. Ignored when merge_clip='off'. |
| clip_delta_strength | FLOAT | 0.50-2–2 | Scalar multiplier on the summed CLIP delta (analogue of delta_strength for the text encoder). Default 0.5 is conservative because text encoders are sensitive to merging. Sane ranges: 0.25-0.50 conservative, 0.50-0.75 normal, 0.75-1.00 aggressive. Ignored when merge_clip='off'. |
| ties_density | FLOAT | 0.500.01–1 | TIES trim density: keep the largest-magnitude ties_density fraction of each child delta (zero the rest), then run sign-aligned merge. 1.0 keeps everything (sign election only); lower values discard more of each child's small noise. Used when merge_mode or merge_clip is ties_delta or dare_ties_delta. Ignored otherwise. Sane ranges: 0.70-1.00 conservative, 0.40-0.70 normal, 0.20-0.40 aggressive. |
| merge_math_gpu | BOOLEAN | false | If True (and CUDA is available), run weighted delta / DARE / TIES math on GPU — often faster than CPU fp32. Uses substantially more VRAM while merging (TIES two-pass keeps large fp32 tensors hot). Disable if you hit OOM; keep False for lowest VRAM. Placed last so saved workflows match earlier widgets by index (don’t reorder above). |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| model | MODEL | Merged MODEL: reference_model with summed child deltas applied as a single 'diff' patch per merged key. |
| clip | CLIP | Merged CLIP (cloned reference if merge_clip='off' or unchanged on the off-path). |
| vae | VAE | Reference VAE, passed through unchanged. |
| merge_report | STRING | Human-readable report: stack contents, profiles, effective weights, drop rate, TIES density, delta strengths, and per-section merged/skipped/mismatch key counts. |