canada-quant/hy3-w4a16-mtp
Hy3 W4A16-MTP
Released 2026-07-16. All gates passed: artifact verification (--check-mtp), quality vs FP8 (standard + reasoning-mode), MTP acceptance, serving smoke tests, and a full benchmark matrix against the FP8 baseline and the leading 4-bit community quants (complete methodology + audit trail in the companion repo'sdocs/RUNLOG.md).
Tencent Hy3 quantized to W4A16 with GPTQ — routable MoE experts in INT4, all other weights (attention, dense layer 0, shared expert, NextN/MTP head) preserved in BF16. vLLM-ready (selects the INT4×FP16 Marlin/Machete kernel at load).
Why this artifact
Same box, same harness, same settings for every column (8×H100-SXM, vLLM 0.25.1 — methodology below):
Quality is statistical parity with the FP8 baseline at 57% of its footprint — and among the 4-bit quants, this is the artifact that combines preserved MTP (+40% single-stream vs the same-scheme, MTP-less AngelSlim), the high-concurrency throughput crown (+21% over FP8 at conc 32), BF16 attention (fewest unvalidated surfaces at long context), and a fully reproducible, audited pipeline.
Quick Start
Stock vLLM ≥ 0.25 — no custom patches or forks. One-shot script and Docker image in the companion repo (scripts/quickstart_hopper.sh, docker/); full Hopper guide in docs/deploy-hopper.md.
# Install vLLM (hy_v3 support since v0.20.0; >=0.25 has expert_bias/token-suffix fixes)
pip install 'vllm>=0.25'
# Serve with NextN/MTP speculative decoding on 8 GPUs
vllm serve canada-quant/hy3-w4a16-mtp \
--tensor-parallel-size 8 --enable-expert-parallel \
--speculative-config '{"method":"mtp","num_speculative_tokens":2}' \
--tool-call-parser hy_v3 --reasoning-parser hy_v3 --enable-auto-tool-choice
# --enable-expert-parallel is REQUIRED at TP=8: g128 W4A16 can't split Hy3's
# 1536-wide experts 8 ways (192 % 128 != 0). Alternative: TP=4 without EP.from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed")
response = client.chat.completions.create(
model="hy3-w4a16-mtp",
messages=[{"role": "user", "content": "Explain quantum computing in one paragraph."}],
max_tokens=256,
)
print(response.choices[0].message.content)What Is This?
This is a W4A16-MTP quantized artifact of Tencent Hy3. Approximately 97% of the model's parameters — the routed MoE expert projections (gate/up/down) of layers 1–79 — are compressed to INT4 (group_size=128, symmetric). The rest — attention, dense layer 0, shared expert, embeddings, layer norms, router, LM head, and the NextN/MTP layer — stays in BF16.
The result is a ≈3.4× reduction in on-disk footprint (≈598 GB → ≈172 GB) with minimal quality degradation, while retaining MTP speculative decoding. The artifact serves on 8×, 4×, or (short-context) 2× H200.
What Gets Quantized
Why W4A16?
W4A16 (INT4 weights × FP16 activations) is the sweet spot for large MoE models:
- A16 keeps activations in FP16, matching the Marlin/Machete INT4×FP16 matmul kernel and avoiding the quality loss from activation quantization.
- W4 halves the weight footprint vs INT8 while maintaining quality for expert projections — the ensemble effect of top-8 routing mitigates per-expert quantization error.
- Kernel readiness — vLLM selects the INT4×FP16 Marlin/Machete kernel at load from the compressed-tensors metadata.
NextN / MTP Speculative Decoding
Hy3 includes 1 NextN / MTP layer (num_nextn_predict_layers=1) for speculative decoding. This ≈3.8B-parameter draft head predicts one extra token, allowing the main model to verify and accept it in the same forward pass.
The NextN head is preserved in BF16. Quantizing the draft head stacks its error on top of the hidden-state shift from main-body quantization and compounds across speculative steps, collapsing the acceptance rate.
vLLM has a native hy_v3 MTP proposer (HYV3MTPModel) since v0.20.0; the unified {"method":"mtp"} speculative config selects it automatically. The MTP layer must be present in the checkpoint in BF16 — this artifact re-injects it post-quantization and lists it in quantization_config.ignore (a quantized MTP layer does not load; vLLM #47792). Tencent's official recommendation is num_speculative_tokens=2; the single NextN layer is re-run per speculative step.
See findings/mtp-preservation-strategy.md for the full analysis.
Quality
Measured against the FP8 deployment baseline (tencent/Hy3-FP8), served on the same 8×H100 box with identical settings, using lm-eval 0.4.12 through vLLM's OpenAI-compatible endpoints. Generation tasks are greedy (temperature 0), with the chat template applied; speculative decoding is off for quality runs (it changes latency, not outputs). GSM8K is 5-shot; wikitext perplexity is loglikelihood_rolling via the completions endpoint. (BF16 is not a practical baseline — it does not fit on 8×H100, and FP8 is the deployment-relevant comparison.)
Every task is within ≈0.7 pp of FP8 — inside eval noise (GSM8K ±0.65 pp, IFEval ±≈1.3 pp, HumanEval ±1.8 pp) — so the INT4 experts are effectively quality-neutral vs FP8 at roughly half the footprint (≈172 GB vs ≈300 GB). MTP acceptance of 62.1% aggregate (position-0 76.8%) exceeds the ≈46.7% ungated-greedy figure reported for the official BF16 stack, giving ≈2.24 effective tokens per decode step.
Eval harness/config recorded in docs/RUNLOG.md. Numbers are for this calibration run (agentic+code blend, 512 samples × 2048 tokens); re-running with a different calibration set or harness settings can shift them by ≈noise.Reasoning mode (thinking) — hard benchmarks vs 4-bit community quants
Hy3 gates reasoning via its chat template (reasoning_effort ∈ nothink/low/high, default nothink — the tables above are the conventional non-thinking protocol). The table below runs thinking=high (0-shot, 14k-token generation budget, \boxed{}/letter-grading via math_verify, identical template/harness/server settings for every model, spec-decode off):
All rows: 0-shot, thinking=high, native 256K context (`max_model_len` 262144), 131,072-token generation budget — uniform for every model, no truncation possible for any observed chain. (Earlier 14k/32k-budget runs are superseded: reasoning budget dominates AIME scores.) AIME24/25 are n=30 each (±7–9pp stderr) — read combined. GPQA is flexible-extract.
Every quant is statistically indistinguishable from FP8 and from each other on every bench (AIME n=30 ±7–9pp; GPQA n=198 ±2pp; MATH-500 ±1pp) — 4-bit expert quantization is quality-neutral on this model regardless of algorithm (GPTQ/AWQ) or grouping (g32/g128). The differentiators are serving traits: AngelSlim ships without the MTP layer (cannot speculate at all — capped at 103 tok/s single-stream); ours preserves it in BF16 and holds the high-concurrency throughput crown. See the throughput table.
Budget sensitivity (ours, AIME24/25): 14k → 33/23%; 32k → 53/57%; 131k → 70/83% — the thinking budget, not the quant, was the binding constraint. All models compared at the same unconstrained budget.
How the 4-bit field compares (artifact-level facts)
Notable: AngelSlim's artifact uses the same GPTQ scheme as ours but shipped without the MTP layer — the silent transformers drop this project's inject_mtp.py step exists to fix. On H100 (SM90, no native FP4), NVFP4 weight-only also runs on the Marlin kernel, so the throughput comparison below is same-kernel-class.
Throughput
Measured with vllm bench serve on a single 8×H100-80GB SXM box (TP=8 + expert-parallel, vLLM 0.25.1, random 1024-in/512-out) — every model at every valid speculative config (k = num_speculative_tokens; AngelSlim ships no MTP layer and cannot speculate). Output tok/s (single-stream TPOT ms at concurrency 1):
Takeaways:
- k=2 is the single-stream sweet spot (Tencent's recommendation confirmed); k=3 already regresses and k=5 is clearly counterproductive at every concurrency.
- k=1 is the best all-rounder for this artifact — top of the entire matrix at conc 8 (822) and conc 32 (2146) while still 133.9 tok/s single-stream.
- The MTP layer is worth +40% single-stream — AngelSlim (identical GPTQ scheme and identical quality, but MTP-less) is capped at 103 tok/s vs our 144.
- INT4 beats FP8 at batch: +21% at conc 32 (2127 vs 1762 spec-off) — less weight memory per token; and matches FP8 single-stream once MTP is on.
- AWQ's g32-asym edges single-stream (152.3) but falls off at conc 32 (1751 at k2); ours holds the high-concurrency crown.
Same box, same kernel class (Marlin WNA16) for all INT4 quants. H200 scales higher. Full raw logs + methodology: docs/RUNLOG.md.How It Was Made
- GPTQ calibration with llm-compressor
oneshot()(nightly ≥ 0.12.1a20260708 for hyv3 MoE support), using an **agentic + code + math + chat blend** (`scripts/buildcalibrationdataset.py`, 512 samples × 2048 tokens) — INT4 degrades most on code/tool-call, so the calibration mix targets those experts. `moecalibrateallexperts` (default) ensures every expert receives calibration data despite top-8 routing. Wall time: ≈15.5 h on one H100 (single-process sequential onload).
- MTP re-injection (
scripts/inject_mtp.py): transformers does not instantiate Hy3's NextN layer (model.layers.80) and silently drops it on load, so the BF16 layer is copied back from the source checkpoint after quantization and added toquantization_config.ignore.
- Verification checks safetensors integrity, dtype distribution, group_size=128 confirmation, and NextN/MTP BF16 preservation + ignore-list coverage (
--check-mtp).
There is no separate Marlin-repack step: oneshot() emits compressed-tensors format directly, and vLLM selects the Marlin/Machete kernel internally at load.The full reproducible recipe is at recipe/recipe.yaml.
Serving on Different Hardware
8× H200 SXM5 (Recommended)
bash scripts/serve_h200.sh
# Defaults: TP=8 + --enable-expert-parallel, max_model_len=8192, port 8000,
# --speculative-config '{"method":"mtp","num_speculative_tokens":2}'Per-GPU VRAM: ≈25 GB / 141 GB — ample headroom for long contexts (4×H200 also fits, ≈43 GB/GPU).
8× RTX PRO 6000 Blackwell
bash scripts/serve_rtxpro6000.sh
# Defaults: TP=8, max_model_len=4096, max_num_seqs=4Per-GPU VRAM: ≈25 GB / 96 GB. PCIe-only interconnect — expect reduced throughput vs H200. Cap maxmodellen at 4096. SM120 needs cu128+ builds; Marlin INT4 kernels ship for SM120.
Limitations
- Calibration data: Calibrated on a 512-sample code + math + chat blend (`canada-quant/hy3-w4a16-mtp-calibration`): Magicoder-OSS-Instruct-75K (code, ~38%), gsm8k + MetaMathQA (math), and ultrachat_200k (chat). An agentic/tool-call slice was intended (xLAM / ToolACE) but its source could not be loaded at calibration time, so that budget was redistributed to ultrachat (see
docs/RUNLOG.md). Primarily English; quality may vary for other languages or domains not represented in calibration. - NextN/MTP coupling: The NextN head is preserved in BF16 but not retrained against the quantized distribution. The hidden-state shift from expert quantization causes a modest acceptance-rate drop. This is expected to be within an acceptable range but is non-zero.
- Expert parallelism required at TP=8: g128 W4A16 cannot split the 1536-wide experts 8 ways; serve with
--enable-expert-parallelor TP=4 (see Quick Start). - Acceptance-rate framing: the official BF16 stack measures ≈46.7% ungated aggregate MTP acceptance (independent audit); per-draft-token acceptance at k=1 is much higher. Published numbers will state the exact metric.
- Non-expert sensitivity: Attention, dense layer 0, shared expert, embeddings, and the LM head remain in BF16 — they are excluded for quality, not because they cannot technically be quantized.
- Context length: Hy3 supports up to 256K natively; W4A16 quality at extreme context lengths (>32K) has not been evaluated.
Reproducibility
Every step is scripted and documented:
See findings/quantization-plan.md for the full execution plan, hyperparameter rationale, and risk analysis.
Citation
@misc{canada-quant2025hy3w4a16,
title = {Hy3 W4A16-MTP: GPTQ-Quantized Tencent Hy3 with MTP Speculative Decoding Preservation},
author = {canada-quant},
year = 2026,
url = {https://huggingface.co/canada-quant/hy3-w4a16-mtp}
}