LTX Attn — QKV Transfer
Carry attention from one generation into another
- model
- transfer_model
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_konly - 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: pastecandidates_csvor typeblock:head | block:h1,h2 | block:all; a bareallresolves against whatever heads were actually captured for thatsource_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.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| attn_type | COMBO | sa | 2 options: sa, ca |
| targets | STRING | 24:8,12,16 | Same 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_step | INT | 00–255 | — |
| transfer_from_step | INT | 00–999 | — |
| transfer_to_step | INT | 9990–999 | — |
| blend | FLOAT | 1.000–1 | — |
| use_map | BOOLEAN | false | — |
| use_q | BOOLEAN | false | — |
| use_k | BOOLEAN | true | — |
| use_v | BOOLEAN | true | — |
| sim_filter | BOOLEAN | false | — |
| sim_threshold | FLOAT | 0.30-1–1 | — |
| handle | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| transfer_model | MODEL | — |