LoRA Trigger Analysis π
Forgot the Trigger Word? This Node Tries to Guess It From the Weights
- lora_stack
- clip
- candidate_triggers
"Trigger word missing" is arguably the #1 reason a LoRA "doesn't work." You load it, you prompt around it, nothing happens, and the model page that listed the trigger word is gone or you never saved it. Most people solve this with rgthree's Power Lora Loader, which reads trigger words off the file or fetches them from CivitAI. This node takes a different, weirder route: it tries to derive candidate trigger words by inspecting the LoRA's weights directly.
It won't always beat looking the model up on CivitAI. When it wins is when there's no page to look up - a LoRA you trained yourself, a download that lost its metadata, or something from a dead account. For those cases, having the pack guess a few high-likelihood tokens is a lot better than grepping your prompt history.
How it works
The mechanism is properly nerdy, and it's worth understanding because it explains both what the node can and can't tell you. A LoRA stores low-rank deltas (lora_down, lora_up) for layers it was trained on. Some of those layers live in the text encoder and act on the token embedding table. This node:
- Discovers every text encoder in the CLIP you wired in - CLIP-L/G, T5-XXL, LLaMA/Gemma, or any dual/triple combination. It does this dynamically rather than assuming a known architecture.
- For each LoRA layer whose
in_featuresmatches an encoder's embedding dimension, it projects the entire token embedding table through thelora_downsubspace and accumulates L2 activation norms. - Tokens with the highest scores are the ones most aligned with what the LoRA's text-encoder weights were trained to respond to - which is exactly the signal you want.
Output is a plain STRING (it's an output node, so it also displays in the UI) listing the top top_k tokens. If multiple encoders are present, results come back labelled per-encoder, e.g. [CLIP-L] ....
The inputs and the output
lora_stack(required) - theFE_LORA_STACKfrom LoRA Load. Only LoRAs in the stack get analysed.clip(required) - the CLIP object to analyse against. Wire up the same CLIP your sampler is using, so the discovered encoders match what you'll actually condition with.top_k- how many candidate tokens to return per encoder (1β50, default 10).candidate_triggers(output) - aSTRINGof comma-separated candidate tokens, one line per encoder when there are several.
A natural pattern: wire the same stack and CLIP to both this node and Apply LoRA, run once, and paste the best candidates into your prompt.
Installing it
Same pack, same steps as the rest of FEnodes:
cd ComfyUI/custom_nodes
git clone https://github.com/FugitiveExpert01/ComfyUI-FEnodes.git
Restart ComfyUI and it shows up under the FEnodes category (also installable via ComfyUI Manager by searching "ComfyUI-FEnodes"). No extra dependencies - torch, numpy and Pillow cover it.
Common issues
- Empty output. The node logs two distinct failure modes. "No token embedding tables found" means the CLIP you wired in exposes nothing it can read as embeddings. "No LoRA layers matched any encoder" means the LoRA's text-encoder layers don't line up with the wired CLIP - often because the LoRA targets the diffusion model only, in which case it has no trigger word to find. Both produce an empty string, which is the honest answer.
- It's a heuristic, treat it as one. High L2-norm tokens are candidates, not gospel. Sanity-check the top hits against the model page if one exists; the KB's troubleshooting doc leans on rgthree's Power Lora Loader for authoritative trigger words, and this node is best when that authority doesn't exist.
- Architecture mismatch. Because it analyses against your wired CLIP, analysing a LoRA trained for a different text encoder than the one you've loaded will either return garbage or nothing. Pair it with the same base model the LoRA was trained for.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| lora_stack | FE_LORA_STACK | β | |
| clip | CLIP | β | |
| top_k | INT | 101β50 | β |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| candidate_triggers | STRING | β |