- clip
- positive
- negative
Here's the problem this node is quietly solving: on Z-Image, Flux 2 Klein, and Qwen-Image, (word:1.3) doesn't boost anything anymore. The old attention-weight syntax gets fed to the new LLM text encoders as literal punctuation, so ((face:1.4)), [body:0.6] makes the model read weird characters instead of a weighted prompt. Unit Prompt Weight is a workaround that puts weighting back - not by teaching the encoder a syntax, but by doing the weighting itself in feature space.
What it actually does
You give it a CLIP model, a positive prompt, and an optional negative. It parses [semantic@weight] markers out of your prompt, encodes each chunk separately, and blends the resulting embeddings together by their weights. The output is a plain positive/negative CONDITIONING pair, so it slots straight into the sampler like any CLIP Text Encode. The mode input picks which model family you're targeting - flux2.klein, z-image, qwen-image, or normal. Be clear-eyed about what normal is: it just calls the stock CLIPTextEncode and ignores your brackets entirely. This node only earns its keep on the three LLM-encoded modes.
The mechanism, from the source, is refreshingly straightforward for all the "Semantic Weight Dynamic Allocation Algorithm" marketing:
- A regex (
\[([^\]]+)@([0-9.]+)\]) splits the prompt into segments.[sunlit [email protected]]becomes a weighted segment; everything unmarked becomes a segment at weight 1.0. - Each segment is tokenized and encoded on its own through your CLIP object, so it goes through whatever text encoder your model actually uses.
- The weights are L1-normalized - meaning they're relative shares, not A1111-style multipliers.
[style@2]just means that segment gets twice the share of a@1neighbor; cranking everything up doesn't overpower the prompt. - The whole prompt is encoded too, then fused:
main_prompt_ratio × whole + (1 − ratio) × individual blend, padding shorter sequences to match. Thatmain_prompt_ratiois the dial between "respect my per-segment weights" (low) and "mostly just encode the whole thing" (high).
The different modes exist because LLM encoders produce variable-length token sequences, and the fusion needs them aligned - the z-image and qwen-image variants carry the alignment logic. The node is also an output node: a small UI widget live-prints the allocation, something like Weight:main_prompt(girl with umbrella, sunlit park)60%|girl with umbrella 24%|sunlit park 16%, which is genuinely handy for seeing what your weights did.
The inputs that matter
- clip - required; your model's CLIP/text-encoder object, same as any encode node.
- pos - the prompt, multiline. This is where your
[semantic@weight]markers go. - mode - pick your model family:
normal,flux2.klein,z-image,qwen-image. - main_prompt_ratio - 0.0–1.0, default 0.5. How much the overall prompt outweighs the individual weighted segments.
- neg - optional; passed through a plain CLIPTextEncode.
Installing it
ComfyUI Manager: search "ComfyUI-Apt_UnitPromptWeight". Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/cardenluo/ComfyUI-Apt_UnitPromptWeight
Restart ComfyUI. That's the whole thing - no requirements to pip install, no model downloads, no extra VRAM beyond your checkpoint's text encoder. A refreshingly dependency-free pack.
Where people get burned
You got a cat you didn't ask for. Empty pos silently becomes "a cat" in the source. Empty neg becomes "bad". Neither is a bug, but both will confuse you the first time.
Your brackets did nothing. Check the mode - in normal they're ignored entirely. Also, if no segment has a weight other than 1.0, the node forces main_prompt_ratio to 1.0, so your per-segment fusion is dropped and only the whole-prompt encoding survives. You need at least one [thing@≠1] for the feature fusion to engage.
Context vanishes between brackets. Each segment is encoded in isolation, so the relationship between "girl" and "walking in rain" dies if you split them into separate brackets. Keep multi-word concepts - [girl with [email protected]] - inside one marker.
Shape errors on modern encoders. If you're on Klein or Qwen-Image and fusion fails, make sure you're not using a mode for the wrong family; the alignment code differs per mode, and the z-image/qwen-image paths handle variable-length encoder output more defensively. If you're on an SDXL-lineage model, honestly just skip this node - (word:1.3) already works natively there, and normal mode adds nothing.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | — | |
| posopt | STRING | — | |
| negopt | STRING | — | |
| modeopt | COMBO | normal | 4 options: normal, flux2.klein, z-image, qwen-image |
| main_prompt_ratioopt | FLOAT | 0.500–1 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| positive | CONDITIONING | — |
| negative | CONDITIONING | — |