LC Anima Block Merge Advanced
Two checkpoints, one fader per block
- model1
- model2
- model
What this is for
Anima is a 2B anime base built on NVIDIA's Cosmos-Predict2, and like most diffusion transformers it is organised as a stack of numbered blocks - 28 of them. That structure is the reason merging works at all here. Instead of picking a checkpoint wholesale, you can take composition from one and finish from the other, block by block. Merging is the cheap way checkpoints get made: minutes of arithmetic, no dataset, no GPU-days.
ComfyUI core can already do this with ModelMergeBlocks, but you have to type blocks.0.: 0.3, blocks.1.: 0.35, … by hand and picture the curve in your head. This node draws the curve instead.
How it actually works
The author is refreshingly upfront here: there is no custom tensor math. The node builds the same prefix-to-ratio mapping core's own Cosmos merge node builds, then hands it to ModelMergeBlocks.merge() - longest-prefix-match against the model's key names, plus get_key_patches / add_patches. It is a UI on a mechanism ComfyUI already ships and tests, which is exactly what you want from a merge node.
One convention to internalise: 0 = all model1, 1 = all model2, per block and per slider. Half of all confused merge posts are someone who had the direction backwards.
The inputs that matter
Wire both checkpoints into model1 and model2. They need to be Anima, or Anima finetunes of each other - the ratio mapping assumes the same key layout.
preset is where you start. 50_50 is the flat neutral default; model2_early takes blocks 0-6 from model2, model2_look takes 7-20 (where an Anima finetune's look tends to sit), model2_late takes 21-27. Pick one, then drag from there.
blocks_curve is the real data: 28 comma-separated ratios, blocks.0 through blocks.27. Drag it on the graph rather than typing. edit_mode decides whether dragging one bar blends its neighbours (smooth, window size from smooth_radius, 0-8) or moves that single block (spike).
The five named sliders cover everything outside the blocks: x_embedder (latent to tokens), t_embedder and t_embedding_norm (the timestep side), llm_adapter (how the Qwen text encoder's output is read into the model - prompt comprehension lives here), and final_layer. Core's Cosmos merge node has no LLM adapter slider; this one does, and that's the single most useful addition. Want model2's prompt reading without its look? Push llm_adapter toward 1 and keep the blocks low.
save_name plus save_curve write your curve and all five sliders to web/anima_block_presets/<name>.json on the next queue, and it appears in the preset list after that. Touch anything by hand and preset snaps back to Custom immediately - the node refusing to lie about what you're running.
One output: model, straight into your sampler.
Install
Search the pack title (ComfyUI_LC_ModelBuilder_nodes) in ComfyUI Manager, or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/lonecatone23/ComfyUI_LC_ModelBuilder_nodes
Restart after. There's no requirements.txt for this node - the merge and save tools run on ComfyUI core alone, and the pack's install.py only chases onnxruntime for the face-scoring nodes. Hard-refresh the browser (Ctrl+Shift+R) after any update, because the draggable curve is a JS extension and a stale one gives you a node that loads but won't drag.
Where people get burned
Flat 0.5 across all 28 blocks is the preset everybody leaves alone, and it's the one that hands you a slightly softer version of neither parent. The curve is the point: ramp low-to-high, or anchor the early blocks and the embedders near 0 and let the late blocks come over. And judge every attempt on a fixed seed batch - merge differences are subtle by nature, which is precisely what you cannot see across two different seeds. Park LC Scoreboard 🏆 from the same pack next to it and stop arguing with yourself.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| model1 | MODEL | Ratio 0 side. Blocks/regions at 0.0 come entirely from this checkpoint. | |
| model2 | MODEL | Ratio 1 side. Blocks/regions at 1.0 come entirely from this checkpoint. | |
| preset | COMBO | 50_50 | Bundled: 50_50, model2_early (blocks 0-6 from model2), model2_look (blocks 7-20, where an Anima finetune's look sits), model2_late (21-27), plus anything you save. Loading one sets the curve and the named sliders. Custom keeps what you dragged. |
| edit_mode | COMBO | smooth | smooth = drag one block and blend neighbors. spike = move one block only. |
| smooth_radius | INT | 20–8 | Neighbor window (in blocks) for smooth mode (0 = spike-like). |
| blocks_curve | STRING | 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 | Comma list of 28 ratios (blocks.0. - blocks.27.). 0 = all model1, 1 = all model2. Source of truth when preset is Custom. |
| x_embedder | FLOAT | 0.500–1 | x_embedder. — turns the image latent into tokens, before block 0. |
| t_embedder | FLOAT | 0.500–1 | t_embedder. — timestep embedding. |
| t_embedding_norm | FLOAT | 0.500–1 | t_embedding_norm. — norm on the timestep embedding. |
| llm_adapter | FLOAT | 0.500–1 | llm_adapter. — maps the Qwen text encoder's output into the model (how the prompt is read). |
| final_layer | FLOAT | 0.500–1 | final_layer. — output layer, after block 27. |
| save_name | STRING | Filename under web/anima_block_presets/ (no extension). | |
| save_curve | BOOLEAN | false | On run, write save_name.json into web/anima_block_presets/. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |