PM FLUX.2.Klein Blocks
The double-block / single-block dial
- block_definition
FLUX.2 Klein is the model that actually runs on consumer cards - the distilled 4B/9B line Black Forest Labs shipped in January 2026, and the thing most people now use as their local editor instead of a 32B Dev they can't fit in VRAM. Its LoRAs key off two block streams: double_blocks (the parallel image + text attention blocks) and single_blocks (the unified blocks that handle the late stages). PM FLUX.2.Klein Blocks is the node that turns that structure into per-block weights for the LoRA Power-Merger pack - think of it as a block-weight map with its hands on both streams.
It doesn't do anything by itself. It's a BlockDefinition producer: you configure the weights, it outputs a block_definition, and you feed that into PM Block Selector, which binds it to a specific LoRA in your stack before the merge. Without the selector, this node is just a config sitting on the canvas.
The inputs that matter
double_blocks_weights- comma-separated per-group weights fordouble_blocks, left to right. Missing groups fall back to 1.0.double_blocks_group_size- default 1. How many consecutive double blocks share one weight. At 1 you're addressing every block individually - the fine-grained end.single_blocks_weights- same idea for thesingle_blocksstream.single_blocks_group_size- default 5. Note the asymmetry: the author's defaults give you per-block control over double blocks but group the singles into chunks of five. That's a sensible starting point - the single blocks are where Klein spends most of its parameters, so coarse control there keeps the node fast to reason about.
The single output, block_definition, plugs into PM Block Selector's block_definition input.
How the weights actually apply
The definition matches layer keys against regexes for double_blocks.N and single_blocks.N, buckets each block index into a group (group = N // group_size), and looks up that group's weight. So with single_blocks_group_size = 5 and weights "1, 1, 0.8, 0.5", blocks 10–14 land on 0.8 and blocks 15–19 on 0.5; anything past the last listed group defaults back to 1.0. Only non-1.0 values are stored, and the whole thing scales each LoRA's up factor linearly during decompose - a 0 weight drops that block's contribution to the merge entirely.
That "missing groups default to 1.0" is the one real footgun. A short weight list means later blocks are unchanged, not zeroed. If you're trying to carve a style down to just the early double blocks and the output looks untouched, count your groups.
Installing it
Same as the pack it ships in. In ComfyUI Manager, search "LoRA Power-Merger", or:
cd ComfyUI/custom_nodes
git clone https://github.com/larsupb/LoRA-Merger-ComfyUI
cd LoRA-Merger-ComfyUI
pip install -r requirements.txt
That installs mergekit (from Arcee AI's git repo) and lxml; there are no model downloads. Restart ComfyUI, then build: PM FLUX.2.Klein Blocks → PM Block Selector → PM LoRA Stack Decompose, with your Klein LoRA sitting at the selector's index in the stack.
Worth a quick sanity check on which Klein variant your LoRA targets - base vs distilled are different checkpoints, but both use the same double_blocks/single_blocks key layout, so this definition works on either. If your merge looks unaffected, confirm the stack index and that the node is actually matching a Klein LoRA: an SDXL LoRA run through a Klein definition matches nothing and silently stays at 1.0.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| double_blocks_group_size | INT | 11–128 | — |
| double_blocks_weights | STRING | 1.0 | Comma-separated per-group weights for double_blocks. |
| single_blocks_group_size | INT | 51–128 | — |
| single_blocks_weights | STRING | 1.0 | Comma-separated per-group weights for single_blocks. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| block_definition | BlockDefinition | — |