Quant Menu II (v0.53.0)

The full advanced-quantization surface. v0.53.0 shipped the closed allowlists and validators; v0.53.1 lit up every writer — 3-stage llama.cpp imatrix pipeline, TorchAO PTQ export, and single-shot BNB-4bit merge. See v0.53.1 live writers for the live-wiring detail.

Unsloth Dynamic 2.0 GGUF ladder

14-entry closed allowlist:

UD-Q8_K_XL · UD-Q6_K_XL · UD-Q5_K_XL · UD-Q4_K_XL · UD-Q3_K_XL · UD-Q2_K_XL · UD-IQ4_XS · UD-IQ3_M · UD-IQ3_XXS · UD-IQ2_M · UD-IQ2_XS · UD-IQ2_XXS · UD-IQ1_M · UD-IQ1_S

validate_ud_gguf_format is case-insensitive with canonical normalisation.

bash
soup export --format gguf-ud --gguf-flavour UD-Q4_K_XL --output ./model.gguf

IQ + Apple/ARM GGUF flavours

  • 12-entry IQ family (IQ1/2/3/4 — including IQ4_NL non-linear)
  • 10-entry Apple/ARM-friendly set (Q4_0_4_4, Q4_NL, Q5_K_M, etc.)

Both wrapped in MappingProxyType metadata.

KV cache types

yaml
training:
  kv_cache_type: fp8   # q8_0 | bf16 | f16 | fp8

FP8 is Hopper-only — cross-validator rejects fp8 on the MLX backend; SM-capability check fires at serve construction.

FP8 attention, NVFP4, native unsloth_bnb_4bit

yaml
training:
  fp8_attention: true       # requires quantization_aware='fp8', non-MLX
  nvfp4: true               # CUDA + text only; Blackwell SM ≥ 12 (runtime check)
  unsloth_bnb_4bit: true    # requires backend='unsloth' + quantization='4bit'

LF / Axolotl parity

yaml
training:
  bnb_4bit_use_double_quant: true   # explicit true requires quantization='4bit'
  llm_int8: true                    # asserts quantization='8bit'
  quantize_ref_model: true          # extends quant to ref model (DPO/IPO/SimPO/ORPO/BCO/KTO/GRPO/PPO/preference)
  quantize_reward_model: true       # PPO + reward_model tasks

bnb_4bit_use_double_quant was read by nothing until v0.73.3. Every place Soup built a 4-bit config hardcoded double-quantization on, so setting the key to false changed your config fingerprint and changed nothing about the run. It is honoured now at the three call sites Soup owns: the resident loader, the layer-streaming path (which reads it once and hands the same value to both the sharder and the meta skeleton, so streamed-versus-resident bit-exactness cannot drift), and the 4-bit save path. Two things travel with that. The field is now tri-state: unset means the shipped default, which is double-quant on, so a config that never set it trains identically; only an explicit true triggers the "requires quantization: 4bit" refusal. And because the resolved config now carries the field, a previously-unset config shows a one-time fingerprint drift in soup ship --evidence provenance and soup lock check with the numerics unchanged. The Unsloth loader cannot honour itFastLanguageModel builds its own quantization config internally with double-quant hardcoded on and exposes no override.

Advanced save formats

bash
soup merge --save-format 4bit          # | 4bit_forced
soup merge --save-format 4bit --no-double-quant   # v0.73.3; ignored for fp16
soup export --format torchao --quant-config quant.yaml

save-format 4bit_forced writes a single BNB-4bit merged checkpoint without a dequant / merge / requant cycle.

--quant-config accepts a closed TorchAO allowlist: Int4WeightOnly / Int8DynActInt4 / Float8DynActFloat8 / NVFP4.

Stats

  • Net +157 tests (7,453 → 7,610 across 179 files)
  • 154 tests in test_v0530.py
  • 5 review agents ran in parallel; every CRITICAL / HIGH / MEDIUM / LOW finding fixed or documented

See also

Soup is free and Apache-2.0. If it saved you a training run, starring the repo costs nothing and helps most. You can also fund the GPU time behind the work a 4 GB laptop cannot reach.