Perp-Neg Prediction
The negative prompt fix that stays out of your way
- positive
- negative
- empty
- prediction
Perp-Neg is one of the few SD-community techniques that shipped with a real paper (arXiv 2304.04968, 2023), and this node implements it directly. The problem it solves: when CFG subtracts your negative prompt's influence, the subtraction isn't clean. The negative doesn't just push away from what you named - it pushes sideways, warping composition, tinting colors, quietly wrecking things. Perp-Neg removes only the part of the negative that's perpendicular to the positive, so the negative can steer you away without steering you elsewhere.
The math
With empty as the neutral baseline:
pos_ind = positive - empty
neg_ind = negative - empty
output = empty + (pos_ind - oproj(neg_ind, pos_ind) * neg_scale) * cfg_scale
oproj(neg_ind, pos_ind) is the component of the negative that's perpendicular to the positive - the part that would drag the image in directions your prompt never asked for. Perp-Neg subtracts that, scaled by neg_scale, before applying CFG. At neg_scale 1 you get full Perp-Neg; dial toward 0 and you soften back toward plain CFG-with-a-negative (0 is plain CFG against empty).
Inputs and outputs
- positive (CONDITIONING) - your main prompt.
- negative (CONDITIONING) - the thing you want to avoid.
- empty (CONDITIONING) - an empty-prompt (or neutral) encode that serves as the reference point.
- cfg_scale (FLOAT, default 6) - the familiar CFG dial.
- neg_scale (FLOAT, default 1, range 0–2) - how aggressively to strip the perpendicular component.
Output: one prediction you can feed straight into the sampler chain.
The honest cost
This node needs three model evaluations per step - positive, negative, and empty - versus two for vanilla CFG. That's a 50% render-time premium, and it's the price of the fix. The pack caches per-step, so it won't multiply further if other nodes share the conditionings, but the three runs are unavoidable. Use it where negatives actually matter: strong negative prompts, concept-killer negatives, LoRA-avoidance lists.
A note on era: Perp-Neg peaked in the 2024 SDXL community and has faded since, mostly because the guidance-distilled models that dominate 2026 run CFG 1 by design - and at CFG 1 there's no negative pass at all for Perp-Neg to clean up. If you're on SD 1.5/SDXL or Pony/Illustrious, it still works and still helps. On a distilled checkpoint, don't bother.
Installing it
Ships in the ComfyUI-Prediction pack by @RedHotTensors (Project RedRocket). ComfyUI Manager → search "ComfyUI-Prediction", or:
cd ComfyUI/custom_nodes
git clone https://github.com/redhottensors/ComfyUI-Prediction
Restart ComfyUI. No extra dependencies or model files. It's under Add Node > sampling > prediction.
Common issues
- Slow. Three evals per step is the feature; reduce steps or switch to plain CFG if the cost isn't justified.
- No visible effect. On a CFG-1 distilled model, negatives are inert and so is Perp-Neg. Check what your model actually is.
- ControlNet unsupported in this pack, so you can't combine Perp-Neg with a ControlNet-conditioned graph here.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| positive | CONDITIONING | — | |
| negative | CONDITIONING | — | |
| empty | CONDITIONING | — | |
| cfg_scale | FLOAT | 6.01–100 | — |
| neg_scale | FLOAT | 1.000–2 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| prediction | PREDICTION | — |