Nodes/ComfyUI-Precision-Model-Save/Precision Model Save V2 (Live Match / FP32 Math)
ComfyUI Node

Precision Model Save V2 (Live Match / FP32 Math)

Your Saved Merge Doesn't Match What You Rendered — This Node Tells You Why

By TiwazM·Created 2 months ago·Updated 10 days ago· 1
Precision Model Save V2 (Live Match / FP32 Math)
  • model
  • saved_path
filename_prefixdiffusion_models/precision_merge_v2
materialise_modematch_live
save_dtypebf16
strip_diffusion_model_prefixtrue

You know the feeling. You merge two checkpoints in ComfyUI, stack a LoRA on top, and the live result is exactly the look you wanted. Then you save the checkpoint, reload it fresh, and the image is subtly off. Same seed, same prompt, same sampler - but the model itself drifted.

That's the "saved model ≠ live model" problem, and Precision Model Save V2 is a diagnostic tool built to settle whether the drift is the save path or something deeper. From TiwazM, it's a one-trick pack with zero external dependencies - no API, no keys, no model downloads. It's just a more honest way to turn a live merged ModelPatcher into a file: it reads MODEL.get_key_patches() - the base weights plus every patch (LoRA, merge, offset) currently applied - materialises each tensor on CPU in fp32, casts once to the file dtype you pick, and writes a standalone .safetensors diffusion model.

How it works

ComfyUI's normal checkpoint saver materialises through its own path, and a live model is not a flat file - it's a base set of weights plus a stack of patches (LoRAs, merges, offsets) that ComfyUI resolves on the fly, often at device-dependent dtypes with stochastic rounding. That's where the drift sneaks in. This node skips the normal path and reads the patch map straight off the live model instead. Two modes control how the materialisation happens:

  • match_live (default) drives ComfyUI's own patch_weight_to_device(..., return_weight=True) - the exact code path live inference uses, LoRA compute dtype and all. This is your control experiment: does the file reproduce what I just rendered?
  • fp32_math rebuilds each patched tensor manually on CPU in float32, then casts once. Higher-precision and V1-compatible, but it can differ slightly from live because live inference doesn't always do LoRA math in fp32.

The inputs that matter

Only five, all required, which is refreshing:

  • model - the live merge you want to capture, straight off the last merge or LoRA node in the graph that produced your image.
  • materialise_mode - match_live or fp32_math, above.
  • save_dtype - fp32 / bf16 / fp16. Trap: the default is bf16, but the README says to run your first test as fp32 - it's roughly twice the size of bf16, and you haven't yet proven the low-precision save is safe.
  • strip_diffusion_model_prefix - keep true. It strips the diffusion_model. prefix so the file loads as a normal checkpoint; flip it and you get keys the loader won't recognise.
  • filename_prefix - defaults to diffusion_models/precision_merge_v2, written under your output folder.

The one output, saved_path, is just a string with the file location. It's an output node - nothing wires out of it; you read the path off the node.

Installing it

ComfyUI Manager, search ComfyUI-Precision-Model-Save, or the manual route:

cd ComfyUI/custom_nodes
git clone https://github.com/TiwazM/ComfyUI-Precision-Model-Save

Restart ComfyUI and it appears under model/merging -> Precision Model Save V2 (Live Match / FP32 Math). No requirements.txt worth mentioning - it leans entirely on ComfyUI's own comfy.lora, comfy.utils and folder_paths, as a diagnostic node should.

The diagnostic recipe

The README's suggested test: save in fp32, keep the prefix-strip on, then fully unload models (or restart), load the file with Load Diffusion Model - note this node saves only the diffusion-model tensors, no text encoder and no VAE, so attach a VAE yourself - and re-render with identical prompt, seed, sampler, scheduler, guidance and steps.

  • FP32 matches the live merge but BF16/FP16 drift → the culprit is output precision. Low-dtype save was the problem all along.
  • FP32 still differs → it's not merely the final save dtype, and the issue lives somewhere else in your pipeline or merge itself.

Where people get burned

  • It's not a universal saver. The README is explicit: it's an experimental diagnostic node for ordinary floating-point models. Quantised formats (GGUF, fp8) may need architecture-specific handling - don't point it at a quantized Flux and expect a magic checkpoint.
  • RAM. Everything materialises on CPU in fp32. An SDXL fp32 file is roughly 13 GB, plus headroom, so this wants real system memory and it will look frozen while saving. It supports interrupt, so you can bail mid-write.
  • match_live needs a modern ComfyUI. If your build doesn't expose patch_weight_to_device(), you get a clear error - use fp32_math or update.
  • Some things can't be baked. Bypass LoRAs, forward hooks and weight-wrapper patches don't survive as ordinary checkpoint tensors; the node logs a warning when it detects them, and the saved file simply won't capture them.

One last take: merging is how half of CivitAI's catalogue is born, and a lot of it drifts into sameness. This node won't rescue an incoherent merge - but it stops the save path from adding its own drift on top.

Categorymodel/merging

Inputs (5)

NameTypeDefaultDescription
modelMODEL
filename_prefixSTRINGdiffusion_models/precision_merge_v2
materialise_modeCOMBOmatch_live2 options: match_live, fp32_math
save_dtypeCOMBObf163 options: fp32, bf16, fp16
strip_diffusion_model_prefixBOOLEANtrue

Outputs (1)

NameTypeDescription
saved_pathSTRING