# ARVQ cold-expert quantization: methodology
How the cold Mixture-of-Experts weights in this repository
(`GLM-5.3-Vision-NVFP4-ARVQ-hybrid`) were quantized and tuned. This document
reconstructs the actual pipeline and tuning decisions from the build transcripts
and the fitting/serving code; numbers are cited from those sources. It is a
methodology record, not a quality claim: full-model task quality and native
SM120 execution were **not** evaluated for this checkpoint.
---
## 1. What this model is (the hybrid)
GLM-5.3 is a large MoE. Each MoE block routes each token to its top-8 of 256
routed experts (plus a shared expert). This checkpoint is a **hybrid** in which
each expert is stored in one of two ways:
- **Hot experts** — kept in the NVFP4 donor format (unchanged).
- **Cold experts** — re-quantized to ~2 bits with **ARVQ** (additive residual
vector quantization), the subject of this document.
The hot/cold split is fixed by a REAP allocation that keeps the **5,750** most
important experts hot; the remaining **13,450** experts across the model are
cold (per the 09-14 build transcript, which verified "13,450 cold-expert source
files"). The allocation is 75% text-REAP / 25% multimodal-salience weighted and
is **not** modified by this campaign.
Only the **75 MoE blocks, layers 3–77**, are touched. Layers 0–2 are dense and
stay frozen. Everything except the cold experts is inherited unchanged:
attention, backbone, shared experts, hot NVFP4 experts, BF16 MTP, and the
vision components.
Cold experts are quantized per (layer, projection). The two projections are the
fused gate/up `w13` (N=4096, K=6144) and the down projection `w2` (N=6144,
K=2048).
---
## 2. ARVQ representation and bit budget
Each cold expert weight group of **8 contiguous columns** is represented as the
sum of two codebook atoms times a scale:
```
w_group = global * block_scale * (c0[a] + c1[b])
```
- **Two codebooks** `c0`, `c1`, each **256 entries × 8 dims** (512 codewords per
pair). This is the "rvq256_256x8" format. Codebooks are **per-expert** in this
v3 checkpoint (`codebook_scope = expert`, packed format
`rvq256_256x8_expert`, version 3).
- **Indices** `a`, `b` are one uint8 each per 8-weight group → **16 index bits
per group = 2.0 bits/weight**.
- **Codebook atoms are constrained to the FP4 grid** `{0, ±0.5, ±1, ±1.5, ±2,
±3, ±4, ±6}` (project-to-FP4 after every update). The FP4 grid on the atoms is
why no incoherence/Hadamard rotation is used: the target space cannot be
rescaled without leaving the grid (see `encoder.py` docstring).
- **Block scales** are stored as **`float8_e4m3fn`**, one scale per **[row,
128-column block]** (48 blocks/row for `w13`, 16 blocks/row for `w2`). At use
time each block scale is `repeat_interleave(16)` to cover the 16 eight-wide
groups in a 128-column block. Adding the FP8 scale (8 bits / 128 weights =
0.0625 bit/weight) gives the reported **2.0625 bits/weight** plus the
amortized per-expert codebooks.
- A single fp32 `global` scalar per (layer, projection) sits above the block
scales so the index/scale layout is unchanged from earlier versions.
Packing (`pack.py`) writes MMA-fragment index tiles (64 uint32 words/tile) and
verifies, per layer, that every expert's indices round-trip exactly and that a
sample of decoded weights matches bit-for-bit before publishing.
---
## 3. Initial fit (Hessian-aware, no PV yet)
Before any gradient tuning, each (layer, projection) gets an
activation-Hessian-tuned initialization (`encoder.py`, `fit.py`):
1. **Per-expert raw-basis Hessian.** `w13` uses `H = E[x xᵀ]` over routed
tokens; `w2` uses `H = E[m mᵀ]` where `m = silu(x·Wgᵀ)·(x·Wuᵀ)` is the BF16
SwiGLU intermediate. Experts with <32 routed tokens fall back to all captured
tokens. Activations are stored/computed in **float32**; Hessians are half.
2. **Escalating-damp Cholesky** of `H⁻¹`: damping starts at `1e-3 · mean(diag H)`
and multiplies by 4× (up to 12 attempts) until the factorization succeeds.
3. **Codebook EM** on a Hessian-importance-weighted subsample (20,000 groups/
expert) of normalized 8-dim groups: k-means warm start → 8 alternating
refine iterations, FP4-projecting the atoms after every M-step.
4. **Per-expert LDLQ/GPTQ error-feedback column sweep** with the fixed
codebooks (col_block=128, 2 sweep passes, 1 inner refine): plain-L2 inner
assignment, off-diagonal Hessian carries cross-group error feedback.
5. **Least-squares refit of the E4M3 block scales** given the chosen codes.
An earlier decision, recorded 09-14: a **tuned Hadamard rotation was tested and
rejected** — a matched 48-expert down-projection refit gave 0.372 (H128 rotated)
versus **0.191 unrotated**, so the unrotated raw-basis fit was adopted.
Nonfinite guards are raised as errors throughout (the fit/tuner refuse to
proceed on NaN/Inf rather than silently scrubbing).
---
## 4. The PV objective: `--target reference`
The cold experts are then output-tuned per layer. The objective for this
checkpoint is **`--target reference`** (`sequential_pv_full_corpus.py`).
For each captured token position the tuner forms:
- `frozen` — the block output from everything that is **not** a cold expert on
the **student** input (retained tuned upstream layers → attention → shared
expert → hot NVFP4 experts). This is fixed.
- `reference` — the **original FP8 reference block output**: the unchanged donor
backbone with the **original FP8 routed experts** (all 256), evaluated on the
**original reference trajectory** for that token position.
- `required = reference − frozen` — the residual the cold experts must supply.
The loss is the relative squared error of the cold-expert sum against `required`:
```
loss = || student_cold(x_student) − required ||² / (denominator · Σw)
```
where `denominator` is the per-row mean energy of `reference − frozen` over the
corpus (so the scale is comparable across layers). Selection metric is
`reference_rel = ||(frozen + cold) − reference|| / ||reference||`, measured over
the **whole transformer block including the residual**, not the cold-experts sum
alone.
**Why reference (and its known weakness).** The transcripts weighed
`reference` against a `same_input` target (match the block's output on the
*student's own* drifted input). The rationale for reference (09-16): "Matching
the original reference trajectory is more directly aligned with preserving the
model's behavior." The acknowledged risk: because each layer receives a
**different (student) input** than the original, the cold experts may lack the
capacity to reproduce the reference output and could "learn corrections that
work on training examples but fail on unseen ones" — i.e. reference-target is
the more out-of-distribution objective. It was chosen only after a matched
layer-4 A/B:
| Layer-4 metric | reference vs same_input |
|---|---|
| validation reference error | **0.21% better** with reference |
| development-audit error | 0.08% **worse** with reference |
A small mixed difference; reference was retained for behavioral alignment. Two
important design consequences: the target is the **complete block output**
(including the residual), so matching only the MoE contribution cannot leave the
incoming residual error untouched; and the loss compares the **routing-weighted
sum of all cold experts** jointly (gate/up and down together).
---
## 5. Sequential per-layer pipeline with trajectory coupling
Layers are processed **sequentially, 3 → 77** (`full_reference.py` /
`sequential_capture.py`):
1. **Capture** (8-way sequence-parallel). For layer L, the student input is the
**retained tuned output of block L-1** (`student_outputs.pt`), while the
reference target re-runs the **donor backbone + original FP8 experts** on the
original reference hidden state. Both trajectories are carried forward in a
rolling cache; layer 3 is the control (no preceding ARVQ layer, so student =
reference input). This cross-layer coupling means each layer is tuned against
the exact drifted inputs it will see at serving time.
2. **Fit / PV tune** the cold experts (Section 6).
3. **Gate** (Section 7).
4. **Export + serialized replay** — decode to the packed format and require the
reloaded forward to match the tuned forward to <2e-6 before use.
5. **Per-layer HF publish** — `publish_reference.py` re-assembles cold slots
across the 8 expert shards, checks slot coverage/allocation/global metadata,
runs the exact index round-trip and sampled decoded-weight parity, then
**atomically replaces that layer's two tensor files + reports in one commit**
with parent-commit protection; remote hashes are re-verified.
Parallelism: cold experts are **sharded across 8 GPUs** (each rank owns distinct
experts); routed outputs are summed with an all-reduce so a single coupled-output
objective is optimized without a dense-model replica.
---
## 6. PV tuning numerics (the published full-corpus campaign)
Per the model card, all 75 layers were replaced by a **full-corpus sequential
PV campaign** drawing sequentially from **18,001,846 training tokens** at
context **1024** (53,248 legacy tokens were removed around 17 exact matches to
held-out prompts). Fixed **validation** and **development-audit** sets each hold
**16,384 tokens**.
- **Optimizer:** Adam. Two trainable parameter groups — FP4-constrained
per-expert **codebooks** and FP8-constrained per-block **scales**. (The
faster fork trains per-row scale deltas instead; the published full-corpus
fork trains the per-128-block log-scales.)
- **Effective batch:** 262,144 tokens, accumulated as **four 65,536-token
microbatch passes** (256 whole 1024-token sequences), one shuffled
no-replacement pass over the corpus.
- **Learning-rate schedule:** book/scale LR **0.048 / 0.032** through update 45,
then dropped by ×0.25 to **0.012 / 0.008** (`lr_decay_after=45`,
`lr_decay_factor=0.25`). (Note: these campaign LRs are higher than the
in-repo code defaults of 0.003/0.002, consistent with the much larger
262k-token batch.)
- **Update budget:** layers 4–26 use a fixed **69 updates**. From layer 27, 69
is the maximum with an **adaptive early stop**: three validation checks more
than 0.1% worse than best trigger an earlier LR reduction; 15 updates without
improvement after that reduction permit stopping.
- **Validation every 5 updates**, retaining the best checkpoint.
- **Index reassignment every 20 updates** (Section 6.1).
- **Regularization:** codebook drift-from-anchor penalty + scale drift penalty,
weighted 0.01; grad-norm clip 1.0; codebook atoms clamped to [-6, 6];
log-scales clamped to within ±0.35 of their initial value.
- **Coverage gate:** experts with fewer than **256 routed training rows** are
frozen (gradient masked) and keep their initial books/scales.
### 6.1 Output-gradient index reassignment
Continuous Adam cannot move the discrete indices, so every 20 updates a discrete
proposal pass runs (`gradient_indices.py`, method
`expert_parallel_output_gradient_prefix_backtracking_v1`):
1. Backprop the **output** loss to the reconstructed weight of one expert
projection.
2. Propose alternative `(a,b)` index pairs near a small gradient step, capped at
`max_fraction=0.001` of groups, `trust_ratio=0.01`, `target_ratio=0.03`; the
current pair is always in the candidate set (changing nothing stays legal).
3. **Prefix backtracking acceptance:** try the top-k proposals with
k∈{full, ¼, 1/16, 1}, accept only if the **training** SSE strictly drops
**and** a separate **check batch** SSE does not increase (beyond 1e-7 slack);
otherwise revert. Proposal deltas are broadcast sparsely (only routed rows).
The transcripts flag this as the method's main theoretical weakness versus
published PV-Tuning: codebooks are tuned for output accuracy while index
proposals originally came from weight-reconstruction Hessians — the
output-gradient proposal above was added to close that gap.
### 6.2 Cold arithmetic emulation
Both training and evaluation emulate the serving numerics (`activation.py`,
pinned to serving revision `b1380cf7…`): **four FP4 activation planes**
(`fp4_planes4_fp16_boundaries_v1`) and **FP16 SwiGLU boundaries** (FP32 GEMM,
FP16 SiLU/product), with straight-through estimators for gradients. This
emulates the quantization boundaries only — **native SM120 MMA accumulation and
TP reduction are not bit-exact** and were not qualified.
---
## 7. Acceptance gates
Publication of a layer requires all of:
- **Validation non-regression:** `0 ≤ final_reference_rel ≤ initial·(1+1e-6)`.
- **Development-audit non-regression:** the held-out audit split (never used for
updates or checkpoint selection) must satisfy
`audit_reference_rel ≤ initial_audit·(1+1e-6)`; otherwise the layer keeps its
initialization. There is no absolute error floor — the rule is purely
final ≤ initial.
- **Serialized-replay parity:** decoded/reloaded forward matches the tuned
forward to <2e-6, and remote file hashes are re-verified after upload.
The audit is honestly labeled **development data, not an untouched final test**;
it is a split of the same calibration tokens the initialization already saw. Two
notable per-layer decisions recorded in the card: **layer 30** retains its
audit-qualified update-15 checkpoint after its validation-best update-20 failed
the development audit; **layer 3** retains a separately qualified lower-LR
refinement.
---
## 8. Calibration corpus
The text corpus (`build_calib_v31.py` + `reasoning_slice.py`) is deterministic
(seed 42), GLM-tokenized, with the following domain mix by tokens:
| Share | Domain | Sources |
|---|---|---|
| ~32% | code | local vLLM sources, m-a-p/CodeFeedback, jtatman/python-code-500k |
| ~20% | tool-calling / agentic | generated GLM chat-template sessions |
| ~15% | reasoning | OpenR1-Math-220k + dolphin-r1 `…` → answer |
| ~13% | instruction chat | tatsu-lab/alpaca + coding chat |
| ~10% | medical | MedQA textbook continuation + medical Q&A |
| ~10% | prose | vLLM docs markdown + databricks-dolly-15k |
The **reasoning slice was added specifically** because the earlier calib-v3 mix
starved the cold 2-bit experts of reasoning-termination behavior: 87% of its
`` blocks were empty. The slice emits multi-turn conversations where an
**earlier** assistant turn carries a real `…` that terminates and
hands off to an answer, followed by a trailing user turn, so the think-close
token **`` (id 154842)** renders in-stream rather than as a trailing
generation prompt. Held-out prompts are explicitly excluded (last 25 vLLM docs,
last 3 MedQA files, vLLM code beyond index 400 of the seed-42 shuffle), and
17 exact-match prompts were purged from the training set.
The capture/training code also supports **up-weighting boundary rows** (rows
whose next token is a boundary such as `` / `<|endoftext|>`) via a
`row_weight` term whose sum normalizes the loss, and an optional matched-mixed
validation set; the published card describes reasoning-based validation.
---
## 9. Results captured during the build
All errors below are **held-out relative L2**, either over the whole transformer
block (including residual) or over the cold-experts sum, as noted. They are
local reconstruction errors, **not** token-accuracy or perplexity.
- **Pilot smoke test** (layer 3, one step): full-block error 0.005497 → 0.005456
(~0.75%), 304/388 expert-projection proposals accepted; exported weights
reproduced the retained result.
- **Layer 3** (200-step pilot): full-block reference error **0.005497 →
0.005271 (−4.12%)**, best at step 200.
- **Layer 4** (200-step pilot): full-block reference error **0.015760 →
0.015596 (−1.05%)**.
- **reference vs same_input** (layer 4, matched): reference 0.21% better on
validation, 0.08% worse on development audit.
- **Faster fork parity:** the optimized fork (larger microbatch, specialized
embedding-lookup backward, sparse proposal broadcast) matched the reference
fork's validation and audit **exactly** on layers 3 and 4, with all propagated
BF16 outputs equal; training loops fell from ~1525 s → ~337 s (layer 3) and
~1226 s → ~303 s (layer 4).
- **Early-layer stability example** (layer 18, full-corpus): initial
0.017205, step-5 0.017176, step-69 0.017183 — differences ≤0.17%, treated as
a signal to watch LR/noise rather than proof of convergence.
Older cold-only checkpoints reported ~0.2211→0.2070 (layer 3) and 0.2364→0.2320,
but those measured **cold-expert output only on different captures** and are
**not comparable** to the full-block errors above.
**No comparison against the FP8 donor or an AQLM variant on perplexity / KLD /
top-1 / wikitext was recorded** in the reviewed transcripts, and no full-model
task evaluation was performed. Those remain open.
---
## 10. Honest limitations
- Full-model quality and native **SM120** execution were **not** evaluated; the
arithmetic emulation covers FP4/FP16 boundaries only, not MMA/TP bit-exactness.
- The development audit is a split of calibration data, not an independent test.
- The reference target is the more OOD objective; its generalization advantage
over same_input was small and mixed on the one matched layer tested.
- Gates enforce local non-regression, not any absolute quality bar.
*Prepared from the GLM-5.3 ARVQ build transcripts (2026-09-14 and 2026-09-16)
and the `btx53/arvq88` fitting/serving code. Where a number could not be sourced
it is stated as unknown rather than estimated.*