Nodes/ComfyUI-LTX-Attention-Toolkit/LTX Attn — QKV Transfer
ComfyUI Node

LTX Attn — QKV Transfer

Carry attention from one generation into another

By g-raw·Created 3 months ago·Updated 2 months ago· 2
LTX Attn — QKV Transfer
  • model
  • transfer_model
attn_typesa
targets24:8,12,16
source_step0
transfer_from_step0
transfer_to_step999
blend1.00
use_mapfalse
use_qfalse
use_ktrue
use_vtrue
sim_filterfalse
sim_threshold0.30
handle

Head Freeze replays a stored attention map. QKV Transfer does something more ambitious: it takes the raw Q/K/V - the actual query, key, and value tensors before softmax - from a source generation and injects them into a target generation, head by head. That's the difference between replaying history and recombining it. Capture "chrome robot on rails," then generate "golden robot on rails" while borrowing the source's keys and values, and you get style/attention transfer at the mechanism level instead of by prompting.

For that you need a source capture with capture_qkv=True in Setup Capture - the raw Q/K/V track, which is independent of (and more expensive than) the attention-map capture. This is the only consumer of that QKV store in the pack, so don't turn capture_qkv on unless you're planning a transfer.

How it works

During the target generation, for each targeted (block, head), it substitutes the source run's components into the attention computation. The transfer flags are combinable:

  • use_k + use_v - classic style transfer: keep the target's queries, drive them with the source's keys and values. This is mode D from the attention-transfer literature, and the default combo.
  • use_k only - key-only steering, the lightest touch.
  • use_map - inject the stored raw softmax map directly, bypassing Q/K/V entirely (this one works from a full-map capture instead of raw QKV).
  • use_q + use_k + use_v - full QKV replacement: the target's head is the source's head.

sim_filter gates the transfer with a cosine-similarity threshold on Q_target vs. Q_source, so only tokens where the two generations "agree" get transferred - that's your content-preserving transfer mode. blend (0–1) mixes transferred and native values.

The inputs that matter

  • targets - same format as Head Freeze: paste candidates_csv or type block:head | block:h1,h2 | block:all; a bare all resolves against whatever heads were actually captured for that source_step.
  • source_step - which captured step's Q/K/V to borrow.
  • transfer_from_step / transfer_to_step - the denoising window over which the transfer is active (defaults: full range).
  • blend - transfer strength.
  • handle - optional; blank = current active QKV store.

Output is a single transfer_model MODEL for the KSampler.

Disable by blanking, not bypassing

Same rule as Head Freeze, same reason: this patches the shared diffusion_model, and ComfyUI's bypass/mute skips the cleanup that would unwrap the patch - so a "disabled" node can keep injecting source QKV from an earlier run. To disable, select no use_* flags or blank targets. If you suspect an orphaned layer anyway, LTX Reset Patches clears everything.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/g-raw/ComfyUI-LTX-Attention-Toolkit.git

Restart ComfyUI. No extra dependencies, no model downloads. Work-in-progress pack - QKV store formats and node I/O can change between versions.

Common issues

The transfer source must exist: no QKV store, no transfer - so confirm the source capture had capture_qkv=True and the right qkv_targets. targets="all" only expands to heads actually captured for that block/step, so if the list comes back short, your qkv_targets were too narrow. And because raw Q/K/V is expensive, keeping qkv_targets to the handful of heads you'll actually transfer (from Head Candidates) is both faster and cheaper on RAM than capturing everything.

Categoryg_raw/LTX/Profiler

Inputs (14)

NameTypeDefaultDescription
modelMODEL
attn_typeCOMBOsa2 options: sa, ca
targetsSTRING24:8,12,16Same format as Head Freeze's targets: 'block,head' one per line (paste Head Candidates' candidates_csv directly), or 'block:head1,head2,... | block:all | ...'. 'all' alone (nothing else) means every block/head captured in the QKV store. Blank disables (see below).
source_stepINT00–255
transfer_from_stepINT00–999
transfer_to_stepINT9990–999
blendFLOAT1.000–1
use_mapBOOLEANfalse
use_qBOOLEANfalse
use_kBOOLEANtrue
use_vBOOLEANtrue
sim_filterBOOLEANfalse
sim_thresholdFLOAT0.30-1–1
handleSTRING

Outputs (1)

NameTypeDescription
transfer_modelMODEL