Flux Klein Identity Feature Transfer ⚡
The node that actually keeps a face across Klein edits
- model
- sigmas
- subject_mask_1
- subject_mask_2
- subject_mask_3
- subject_mask_4
- subject_mask_5
- subject_mask_6
- subject_mask_7
- subject_mask_8
- MODEL
Klein edits are great at following structure and content, but "same face, every time" is a separate problem - reference conditioning gets the identity close, and close is where weird likeness drift lives. Flux Klein Identity Feature Transfer is the serious answer: a multi-reference, identity-preserving feature transfer that rides inside the model's attention blocks and pulls generated features toward the reference images block by block. It's the flagship node of the source pack this was ported from, and it's the one you reach for when a character has to survive an edit sequence.
MODEL in, MODEL out. It slots onto the model alongside Flux Klein img2img, before the sampler.
How it works
During each forward pass, comfy's Flux/Kontext/Klein attention blocks expose their internal features. This node registers hooks (set_model_attn1_output_patch, always; set_model_attn1_patch when you pick mask_behavior="zero_unmasked_tokens" and wire a mask) and does a feature-transfer dance at the scheduled blocks: per-image centering of generated vs reference features, normalized similarity matching with a configurable floor, temperature-controlled pooling across references, and a confidence-gated pull whose strength is scheduled per double/single block. It's not a LoRA and not a sampler - it's a model patch, so it composes with everything else that patches the model.
The inputs you'll actually touch:
preset-HARD_LOCK/MID_LOCK/SOFT_LOCK/custom. How hard identity locks on. Start withMID_LOCK; hard lock trades likeness for prompt fidelity.reference_indices- which references the transfer uses:all, comma-separated0,2,3, or ranges0-3. Zero-based.similarity_floorandsoftmax_temperature- the gate and the sharpness of reference pooling. Leave them alone until you've seen a result.double_blocks/single_blocks- schedule strings like0-7:mid_img=0.55controlling where in the network the pull applies and how strong. The defaults are the source pack's tuned values.sigmas(optional) - connect the sampler's sigma schedule and block strengths decay per step, so identity locks early and lets detail breathe later.subject_mask_1..8- up to eight masks scoping each reference, plusmask_behavior:focus_onlylimits this node's reference bank while Klein still sees the full reference;zero_unmasked_tokensadditionally blocks a wired reference's unmasked tokens as attention sources everywhere.
The caveat you must read before using it
The default schedules and presets hardcode 8 double / 24 single blocks as magic numbers tuned for the Klein 9B layout. They're never read from the live model. On a different-sized checkpoint - the 4B klein-base, say - out-of-range indices clamp harmlessly, but a preset can end up applying strength to the wrong semantic blocks. If you're not on the 9B, use preset="custom" and write your own double_blocks/single_blocks strings. This is a carried-over quirk of the source, documented rather than "fixed" speculatively - worth knowing before a 4B user spends an afternoon wondering why the transfer feels misaimed.
Installing it
Part of the CCTech pack:
cd ComfyUI/custom_nodes
git clone https://github.com/ChrisColeTech/ComfyUI-GGUF-Loader
cd ComfyUI-GGUF-Loader
pip install --upgrade gguf
Restart; it's under 🤖 CCTech/Flux Klein. No model downloads - the transfer operates on whatever references and Klein checkpoint you already loaded.
The workflow shape
Flux Klein Model Loader → Flux Klein img2img (prompt + references) → this node on model → stock KSampler → VAE Decode. The pack's other Klein model-hook nodes (Ref Latent Controller, Text/Ref Balance, Identity Guidance) can stack on model alongside it - they patch different mechanisms, so they coexist. Start with one reference and MID_LOCK, look at the eyes, then dial the schedule.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| preset | COMBO | HARD_LOCK | 4 options: HARD_LOCK, MID_LOCK, SOFT_LOCK, custom |
| enabled | BOOLEAN | true | — |
| reference_index | INT | 00–15 | — |
| reference_indices | STRING | all | Zero-based references used by the transfer. 'all', comma-separated indices like '0,2,3', or ranges like '0-3'. |
| similarity_floor | FLOAT | 0.0400–0.95 | — |
| softmax_temperature | FLOAT | 0.02500.0001–0.25 | — |
| mask_threshold | FLOAT | 1.000–1 | — |
| double_blocks | STRING | 0-7:mid_img=0.55 | — |
| single_blocks | STRING | 0:mid_img=0.22; 1:mid_img=0.24; 3:mid_img=0.28; 4:mid_img=0.22; 6:mid_img=0.26; 7:mid_img=0.27; 8:mid_img=0.25; 10:mid_img=0.27; 13:mid_img=0.27 | — |
| debug | BOOLEAN | false | — |
| mask_behavior | COMBO | focus_only | focus_only: the mask limits this node's reference bank while Klein still sees the complete reference. zero_unmasked_tokens: also blocks each wired reference's unmasked tokens as attention sources in every block. References without a wired mask remain complete either way. |
| sigmasopt | SIGMAS | Optional sampler sigma schedule. When connected, block strengths decay per sampling step by delta_sigma_0 / delta_sigma_step. | |
| subject_mask_1opt | MASK | — | |
| subject_mask_2opt | MASK | — | |
| subject_mask_3opt | MASK | — | |
| subject_mask_4opt | MASK | — | |
| subject_mask_5opt | MASK | — | |
| subject_mask_6opt | MASK | — | |
| subject_mask_7opt | MASK | — | |
| subject_mask_8opt | MASK | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |