Nodes/ComfyUI-Diff2Flow/Diff2Flow ODE KSampler
ComfyUI Node

Diff2Flow ODE KSampler

Your SDXL Isn't Flow-Matching. This Node Pretends It Is.

By Koratahiu·Created 10 months ago·Updated 9 months ago· 2
Diff2Flow ODE KSampler
  • model
  • positive
  • negative
  • latent_image
  • LATENT
solvereuler
steps20
cfg5.0
denoise1.00
seed0
schedulersimple
log_relative_tolerance-2.5
log_absolute_tolerance-3.5
max_steps100

Every modern model - Flux, SD3, Z-Image - is trained with flow matching: instead of predicting the noise added at each step, the model learns a velocity along a nearly straight path from noise to image. Straight paths are why those models nail 4–8 steps while your SD1.5 or SDXL checkpoint still wants 20–30 with a curved noise schedule. Diff2Flow is a 2025 paper that bridges the two paradigms by converting a pretrained diffusion model into a flow-matching one. This node applies that math at inference time, so your existing SD checkpoint gets sampled as if it were a flow model - through a real ODE solver, no retraining required.

It comes from Koratahiu, who has more skin in this game than most custom-node authors: he's a OneTrainer contributor and the person behind the SDXL-as-flow-matching training branch (BigASP 2.5). This is the inference half of that project. The pack is explicitly experimental, so treat it as a toy worth playing with, not a replacement for your daily KSampler.

What it actually does

Diff2Flow ODE KSampler lives under sampling/custom_sampling and looks like a drop-in KSampler: MODEL, positive, negative, latent_image in, LATENT out, wire it to a VAE Decode. The trick is that when you hit Queue, it patches your loaded model in-place (enable_diff2flow), building the schedule constants that let a diffusion model speak flow-matching. It works with epsilon-prediction checkpoints (SD1.5, SDXL) and v-prediction ones (SD2.1). Other prediction types raise a hard error.

Mechanically, each step converts the flow-matching timestep back to the diffusion timestep, realigns the latent, runs your UNet, then turns its output into a velocity field (z_pred − eps_pred). That velocity gets integrated by a genuine ODE solver from torchdiffeq - not the usual discretized sampler loop.

The inputs that matter

  • solver - the whole point. euler is the fast, predictable default (basically standard Euler). The adaptive solvers (dopri5, bosh3, fehlberg2, adaptive_heun, dopri8) pick their own step sizes on the fly; rk4, midpoint, and heun3 are fixed-step alternatives. If you want to see what the fuss is about, dopri5 is the fun one.
  • steps - how many fixed steps for non-adaptive solvers. Adaptive solvers largely ignore it; that's what max_steps (default 100) caps instead.
  • cfg - standard classifier-free guidance, applied between the positive and negative velocity fields. Default 5; same ballpark as your SDXL KSampler.
  • scheduler - defaults to simple, and here's a KB-backed warning: on a straight flow path, Karras-style schedules that concentrate denoising in the middle tend to distort rather than help. Start with simple or sgm_uniform and don't reach for Karras out of habit.
  • log_relative_tolerance / log_absolute_tolerance (optional) - only meaningful for adaptive solvers; the tolerances that tell torchdiffeq how hard to chase accuracy. Defaults of −2.5 / −3.5 are a sane start.

Install

ComfyUI Manager: search "ComfyUI-Diff2Flow". Or the manual way:

cd ComfyUI/custom_nodes
git clone https://github.com/Koratahiu/ComfyUI-Diff2Flow
pip install torchdiffeq   # the one real dependency; pins to 0.2.5

Restart ComfyUI. No model downloads - it patches whatever checkpoint you already have.

Gotchas (and when to skip it)

The source code is more honest than the README in one important spot: denoise below 1.0 raises NotImplementedError. The field exists in the node, but img2img and refining through the denoise slider just don't work yet - keep it at 1.0.

The other traps: if torchdiffeq isn't installed, the solver dropdown shows a single "torchdiffeq not installed" entry and the node fails with an ImportError - the pip install above is mandatory. ODE samplers don't support masks well, so don't feed it inpainting. And remember this is inference-only: the paper's headline 2-step results come from finetuning with the Diff2Flow objective (official CompVis code, or OneTrainer PR #1052). At plain inference you'll get a different - sometimes better, sometimes just different - rendering, not magic.

Expect it to be slower than a KSampler (adaptive solvers especially), and keep expectations measured for a pack this new with zero community chatter behind it. But if you've ever wondered what your SDXL would look like with a straight path to noise, this is the cheapest way to find out.

Categorysampling/custom_sampling

Inputs (13)

NameTypeDefaultDescription
modelMODEL
solverCOMBOeuler11 options: adaptive_heun, bosh3, dopri5, dopri8, euler, explicit_adams, +5
stepsINT201–10000
cfgFLOAT5.00–100
denoiseFLOAT1.000–1
seedINT00–18446744073709550000
positiveCONDITIONING
negativeCONDITIONING
latent_imageLATENT
schedulerCOMBOsimple9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
log_relative_toleranceoptFLOAT-2.5-7–0
log_absolute_toleranceoptFLOAT-3.5-7–0
max_stepsoptINT1001–1000

Outputs (1)

NameTypeDescription
LATENTLATENT