KV_Edit_Sample (native DiT)
KV-Edit leaves the rest of your image bit-identical, and that's the whole pitch
- model
- source_conditioning
- target_conditioning
- latent_image
- mask
- latent
First, which "KV Edit" did you google?
In 2026, "KV edit" mostly means the FLUX.2 Klein KV Edit template that ships with ComfyUI - reference image in, subject preserved, everyone on r/comfyui calling it "stupid good." This node is not that. KV_Edit_Sample implements the KV-Edit paper (arXiv 2502.17363) - training-free masked editing for FLUX.1 dev - ported onto ComfyUI's own native Flux DiT stack. No Klein, no FLUX.2.
What it buys you is the one thing instruction editors still can't do - the thing people complain about when Kontext or Qwen-Image-Edit quietly reshuffles detail they weren't asked to touch: the unmasked area comes back bit-identical. Not "close." Identical. If that's your problem, this is the tool. If you just want to swap a jacket, go use Klein like everyone else.
How it works, roughly
Inside every Flux block, attention builds keys and values alongside the image tokens. KV-Edit runs the model twice per step. First a source pass over a noisy version of your original - fed the prompt describing what's already there - which caches the K and V of the background for all 57 blocks. Then the target pass with the prompt describing what you want, where each block splices those cached background rows back over the fresh ones. Only the masked tokens carry new information; the applied velocity is the difference between the passes (v_target - v_source on the edited rows), integrated over the schedule.
So the background isn't "preserved by a good model" - it never gets a chance to move. The node composites the result onto your input latent through the pixel mask, so the untouched region is bit-identical rather than a VAE round-trip of itself. Two forwards per step is the bill: 28 steps means 56 model evaluations, roughly double a normal Flux render.
The inputs that matter
Wire VAEEncode of your source image into latent_image and a mask into mask, where white is the region to edit - the complement is what survives. model wants a native Flux MODEL (Load Diffusion Model, LoRA optional; flux1-dev-fp8 is fine). Then VAEDecode the single latent output.
Two conditionings, and beginners get this backwards constantly. source_conditioning is a CLIPTextEncode of the image you have - describe it honestly, background included; it's doing real work building that cache. target_conditioning is what you want instead. The rest, in the order you'll actually touch it:
steps/skip_step- 28 by default.skip_step=1drops the noisiest step (upstream's own choice); 0 starts from full noise and wanders more. With an 8-step turbo LoRA, setsteps=8- the node drives its own resolution-dependent sigma shift internally.source_guidance/target_guidance(1.5 / 5.0) - guidance lives here and this node's values win, so an upstream FluxGuidance is pointless. The defaults suit full flux1-dev; on a distilled turbo LoRA, pulltarget_guidancedown.kv_offload(on) - keeps the per-step K/V cache in CPU RAM, ~0.7 GB at 512 and ~2.9 GB at 1024. Leave it on; on a 12 GB card the GPU copy doesn't fit next to the model.attn_scale(1.0) - a bias on background keys during the target pass. Lower it if the edit looks pasted on; 0 disables it entirely.attn_mask- off, and leave it off. It hard-blocks mask↔background attention and forces a slow attention backend.
Ignore seed and re_init unless you switch use_inf off: the inversion-free path fixes the source noise to seed 0 upstream, so the seed field does nothing there, and re_init only applies to the slower real-inversion path.
Install
ComfyUI Manager → Install Custom Nodes → search ComfyUI_KV_Edit, or:
cd ComfyUI/custom_nodes
git clone https://github.com/smthemex/ComfyUI_KV_Edit
Restart ComfyUI. The dependency story is the good news: requirements.txt is literally torch. The older wrapper this pack replaced dragged in diffusers/transformers/accelerate and built a second copy of the Flux weights - that's what ate 12 GB cards. Version 2.0 imports none of it. You still need the models:
# ComfyUI/models/diffusion_models
flux1-dev.safetensors # 23.8 GB full, or flux1-kj-dev-fp8 ~11 GB
# ComfyUI/models/clip
clip_l.safetensors
t5xxl_fp8_e4m3fn.safetensors
# ComfyUI/models/vae
ae.safetensors
An example graph is in example_workflows/example.png.
Where people get burned
Batch size. Anything above one raises KV-Edit works on one image at a time (batch must be 1).
Empty or full masks. A mask selecting no token throws the mask selects no token - nothing to edit; a mask covering the whole frame just warns and gives you a normal generation.
Mask edges are hard by design. The mask is binarized and snapped to a 16-pixel token grid, and the background can't drift to hide a sloppy edge - a badly painted boundary reads as a visible cut. Pad it a few pixels past what you want changed.
The seed is a decoy on the default path. Reseeding won't change your result; change the prompt or attn_scale instead.
VRAM. The node unloads everything else and reserves ≥2 GB before loading the model plus cache. fp8 weights with kv_offload is what fits on 12 GB; the KVEDIT_VRAM_BUDGET env var raises that floor.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | A native flux MODEL (UNETLoader / CheckpointLoaderSimple / + LoraLoader). flux1-dev-fp8 works. | |
| source_conditioning | CONDITIONING | CLIPTextEncode of the prompt that describes the INPUT image. | |
| target_conditioning | CONDITIONING | CLIPTextEncode of the prompt that describes the DESIRED image. | |
| latent_image | LATENT | Raw latent of the source image (VAEEncode). | |
| mask | MASK | Region to EDIT (white = edited). The complement is preserved pixel-exact. | |
| steps | INT | 281–200 | — |
| skip_step | INT | 10–30 | Upstream default 1: drop the noisiest step of the schedule. |
| attn_scale | FLOAT | 1.00–5 | Additive bias on the background keys during the target pass. 0 disables it. 1.0 = upstream default. |
| attn_mask | BOOLEAN | false | Upstream `attn_mask`: hard-block mask<->background attention during the source pass. Off upstream-default; it forces a slow attention backend. |
| use_inf | BOOLEAN | true | Inversion-free path (upstream default). OFF = a real RF inversion pass first. |
| source_guidance | FLOAT | 1.50–30 | — |
| target_guidance | FLOAT | 5.00–30 | — |
| seed | INT | 00–18446744073709550000 | Only used by re_init on the two-pass path; upstream fixes the source-trajectory noise to seed 0 on the inversion-free path. |
| re_initopt | BOOLEAN | false | Two-pass path only: restart the edited region from fresh noise instead of the inverted latent. |
| kv_offloadopt | BOOLEAN | true | Keep the per-step K/V cache on the CPU (~0.7 GB at 512, ~2.9 GB at 1024). On by default: on a 12 GB card the GPU copy does not fit next to the model. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| latent | LATENT | — |