Nodes/ComfyUI-DonutNodes/DonutMultiModelSampler (DEPRECATED)
ComfyUI Node

DonutMultiModelSampler (DEPRECATED)

Sample with three models and a CFG that slides

By DonutsDelivery·Created about a year ago·Updated about 19 hours ago· 25
DonutMultiModelSampler (DEPRECATED)
  • model_1
  • positive
  • negative
  • latent_image
  • model_2
  • model_3
  • nag_negative
  • latent
  • sampling_info
add_noise
steps20
cfg_start8.0
cfg_halfway4.0
cfg_end1.0
halfway_step10
sampler_name
scheduler
noise_seed0
start_at_step0
end_at_step10000
return_with_leftover_noise
randomize_seed_per_modelenable
denoise1.00
cfg_curvelinear
switch_at_step_110
switch_at_step_215
nag_enabledfalse
nag_phi4.0
nag_tau2.50
nag_alpha0.25
nag_sigma_start1000.0
nag_sigma_end0.0

Most workflows use one model for the whole denoising run. DonutMultiModelSampler is the "why not three?" node: you hand it up to three MODEL inputs and two switch_at_step values, and it runs phase one on model_1, hands off to model_2 at step 10, and finishes on model_3 at step 15 - all while its CFG value slides along a configurable curve. It's a sampler, a model blender, and a dynamic-CFG controller in one box.

It's DEPRECATED, with a twist worth knowing: it wasn't removed, it was absorbed. The current DonutSampler node has a mode dropdown with multi_model as one of its three modes, and this standalone node is the pinned-multi-model alias kept so old graphs load. If you're building fresh, DonutSampler → mode multi_model is the same engine with the bonus of the other two modes.

How it works

The engine (_DonutSamplerEngine in the pack's DonutKSamplerCFGLinear.py) is what the whole sampler family shares. For multi-model mode, it plans model phases from your switch_at_step_1 / switch_at_step_2 boundaries, computes a CFG value per step from your three-point curve, and patches a DynamicCFGGuider into the sampling loop so each step runs at its own guidance. randomize_seed_per_model (default enable) gives each phase a fresh seed so you're not sampling the same latent three times in a row.

The CFG controls are the three-point setup: cfg_start (default 8), cfg_halfway (default 4 at halfway_step 10), cfg_end (default 1), plus a cfg_curve (20 easing options, linear default). So a typical run ramps guidance down as detail locks in - the opposite of the old "constant CFG 7 the whole way," and closer to how a lot of people now argue sampling should work.

The inputs that matter

  • model_1 (required), model_2, model_3 (optional) with the two switch points.
  • cfg_start / cfg_halfway / cfg_end / halfway_step / cfg_curve - the dynamic guidance.
  • steps, sampler_name, scheduler, denoise - standard sampling kit.
  • positive / negative / latent_image / noise_seed - the usual plumbing.

Outputs: latent (feed a VAE Decode) and sampling_info - a STRING with a per-step CFG chart the pack formats as ASCII. That chart is genuinely useful for debugging, so route it to a text display.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/DonutsDelivery/ComfyUI-DonutNodes.git donutnodes
cd donutnodes
python -m pip install -r requirements.txt

or ComfyUI Manager → "DonutNodes," restart.

The honest caveat

Three-model switching is a real technique for blending, but it's also the fiddliest thing in the sampler family: the handoff points live in latent-space denoising progress, so a bad switch_at_step mid-detail phase produces an abrupt style jump that reads as "the image broke." Start with one model and just use the CFG curve - that's the part most people actually want - and add the second/third models only when you have a concrete blend in mind. And note the sampler/scheduler advice from the KB: your choices must match your architecture; don't carry SDXL habits onto a flow-matching model.

Categorydonut/sampling

Inputs (30)

NameTypeDefaultDescription
model_1MODEL
add_noiseCOMBO2 options: enable, disable
stepsINT201–10000
cfg_startFLOAT8.00–100
cfg_halfwayFLOAT4.00–100
cfg_endFLOAT1.00–100
halfway_stepINT101–10000
sampler_nameCOMBO44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
schedulerCOMBO9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
positiveCONDITIONING
negativeCONDITIONING
latent_imageLATENT
noise_seedINT00–18446744073709550000
start_at_stepINT00–10000
end_at_stepINT100000–10000
return_with_leftover_noiseCOMBO2 options: disable, enable
randomize_seed_per_modelCOMBOenable2 options: disable, enable
denoiseFLOAT1.000–1
cfg_curveCOMBOlinear20 options: linear, exponential, logarithmic, ease_in, ease_out, ease_in_out, +14
model_2optMODEL
model_3optMODEL
switch_at_step_1optINT101–10000
switch_at_step_2optINT151–10000
nag_enabledoptBOOLEANfalseApply Krea2 NAG inside sampling (requires krea2-nag). Uses CFG 1; Turbo negative conditioning stays zeroed.
nag_negativeoptCONDITIONINGUnzeroed negative prompt for NAG. Defaults to edit_negative_prompt in edit mode, otherwise negative.
nag_phioptFLOAT4.00–20
nag_tauoptFLOAT2.500.01–20
nag_alphaoptFLOAT0.250–1
nag_sigma_startoptFLOAT1000.00–1000
nag_sigma_endoptFLOAT0.00–1000

Outputs (2)

NameTypeDescription
latentLATENT
sampling_infoSTRING