Nodes/ComfyUI-SMC-CFG/SMC-CFG (Sliding Mode Control)
ComfyUI Node

SMC-CFG (Sliding Mode Control)

CFG keeps burning your image? This node bolts a sliding-mode shock absorber onto it

By belgiangurista-art·Created 6 months ago·Updated 6 months ago· 1
SMC-CFG (Sliding Mode Control)
  • model
  • MODEL
smc_cfg_enabletrue
smc_cfg_lambda5.0
smc_cfg_k0.20
no_cfg_warmup_steps0

Every SD-lineage user knows the exact moment it stops being fun: you crank CFG to make the prompt actually obey, and the render comes back deep-fried - oversaturated, high-contrast, faces caving in. That's CFG's proportional controller overshooting, and it's the problem this node exists to fix. SMC_CFG_Patch wraps SMC-CFG (Sliding Mode Control CFG), the control-theory answer from Tsinghua's CFG-Ctrl paper, and drops it into your ComfyUI graph as a model patch.

What it actually is

A patch node. You feed it a MODEL, it hands back a patched MODEL, and you wire that into the KSampler. Under the hood it calls ComfyUI's set_model_sampler_cfg_function, the same hook a bunch of CFG-tweaking nodes use, so it slots into any workflow that runs real two-pass CFG - SD1.5, SDXL, Pony/Illustrious, and Wan video. If you're on Flux, this isn't the node: Flux has no native unconditioned pass in ComfyUI to patch, so there's nothing to correct.

How it works

Vanilla CFG is a proportional controller: guided = uncond + scale × (cond − uncond). Fine at the model's sweet spot, but the proportional term keeps growing with the scale and eventually overshoots - that's your overbake. SMC-CFG keeps that same P-control output and layers a switching term on top: u_sw = −K·sign(e_t). Because of the sign(), the correction is a constant-magnitude nudge toward the conditional side rather than a second proportional term, which is exactly why it can stabilize high CFG instead of amplifying it.

Now the honest part. The paper's full version is stateful: it builds a sliding surface s_t = (e_t − e_{t−1}) + λ·e_{t−1} from the previous step's guidance error, then applies u_sw = −K·sign(s_t). The ComfyUI patch - which its own code comments admit is a quick bridge, in Flemish, because this is a genuinely Belgian project - approximates with the current error only: compute standard CFG, then add −k·sign(cond − uncond). It captures the stabilizing idea. It is not a bit-exact port, so don't expect identical numbers to the reference implementation.

The inputs that matter

Four knobs in the UI, but only two actually do anything in the version I'm looking at:

  • smc_cfg_enable (default on) - the master switch. Off, and the node returns your model untouched, which makes A/B testing in one graph trivial.
  • smc_cfg_k (default 0.2, range 0–5) - the switching gain, i.e. how strong the correction nudge is. This is the knob you tune.

The other two, smc_cfg_lambda (the paper's exponential decay coefficient) and no_cfg_warmup_steps (initial steps without CFG), are declared in the input schema but never referenced inside the patch function as shipped - the hook only reads smc_cfg_k. Don't burn an evening dialing λ. Check the repo occasionally in case a later commit wires them up.

The output is a single MODEL - the patched model, straight into your KSampler's model input. That's the whole node.

Installing it

ComfyUI Manager: search "ComfyUI-SMC-CFG", install, restart. Or by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/belgiangurista-art/ComfyUI-SMC-CFG

then restart ComfyUI. The README also tells you to pip install diffsynth - that's only for the pack's standalone DiffSynth research pipelines in pipeline/, not for this node. The patch itself runs on torch and numpy, which ComfyUI already ships, so you can skip the heavy dependency unless you want the custom scripts.

Where people get burned

  • Distilled models: it doesn't help, it hurts. The README's own note says Lightning/Turbo 4-step variants come out overbaked. Makes sense - those have guidance baked in and run at CFG 1, so there's no real two-pass CFG to correct and the switching term just pushes toward an already-hot output.
  • It's niche. "SMC-CFG" barely shows up in community traffic - a handful of 2026 threads, mostly the Wan image-to-video crowd treating it as a "potentially better prompt-following" option. This is a paper bridge from a small project, not a polished ecosystem staple. Reach for it when high CFG is genuinely your problem; don't rebuild your workflow around it.
  • Treat k like a stabilizer, not a new CFG. Keep your normal CFG where it works and nudge k in the 0.1–0.5 range. And apply the standing CFG rule: judge it on a fixed seed across several generations, because one lucky image proves nothing.
Categorymodel_patches/SMC_CFG

Inputs (5)

NameTypeDefaultDescription
modelMODEL
smc_cfg_enableBOOLEANtrue
smc_cfg_lambdaFLOAT5.00–20
smc_cfg_kFLOAT0.200–5
no_cfg_warmup_stepsINT00–50

Outputs (1)

NameTypeDescription
MODELMODEL