Nodes/ComfyUI Model Bending/Steering Vector (from Activations)
ComfyUI Node

Steering Vector (from Activations)

Winter minus summer, added to any prompt

By abuzreq·Created 2 years ago·Updated 11 days ago· 26
Steering Vector (from Activations)
  • activations_a
  • activations_b
  • steering_vector
  • info
◄sitemiddle_block.1►
◄modechannel►

Here's the pitch, straight from the pack's own example workflow: run the same image twice, changing only one word - winter and summer - and subtract the two runs' activations. What's left is a direction in the model's internal space that means "colder". Now add it to a completely different prompt, a lighthouse, say, and the lighthouse gets colder. No LoRA, no training, no embedding.

This is activation steering, borrowed from the LLM interpretability world, and this node is the bit that does the subtraction. It's marked experimental in the pack and it deserves the label, but the mechanism is refreshingly simple.

How it works

The node takes two ACTIVATIONS snapshots - A (the concept to steer towards) and B (the concept to steer away from) - and computes the difference of their mean activations at one site, per denoising step:

delta[step] = mean_activations_A[site][step] − mean_activations_B[site][step]

That's it. No SVD, no optimisation pass. The classic difference-in-means trick, applied to a diffusion layer instead of a transformer's residual stream. You get one delta tensor per step, so the direction can drift over the trajectory rather than being a single fixed vector.

If the two runs used different step counts, the longer one is resampled down by position to match - so a 20-step A against a 30-step B still works, it's just approximate.

The mode input decides which means get subtracted, and it's the most important choice here:

  • channel - per-channel means. Layout-free, so the direction is about colour, style and concept, and it transfers to other subjects and other compositions. This is what you want 95% of the time.
  • spatial - keeps the layout. You get a direction that also carries where things were. Needs both probes recorded with stats+spatial_means, and it will happily paste the composition of run A onto run B.

Inputs and outputs

  • activations_a - the run with the concept to steer towards. The example workflow feeds this from the "winter" run's Read Activation Probe.
  • activations_b - the concept to steer away from (summer).
  • site - the layer path the vector lives at. Default middle_block.1. The workflow's tip list suggests output_blocks.5.1 for style and colour, and mentions output_blocks.4.1, 8.1 and middle_block.1 as alternatives. Both probes must have recorded that site.
  • mode - channel or spatial, as above.

Outputs are steering_vector (into Apply Steering Vector) and info - a small JSON blob with the site, mode, step count, shape and a relative_norm, which is the honest answer to "how big is this direction compared to the activations it came from". A tiny relative norm means the two prompts barely differed at that layer, and your steer will be mush.

The workflow around it

Two CLIP Text Encode nodes, identical except for the concept word. Each goes to a sampler with its own Activation Probe on the model chain - middle_block.1, output_blocks.*.1 with store: stats+channel_means is what the shipped workflow uses. Each sampler's output feeds a Read Activation Probe, whose activations output goes here. No reference wire on either reader; these are two independent runs, not a bent/unbent pair.

Then Apply Steering Vector hangs this vector on your actual prompt's model chain.

Install

ComfyUI Manager → "ComfyUI Model Bending", or:

cd ComfyUI/custom_nodes
git clone https://github.com/abuzreq/ComfyUI-Model-Bending
pip install -r ComfyUI-Model-Bending/requirements.txt

kornia and scikit-learn, then a restart. Everything the pack logs carries the [model-bending] prefix.

Where people get burned

  • "Site has no channel means in both probes." The node tells you this outright, and the fix is store: stats+channel_means (or stats+spatial_means for mode: spatial) on both probe nodes. Free lesson: the cheap stats store cannot make steering vectors.
  • Changing more than the concept word. Different seed, randomise off - keep A and B identical but for the word, or your direction encodes the seed as much as the concept. A and B also need the same checkpoint and the same resolution, or the activation shapes won't even match.
  • Steering at a layer you didn't probe. The vector only exists for the site you passed. Other sites error out or, worse, get skipped downstream with a warning.
  • Expecting a prompt edit. This doesn't change your text. It changes what a layer carries, which is why the direction survives when you swap the subject - and why it can also break the image in ways a prompt never would.

If you want the friendlier cousin of this idea, that's what the rest of the ecosystem does with IP-Adapter-style conditioning: a reference image injects into cross-attention. Steering is the no-training version that works from a pair of prompts and lives at one layer.

Categorymodel_bending/probe

Inputs (4)

NameTypeDefaultDescription
activations_aACTIVATIONSRun with the concept to steer towards
activations_bACTIVATIONSRun with the concept to steer away from
siteSTRINGmiddle_block.1—
modeCOMBOchannelchannel: per-channel means (style/concept, layout-free); spatial: keeps the layout (needs spatial means)

Outputs (2)

NameTypeDescription
steering_vectorSTEERING_VECTOR—
infoSTRING—