Train Lens (Few-Shot)
Point it at a folder of images and get a concept vector
- lens_path
Some concepts are easy to describe in words; others are "you know it when you see it." This is the node for the second kind. Instead of writing contrastive text pairs, you point it at a folder of images that embody the concept (a minimum of two, jpg/png/webp) and it builds a concept lens from them. It's the natural way to capture a visual vibe you can find but not describe - a particular Instagram filter look, a texture you can't name, a mood that defies a sentence.
How it works
The core path is: SigLIP embeds your positive images, contrastive paired-margin optimization separates those embeddings from negatives, and a small cross-modal bridge projects the 768d SigLIP direction into the target encoder's space (2560d for Qwen on Z Image, 768d for SD 1.5). That bridge is why the lens files can be ~14 MB rather than ~10 KB - the projection weights ride along with the direction.
Three methods are available:
- contrastive (default) - SigLIP embeddings + paired margin optimization. The reliable, recommended path.
- vl_caption - a vision-language model captions your images, then the captions are trained through the native text encoder. The author calls this the best-quality option because the caption training happens in the encoder's own space. Needs a VL model; it auto-detects if you leave
vl_modelblank (Qwen2.5-VL-7B is the "best, ~8GB VRAM" pick, Florence-2-large the light one). - centroid - plain
mean(pos) - mean(neg). Fast, but the README calls it weak; outliers can skew it. Fine for a first sketch.
If you set transcoder_repo with vl_caption mode (zimage only), captions get decomposed through 163,840 monosemantic transcoder features for much better concept isolation - the research-grade option.
The inputs that matter
- concept_name - output filename base.
- positive_dir - absolute path to the concept images. At least 2.
- negative_dir - optional, but strongly recommended for contrastive mode. A folder of images without the concept. Leave empty and it uses origin as contrast, which is weaker.
- method - contrastive / vl_caption / centroid.
- target -
zimageorsd15, matching your generation model. - vl_model - only used in vl_caption mode.
- encoder_path - Qwen safetensors for zimage target (or
QWEN_ENCODER_PATHenv var).
Output is lens_path (a STRING), the absolute path to the saved lens. It also drops into lenses/ and shows up in the Concept Steer dropdown.
Installing
Pack-wide install, same as the others: ComfyUI Manager search "Concept Steer", or git clone https://github.com/Nynxz/ComfyUI-ConceptSteer into custom_nodes/ and restart. transformers and safetensors are needed for training (pip install transformers safetensors). The vl_caption mode pulls its own VL model weight when you pick one - the 7B option is ~8GB VRAM and downloads on first use, so budget for that.
Common gotchas
- The few-shot direction is only as clean as your image folder. Mixed images in
positive_dirproduce a mushy average. Pick a tight, consistent set; add anegative_dirthat's visually close to the positives minus the concept. - Don't skip
negative_dirfor contrastive mode. "Origin as contrast" works, but the separation is noticeably weaker than with real negatives. - SD 1.5 vs Z Image: a lens trained with
target=sd15has a 768d direction and won't apply to a 2560d Qwen workflow. Match the target to the model you sample with. - The first vl_caption run feels slow because it downloads a VL model and captions every image. That's one-time cost per model; the resulting lens is usually the best of the three methods.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| concept_name | STRING | my_concept | Name for the concept (used in filename) |
| positive_dir | STRING | Absolute path to directory of images embodying the concept. Minimum 2 images required. Supports jpg, png, webp. | |
| negative_dir | STRING | Optional: directory of images WITHOUT the concept. Strongly recommended for contrastive mode. Leave empty to use origin as contrast. | |
| target | COMBO | zimage | Target model. 'zimage' = Qwen 3.4B (2560d), 'sd15' = SigLIP (768d). |
| method | COMBO | contrastive | Training method: • contrastive: SigLIP embeddings + paired margin optimization (recommended) • vl_caption: VL model captions → native text-encoder training (best quality, needs VL model) • centroid: Simple mean difference (fast but weak) |
| contrastive_steps | INT | 500100–5000 | Contrastive optimization steps (more = better but slower) |
| vl_model | STRING | VL model for captioning (only used in vl_caption mode). Leave empty to auto-detect. Examples: • Qwen/Qwen2.5-VL-7B-Instruct (best, ~8GB VRAM) • Qwen/Qwen2.5-VL-3B-Instruct (good, ~4GB VRAM) • microsoft/Florence-2-large (light, ~1.5GB) | |
| encoder_path | STRING | Path to Qwen 3.4B safetensors file (for zimage target). Leave empty to auto-detect from ComfyUI model paths. | |
| transcoder_repo | STRING | HuggingFace repo for pretrained transcoders (e.g. 'mwhanna/qwen3-4b-transcoders'). When set with VL caption mode, captions are decomposed through 163,840 monosemantic transcoder features for much better concept isolation. Only supported for zimage target. | |
| output_dir | STRING | Override output directory for the lens file | |
| protect_existing | BOOLEAN | true | If the output lens file already exists, save as _v2, _v3, … instead of overwriting. Disable only when intentionally replacing. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| lens_path | STRING | — |