Nodes/ComfyUI-GPTQ-Calibration/Dual Model Calibration Data Collector
ComfyUI Node

Dual Model Calibration Data Collector

Two Models, One Workflow, Two Calibration Files

By ThunderFun·Created 3 months ago·Updated 2 months ago· 0
Dual Model Calibration Data Collector
  • model
  • model_negative
  • positive
  • negative
  • calibration_path_positive
  • calibration_path_negative
cfg4.0
num_steps4
num_samples16
seed0
hessian_block_size128
hessian_formatdlr_nystrom
dlr_rank128
collect_amaxtrue
output_path_positive/tmp/ComfyUI/output/calibration_positive.pt
output_path_negative/tmp/ComfyUI/output/calibration_negative.pt
latent_height64
latent_width64
convrotfalse
rot_size256
rpbhfalse
rpbh_seed42
rpbh_block_size256
permuquantfalse
pisofalse
sigma_min0.00
sigma_max1.00
force_cpu_hookfalse
timestep_channel_amaxfalse
timestep_buckets4

Some ComfyUI workflows don't run one model - they run two, with CFG applied between them at every denoising step. That's how Ideogram 4 works in practice: the main model takes your prompt, and a second, image-only expert acts as the "negative" side. If you want to quantize that setup, you can't calibrate the two halves separately and hope the numbers still make sense together. You need both models seeing the same data, in the same dual-model arrangement, at the same time. That's exactly what this node does.

It's the sibling of the Calibration Data Collector in the same pack, and it shares all the machinery: forward hooks accumulate per-layer Hessians (H += xᵀx) and amax over a short sampling pass, nothing about the weights is modified, and it spits out .pt files for an external quantizer - the author's companion tool, int_crush_converter. The only difference is it runs the two models together and writes two calibration files.

How it works

The source is explicit: it mirrors DualModelGuider. Positive conditioning runs through model; the negative side (often image-only conditioning) runs through model_negative; and CFG is applied between them at each step. Same sampler semantics as inference, so the statistics match how the models are actually used. Two .pt files come out, one per model, each in the same schema as the single-model node.

The inputs that matter

  • model - the positive, conditional model.
  • model_negative - the unconditional model. For Ideogram 4, this is the image-only expert.
  • positive - your conditioning, wired like normal.
  • negative - optional. Leave it disconnected and the negative model gets an image-only pass, which is the Ideogram 4 default. This is the input beginners trip on most: it genuinely expects to be empty for that workflow.
  • cfg - the CFG value between the two models. Must be greater than 1.0 (min is 1.01); at 1.0 there's no gradient between the models and the node won't produce meaningful data for both.
  • num_samples / num_steps - same story as the single version: more samples, smoother statistics; 4 steps per sample is plenty.
  • hessian_format - leave it on dlr_nystrom, the recommended default. It's a Diagonal + Low-Rank Hessian built with a randomized Nyström sketch, roughly 100× faster to construct than the plain streaming dlr variant and with the exact diagonal preserved.
  • output_path_positive and output_path_negative - where each model's file lands.

The optional set (convrot, rpbh, permuquant, piso, sigma_min/sigma_max, force_cpu_hook, timestep_channel_amax) is the same advanced rotation and clipping toolkit as the single-model node. One rule carries over: if you enable RPBH, the converter must use the same rpbh_seed (default 42) to regenerate the matching rotation for weight folding.

The outputs

Two strings: calibration_path_positive and calibration_path_negative, pointing at the saved .pt files. Like its sibling it's an output node - you run it, grab the paths, and hand both files to the converter.

Installing it

Same pack as the single-model node, same install. ComfyUI Manager (search "ComfyUI-GPTQ-Calibration"), or:

cd ComfyUI/custom_nodes
git clone https://github.com/ThunderFun/ComfyUI-GPTQ-Calibration.git

Restart, done. Dependencies are torch and numpy (already in ComfyUI). Triton is optional and only accelerates the Hadamard rotation path:

pip install triton

No model files to download - it reads whatever you load in.

Where people get burned

The same caveat that applies pack-wide: the README warns the code is not thoroughly tested - verify outputs before relying on it. It's a young, low-community pack (version 0.3, effectively no discussion out there), so treat your first quant as a beta.

Two failure modes are built into this node by design. First, the two output paths must be different - it raises a ValueError if they resolve to the same file, so don't point both at one path. Second, if cfg isn't above 1.0 you don't actually get dual-model statistics; keep it at the 4.0 default unless you know why you're changing it. And the usual suspects apply: leave negative disconnected for image-only setups, set latent_height/latent_width (128 for 1024px, 64 for 512px) so the statistics match real inference, and flip force_cpu_hook if the dual-model pass OOMs your card.

Categorymodel/quantization

Inputs (28)

NameTypeDefaultDescription
modelMODELPositive (conditional) model.
model_negativeMODELNegative (unconditional) model. For Ideogram 4 this is the image-only expert.
positiveCONDITIONINGPositive conditioning — runs through `model`.
negativeCONDITIONINGNegative conditioning for the uncond model. Leave disconnected for image-only pass (default for Ideogram 4).
cfgFLOAT4.01.01–100CFG value to apply between the two models. Must be > 1.0 to calibrate both models.
num_stepsINT41–50
num_samplesINT161–4096
seedINT00–4294967295
hessian_block_sizeINT1280–10240 = full Hessian, 128 = diagonal blocks. Ignored when hessian_format='dlr'.
hessian_formatCOMBOdlr_nystromHessian storage format. 'dlr_nystrom' = DLR via randomized Nyström (streaming, exact diagonal, ~100× faster — recommended). 'dlr' = DLR via FrequentDirections. 'block' = diagonal blocks. 'full' = full Hessian.
dlr_rankINT1281–4096Rank for DLR Hessian (only used when hessian_format is 'dlr' or 'dlr_nystrom').
collect_amaxBOOLEANtrue
output_path_positiveSTRING/tmp/ComfyUI/output/calibration_positive.ptWhere to save the positive model's calibration .pt file.
output_path_negativeSTRING/tmp/ComfyUI/output/calibration_negative.ptWhere to save the negative model's calibration .pt file.
latent_heightoptINT648–1024
latent_widthoptINT648–1024
convrotoptBOOLEANfalse
rot_sizeoptINT25616–4096
rpbhoptBOOLEANfalseEnable RPBH rotation. Mutually exclusive with ConvRot. Best with DLR Hessian format.
rpbh_seedoptINT420–2147483647Random seed for RPBH. The converter must use the same seed.
rpbh_block_sizeoptINT2560–65536RPBH Hadamard block size. 0 = auto-detect (default). Set to 256 for uniform block size. Must be a power of 2 if non-zero.
permuquantoptBOOLEANfalse
pisooptBOOLEANfalse
sigma_minoptFLOAT0.000–1Lower bound of the sigma range to sample. Set to 0.875 with Wan 2.2 high-noise expert, or 0.0 for full range (default).
sigma_maxoptFLOAT1.000–1Upper bound of the sigma range to sample. Set to 0.875 with Wan 2.2 low-noise expert, or 1.0 for full range (default).
force_cpu_hookoptBOOLEANfalseForce hook-side processing to CPU. Enable if you hit GPU OOM with dual-model calibration.
timestep_channel_amaxoptBOOLEANfalseCollect per-timestep-bucket per-channel amax for both models. Enables time-varying channel imbalance analysis (ViDiT-Q Section 4.2).
timestep_bucketsoptINT41–64Number of timestep buckets for per-timestep channel amax. 4 = paper default.

Outputs (2)

NameTypeDescription
calibration_path_positiveSTRING
calibration_path_negativeSTRING