Layout
compressed-tensors nvfp4-pack-quantized. Tensor names, dtypes, shapes, file grouping and quantization_config
(including the 1,607-entry ignore list) are identical to
cgg507/GLM-5.3-Flash-GM-E32-NVFP4. All 147,634 tensors
were checked.
Table with columns: Modules, Format| Modules | Format |
|---|
routed experts of layers 3-44, gate_proj / up_proj / down_proj (36,288 matrices) | NVFP4: fp4 e2m1 weights, group 16, fp8-e4m3 group scales + fp32 global scale (gate/up fused); input_global_scale from calibration |
attention (KDA, MLA), DSA indexer, routers, shared experts, dense MLPs, mHC, norms, embeddings, lm_head | BF16 (mHC hc_*_base/scale, A_log, dt_bias, e_score_correction_bias fp32), same dtypes as the E32 repo |
| vision tower | BF16, unchanged |
MTP / NextN layer 45 (model_mtp.safetensors, 889 tensors) | BF16 (dequantised from FP8), not adapted, not quantized |
Total 205 GB (191.0 GiB): 46 layer/non-layer shards + model_mtp.safetensors.
How it was made: nmoe-quant
The quant was produced natively by nmoe-quant (C++/HIP, part of nmoe, branch tools/nmoe-quant) on
2x Radeon AI PRO R9700 (ROCm 7.2). It reuses the nmoe trainer's GLM-5.3-Flash forward code. No Python and no
llm-compressor were used for the heavy work. The run goes layer by layer and never holds a full BF16 model:
- Load + merge. Read the FP8 layer, block-dequantise it to BF16, then merge
W += (alpha/r) B A (fp32, stored
as bf16). The adapters are rank 64 / alpha 32 for attention / shared / dense (496 adapters) and rank 32 /
alpha 16 for routed experts (36,288 adapters). There are 36,784 targets (attention 361, shared expert 126,
dense MLP 9, routed expert 36,288). Each target was merged exactly once with a matching shape (asserted).
Adapter sha256[:16] 8d931db5d5fda2e2.
- Calibration forward of the merged layer with the trainer's layer-major GLM code (KDA, MLA + DSA indexer,
mHC, MoE). The inputs are the hidden states of the already-quantized prefix (GPTQ-sequential). All
512 x 2048 calibration tokens are held in host RAM.
- Hessians (calibrate-all-experts):
- every expert sees every token;
- gate/up of all 288 experts share one
H = X^T X;
- down_proj gets a per-expert
H_e = A_e^T A_e, with A_e = SiLU(gate_e x) * (up_e x) over all tokens;
- the GEMMs are bf16 x bf16 -> fp32 on both GPUs (144 experts each).
- GPTQ-NVFP4 on the GPU with llm-compressor 0.14 / compressed-tensors 0.19 semantics (E32 recipe):
- block 128, dampening 0.01, static activation ordering;
- Cholesky of H^-1 with rocSOLVER, then the blockwise column loop with error propagation;
- memoryless-minmax observer, fused gate/up global scale, e4m3 group scales;
NVFP4PackedCompressor re-quantisation of bf16(Q) and packing (low nibble = even column).
The quantized experts then propagate to the next layer with normal top-8 routing.
- Finalize + verify. Index, config (E32
quantization_config, ignore list regenerated and required to equal
the E32 set), tokenizer/template files. --verify re-reads the output and checks:
- every non-quantized tensor (2,482) is bitwise equal to the dequantised FP8 + LoRA, recomputed from the source;
- all 36,288 expert matrices have the right dtypes and shapes, finite positive scales, and the gate/up global
scale fused.
Calibration: 512 x 2048 tokens with the GLM chat template (ultrachat_200k 267, roleplay training conversations
154, calibration_datav3 31, wikitext-2 60). 2 of the 512 sequences are held out from the Hessians for the metrics
below.
Time: ~97 min of layer compute. A MoE layer took ~136 s: 13 s capture, 61 s Hessians, 38 s GPTQ, 21 s propagation.
The ~68 s NFS read of the next layer runs in parallel. The whole run, including a 5-layer trial that was continued,
checkpoints, finalize and verify, took 2 h 10 min.
Validation
- Held-out layer-local output error of the quantized experts,
tr(D H D^T) / tr(W H W^T) on the 4,096 held-out
tokens, over all 36,288 matrices: median per layer 0.0031-0.0083 (median 0.0062), p99 per layer <= 0.0089.
Relative weight error 0.099. No RTN fallbacks.
- Independent Python checks (
refusal_bench/scripts/glm_nvfp4_local, glmq.py + compressed-tensors):
- layers 0-4, 24 and 44: all non-quantized tensors are bitwise equal to the FP8 dequant + merge;
- on sampled experts, global and group scales are bitwise equal to compressed-tensors' observer;
NVFP4PackedCompressor.decompress equals the expected dequant.
- Tiny-config test against llm-compressor:
- given the same Hessian, the codes are 99.96 % equal to llm-compressor
quantize_weight + NVFP4PackedCompressor;
- scales and global scales are 100 % equal;
- parity of all non-quantized tensors is bitwise.
- nmoe smoke test (
nmoe serve --gpu --tp-size 2, thinking ON, GM system prompt, temperature 0.6):
- the model writes a coherent
<think> plan: set the scene, play the informant, don't act for the player, end
on a decision;
- it then gives an atmospheric second-person reply that ends with "What do you do?";
- see
quantization/nmoe_smoke.json.
- Not run: perplexity / KL evaluation, vLLM.
Usage
nmoe
hf download cgg507/GLM-5.3-Flash-GM-CoT-NVFP4 --local-dir GLM-5.3-Flash-GM-CoT-NVFP4nmoe serve GLM-5.3-Flash-GM-CoT-NVFP4 --gpu --port 1337
The adapter is already merged, so no --lora-path is needed. Requests use chat_template_kwargs.enable_thinking
(default on for GLM); the reasoning is returned in reasoning_content.
This is standard compressed-tensors nvfp4-pack-quantized with per-expert names, the same as the E32 repo. Any
runtime that supports glm5_next and compressed-tensors NVFP4 MoE should load it, but none was tested here.
Files
Table with columns: Path, Content| Path | Content |
|---|
model-000NN-of-00046.safetensors | layers 0-44 (one file per layer) + embeddings / lm_head / vision tower (file 46) |
model_mtp.safetensors | MTP layer 45 (BF16) |
quantization/ | merge plan, run config, per-layer GPTQ reports (layers/NN.json), verify report, check reports, smoke test, run log |