SonarApplyLatentOperationCFG
Run a latent operation mid-sampling by wrapping your model, not your workflow
- model
- operation_1
- operation_2
- operation_3
- operation_4
- operation_5
- MODEL
Normally a latent operation happens before or after sampling - you pass a latent through a filter node, then hand it to the sampler. SonarApplyLatentOperationCFG does the weirder and more interesting thing: it wraps your MODEL so that a LATENT_OPERATION gets applied during the sampling loop, on the model's own predictions. Model in, model out, and everything downstream - KSampler, SamplerCustom, whatever - just works, because the patch rides along inside the model object.
A LATENT_OPERATION is ComfyUI's pluggable "transform this latent" interface. ComfyUI ships a few built-in ones, and this pack adds its own, SonarLatentOperationQuantileFilter, which is presumably what most people wire up here. The point of applying one mid-CFG is to reshape the denoised image at the point where it actually matters - think of it as an in-loop filter that can suppress or sculpt features while the sampler is still working, rather than after the fact.
The mode dropdown is the heart of it. The default cond_sub_uncond is what ComfyUI's own latent operations use - it operates on the classifier-free-guidance result (cond minus uncond), which is the thing CFG is actually steering. The other modes (denoised, cond, uncond, denoised_sub_uncond, etc.) operate on different internal predictions, and the tooltip flags that the non-sub_uncond ones won't work with pred_flip_mode. In short: stay on cond_sub_uncond until you have a reason not to.
The inputs a beginner actually sets:
start_sigma/end_sigma- the sigma range where the effect is active.start_sigmaat -1 means "the model's max sigma" (i.e. from the very beginning);end_sigmaat 0 means "until the end." Narrow this to apply the operation only in the middle of sampling.blend_strength- how hard the operation's output mixes with the original. 1.0 = full replacement, 0.0 = nothing.blend_scale_mode- scales the blend over time. The recommendedreverse_samplingis strong at the start of sampling and fades to 0 at the end - the tooltip's reasoning: these operations usually work better early, when structure is being established.pred_flip_mode- applies the operation to the noise prediction instead of the image prediction. The tooltip is disarmingly honest: no real reason it should be better, just something to try.operation_1throughoperation_5- the actual operations, applied in sequence.immediate_blendforces blending after each one rather than only at the end.
Output is a MODEL, so this slots between your checkpoint loader and your sampler node. The CFG math here is real - this is the same family of model-patching that ComfyUI's own _cfg_pp samplers use, where the sampler steers using the unconditional prediction. That's also why require_uncond exists: at CFG 1.0 ComfyUI skips the uncond pass entirely for speed, and an operation that needs uncond would silently do nothing unless you opt back in.
Install is the pack standard, no model downloads:
cd ComfyUI/custom_nodes
git clone https://github.com/blepping/ComfyUI-sonar
It's a power-user node - if you're not sure what operation you're applying or why mid-sampling beats post-processing, start with SonarLatentOperationQuantileFilter at a modest blend_strength and reverse_sampling and see whether the in-loop version does something you can't get by filtering the latent afterward. Sometimes it does, and that's the whole appeal.
Inputs (18)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| mode | COMBO | cond_sub_uncond | cond_sub_uncond is what ComfyUI's latent operations use. The non-sub_uncond modes likely won't work with pred_flip mode enabled. If you have anything but the denoised options selected, this will use pre-CFG, otherwise it will use post-CFG (unless you are using model_input). |
| pred_flip_mode | BOOLEAN | false | Lets you try to apply the latent operation to the noise prediction rather than the image prediction. Doesn't work properly with the non-sub_uncond modes. No real reason it should be better, just something you can try. Note: The noise prediction gets scaled by the sigma first, in case that's useful information. |
| require_uncond | BOOLEAN | false | When enabled, the operation will be skipped if uncond is unavailable. This will also happen if you choose a mode that requires uncond. |
| start_sigma | FLOAT | -1.000-1–10000 | First sigma the effect becomes active. You can set a negative value here to use whatever the model's maximum sigma is. |
| end_sigma | FLOAT | 0.0000–10000 | Last sigma the effect is active. |
| blend_mode | COMBO | lerp | Controls how the output of the latent operation is blended with the original result. |
| blend_strength | FLOAT | 0.500-10000–10000 | Strength of the blend. For a normal blend mode like LERP, 1.0 means use 100% of the output from the latent operation, 0.0 means use none of it and only the original value. Note: Blending is applied to the final result of the operations unless you enable immediate_blend, in other words operation_2 sees a full unblended result from operation_1. |
| blend_scale_mode | COMBO | reverse_sampling | Can be used to scale the blend strength over time. Basically works like blend_strength * scale_factor (see below) none: Just uses the blend_strength you have set. reverse_sampling: The opposite of the model sampling percent, so if you're making a new generation, the beginning of sampling will be 1.0 and the end will be 0.0. The recommended option as applying these operations usually works better toward the beginning of sampling. sampling: Same as reverse_sampling, except the beginning will be 0.0 and the end will be 1.0. reverse_enabled_range: Flipped percentage of the range between start_sigma and end_sigma. enabled_range: Percentage of the range between start_sigma and end_sigma. sampling_sin: Uses the sampling percentage with the sine function such that blend_strength will hit the peak value in the middle of the range. enabled_range_sin: Similar to sampling_sin except it applies to the percentage of the enabled range. |
| blend_scale_offset | FLOAT | 0.000-1–1 | Only applies when blend_scale_mode is not none. Adds the offset to the calculated percentage and then clamps it to be between blend_scale_min and blend_scale_max. |
| blend_scale_min | FLOAT | 0.000-10000–10000 | Only applies when blend_scale_mode is not none. Minimum value for the blend scale percentage. Many blend modes don't tolerate negative values here. |
| blend_scale_max | FLOAT | 1.000-10000–10000 | Only applies when blend_scale_mode is not none. Maximum value for the blend scale percentage. Many blend modes don't tolerate values over 1.0 here. |
| immediate_blend | BOOLEAN | false | You can enable this to do blending immediately after each latent operation is called. Mainly affects the case where you have multiple latent operations connected. |
| operation_1opt | LATENT_OPERATION | Optional LATENT_OPERATION. The operations will be applied in sequence. | |
| operation_2opt | LATENT_OPERATION | Optional LATENT_OPERATION. The operations will be applied in sequence. | |
| operation_3opt | LATENT_OPERATION | Optional LATENT_OPERATION. The operations will be applied in sequence. | |
| operation_4opt | LATENT_OPERATION | Optional LATENT_OPERATION. The operations will be applied in sequence. | |
| operation_5opt | LATENT_OPERATION | Optional LATENT_OPERATION. The operations will be applied in sequence. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |