Files
vllm-omni/.claude/skills/quantization/references/modelopt-fp8.md
T
2026-06-11 06:41:31 +08:00

4.7 KiB

ModelOpt FP8 Conversion and Loading

Use this when exporting or loading ModelOpt FP8 checkpoints for diffusion transformers. This reference captures the practical conversion lessons from the 2026-04-21 ModelOpt FP8 paste and aligns them with the current vllm-omni ModelOpt adapter.

Core Rule

Treat ModelOpt FP8 as selective checkpoint quantization, not one-click whole-model FP8. Quantize the main transformer or DiT backbone, keep sensitive or peripheral modules BF16, serialize a complete ModelOpt checkpoint, and let vLLM-Omni auto-detect it from config.

Do not pass --quantization fp8 to force a ModelOpt checkpoint path. The checkpoint's quantization_config should select modelopt.

Conversion Strategy

Prefer:

  • backbone attention Q/K/V and FFN expansion projections
  • conservative per-model ignore lists
  • MHA quantizers disabled until basic linear quantization is stable
  • full module-name prefixes in ignore/routing logic
  • BF16 fallback for output-side and routing-sensitive layers

Avoid quantizing by default:

  • VAE
  • text, vision, or audio encoders
  • embedders and modulation layers
  • final heads and output projections
  • refiner modules
  • MoE routers and layernorm-sensitive blocks

Model-Specific Starting Points

Model Family Quantize First Keep BF16 First
Z-Image attention q/k/v, FFN w1/w3 to_out, w2, noise_refiner, context_refiner, embedders, modulation, final/output
Qwen-Image transformer backbone linear layers proj_out, img_in, txt_in, norms, modulation, position/time/embed layers
FLUX2-dev / FLUX2-klein backbone linear layers proj_out, context/x embedders, norm_out, stream modulation, time embeddings
HunyuanImage-3.0 model.model backbone VAE, vision tower, token/time/image embedders, final image head, LM head, routers, layernorm-sensitive blocks

These are starting points, not support claims. Validate with BF16 outputs.

Required Checkpoint Metadata

transformer/config.json must include a complete quantization_config. At minimum it should identify ModelOpt and the algorithm:

{
  "quantization_config": {
    "producer": {"name": "modelopt"},
    "quant_method": "modelopt",
    "quant_algo": "FP8"
  }
}

Current vLLM-Omni auto-detects:

  • FP8 and FP8_PER_CHANNEL_PER_TOKEN -> modelopt
  • NVFP4 -> modelopt_fp4
  • MIXED_PRECISION -> modelopt_mixed

Packed modules and scales must map correctly:

  • to_qkv from to_q, to_k, to_v
  • add_kv_proj from add_q_proj, add_k_proj, add_v_proj
  • w13 from w1, w3
  • .input_scale, .weight_scale, .weight_scale_2, .weight_scale_inv

For selective FP8, target layers that remain BF16 must be allowed to dequantize from FP8 weights using the matching weight_scale, or the adapter must skip the quantized scale tensors for that BF16 target.

Runtime Signals

Healthy loading should show ModelOpt auto-detection and a ModelOpt linear kernel path. Useful signals include:

  • auto-detected quantization from config
  • selected ModelOpt FP8 linear method
  • CUTLASS or FlashInfer FP8 scaled-mm backend when enabled and supported
  • non-eager path compiling the transformer when expected

If online serving fails while offline inference works, inspect warmup and serving initialization before changing checkpoint conversion.

Validation Order

  1. Check config completeness.
  2. Run an export checker such as examples/quantization/check_modelopt_fp8_export.py.
  3. Confirm actual FP8 tensors and expected disk-size reduction.
  4. Run one offline generation with fixed prompt, seed, size, and steps.
  5. Run serving with vllm serve --omni and verify /v1/images/generations.
  6. Compare against BF16 using visual review plus metrics such as LPIPS, PSNR, MAE, cosine similarity, and SSIM.
  7. Compare performance only under matched modes:
    • BF16 eager vs FP8 eager
    • BF16 non-eager vs FP8 non-eager

FP8 is not automatically faster. Check whether execution reaches FP8 kernels, whether compile mode is comparable, and whether the workload shape fits the kernel path.

Triage

Symptom First Check
Startup failure config.json, model_index.json, quantization_config, missing scales
Loads but output is corrupted Over-quantized sensitive layers or wrong full-name prefixes
Offline works but online fails Dummy warmup, serving init, compile path
FP8 is not faster Kernel selection, dtype, compile mode, workload shape
BF16 fallback fails Missing weight_scale for dequantization or wrong packed-module mapping

The success criterion is stable, correctly scoped checkpoint loading with quality preserved enough for the target use case, not maximizing the number of FP8 layers.