Train SAE
The 15-minute job that unlocks every Feature node in this pack
- sae_path
Everything in the pack's "Feature Surgery" and "Research" sections - Feature Map, Feature Gate, Feature Probe, Feature Dict, Diff Features, Feature Atlas - needs a trained Sparse Autoencoder to work on. This is the node that trains it. You run it once, save a .pt file, and hand that path to every other Feature node. It's the pack's prerequisite disguised as a node.
How it works
A sparse autoencoder learns to decompose the text encoder's residual-stream activations into a set of sparse, roughly monosemantic features - the "interpretable features" that SAE research (Bricken et al. 2023) popularized. With the default 8× expansion on Qwen's 2560d space that's 20,480 features. The node collects text-encoder activations, then trains the autoencoder to reconstruct them while keeping only a few features active per input (L1 sparsity penalty). The decoder columns it learns are feature directions you can later probe, gate, and label.
Where the training text comes from matters:
- fineweb (recommended) - streams real web text from HuggingFace's FineWeb dataset. 500K+ diverse activation vectors, ~15–30 min on GPU. Real data → well-separated, high-quality features.
- synthetic - generates prompts from templates. Fast (~2–5 min) but only ~15K vectors, which the tooltip warns is underdetermined for 20K features. Fine for experiments, not for anything you rely on.
The inputs that matter
- save_path - where the SAE lands; feed this exact path into Feature Map / Feature Gate.
- data_source -
fineweborsynthetic. Choose fineweb for real work. - layer - 22 default, matching the rest of the pack's convention. Must match what you use everywhere else.
- sae_expansion - 8× = 20,480 features. Higher = finer-grained but slower and bigger.
- n_vectors - fineweb mode only; rule of thumb is 25–50× your feature count, so 500K–1M for 20K features.
- l1_coeff - the sparsity penalty, 0.008 default. Too high → dead features; too low → dense mush. The tooltip's 0.005–0.01 range is the safe zone.
- learning_rate - 3e-4 default, warms up then cosine-decays. Usually leave it.
- hf_dataset / hf_subset - defaults to
HuggingFaceFW/fineweb/sample-10BT; any text dataset with atextcolumn works (allenai/c4is the classic alternative). - seed -
-1means random features each run. Set a fixed value (42, whatever) to get reproducible feature indices across retrains, and write it down - feature indices are meaningless without knowing which SAE and seed made them. - cache_activations - on by default; reuses collected activations when you retrain with different hyperparameters. Keep it on.
Output is sae_path, a string you'll paste into every downstream Feature node.
Installing
Same pack install as always - ComfyUI Manager search "Concept Steer", or git clone https://github.com/Nynxz/ComfyUI-ConceptSteer into custom_nodes/ and restart. Beyond transformers and safetensors, the fineweb path needs internet access to stream the dataset, and datasets installed (pip install datasets) so HuggingFace's streaming works. Qwen encoding wants ~10 GB VRAM.
Common gotchas
- "Dead feature" diagnostics. Too-high
l1_coeffkills features. The Feature Atlas node exists partly to tell you this - its health diagnostics report dead/alive counts. - Synthetic mode is a trap for real work. 15K vectors for 20K features is mathematically underdetermined; you'll get a noisy SAE. The tooltip doesn't mince words.
- Feature indices change between runs unless you pin the seed. If you save feature indices for a Gate workflow, note the seed that produced them, or retrain with a fixed seed.
- It's not instant. Fineweb mode is a 15–30 minute GPU job. Cache activations and reuse the file across the pack - you only pay for this once.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| save_path | STRING | /tmp/ComfyUI/custom_nodes/ComfyUI-ConceptSteer/sae/sae_layer22_8x.pt | Where to save the trained SAE weights. Use this path in Feature Map and Feature Gate nodes. |
| data_source | COMBO | fineweb | Where to get training text. • fineweb: Stream from HuggingFace FineWeb (recommended). Real diverse web text → high-quality features. • synthetic: Generate from templates (fast, lower quality). |
| layer | INT | 221–36 | Which transformer layer to decompose. 22 (~60% depth) is the sweet spot for style/aesthetic concepts — earlier layers capture syntax, later ones are too abstract. |
| sae_expansion | INT | 82–16 | Feature multiplier. 8× on 2560d Qwen = 20,480 features. Higher = more fine-grained features but slower training and larger file. |
| n_vectors | INT | 50000010000–5000000 | Target activation vectors for training (fineweb mode). Rule of thumb: 25–50× your SAE feature count. • 8× expansion (20K features): 500K–1M vectors • 16× expansion (40K features): 1M–2M vectors In synthetic mode, this is ignored (uses n_prompts). |
| epochs | INT | 81–100 | Training epochs over the collected data. • fineweb (500K+ vectors): 5–10 epochs recommended. • synthetic (15K vectors): use 100–300 epochs. More data + fewer epochs > less data + many epochs. |
| n_prompts | INT | 500100–2000 | Diverse prompts for activation collection (synthetic mode). 500 gives ~15K activation vectors. Ignored in fineweb mode. |
| l1_coeff | FLOAT | 0.0080.001–0.1 | Sparsity penalty. Higher = fewer active features per input (more selective). 0.005–0.01 recommended. Too high → dead features. Too low → dense, uninterpretable. |
| learning_rate | FLOAT | 0.00030.00001–0.01 | Peak Adam learning rate (after warmup). 3e-4 is safe for fineweb. LR warms up linearly over the first 5% of steps then cosine-decays. |
| cache_activations | BOOLEAN | true | Save collected activations to disk for reuse. Avoids re-collecting when re-training with different hyperparameters. Cache is saved next to the SAE file. |
| hf_dataset | STRING | HuggingFaceFW/fineweb | HuggingFace dataset to stream from (fineweb mode). Default is FineWeb. Any text dataset with a 'text' column works. Other options: 'HuggingFaceFW/fineweb-edu', 'allenai/c4' |
| hf_subset | STRING | sample-10BT | Dataset config/subset. For FineWeb, 'sample-10BT' is a 10B-token sample that's fast to stream. |
| encoder_path | STRING | Path to Qwen 3.4B safetensors. Leave empty to use QWEN_ENCODER_PATH env var. | |
| seed | INT | -1-1–4294967295 | Random seed for reproducible feature dictionaries. -1 = random (different features each run). Set a fixed value (e.g. 42) to get the same feature indices every time you retrain with the same data and hyperparameters. Write the seed down alongside your saved feature indices! |
| protect_existing | BOOLEAN | true | If the save path already exists, auto-rename to _v2, _v3, … instead of overwriting. Disable only when you intentionally want to replace the file. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| sae_path | STRING | — |