Precision Model Save V2 (Live Match / FP32 Math)
Your Saved Merge Doesn't Match What You Rendered — This Node Tells You Why
- model
- saved_path
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 ownpatch_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_mathrebuilds 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_liveorfp32_math, above.save_dtype-fp32/bf16/fp16. Trap: the default isbf16, but the README says to run your first test asfp32- it's roughly twice the size of bf16, and you haven't yet proven the low-precision save is safe.strip_diffusion_model_prefix- keeptrue. It strips thediffusion_model.prefix so the file loads as a normal checkpoint; flip it and you get keys the loader won't recognise.filename_prefix- defaults todiffusion_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_liveneeds a modern ComfyUI. If your build doesn't exposepatch_weight_to_device(), you get a clear error - usefp32_mathor 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.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| filename_prefix | STRING | diffusion_models/precision_merge_v2 | — |
| materialise_mode | COMBO | match_live | 2 options: match_live, fp32_math |
| save_dtype | COMBO | bf16 | 3 options: fp32, bf16, fp16 |
| strip_diffusion_model_prefix | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| saved_path | STRING | — |