GPT-OSS (mixed_gptq)¶
GPT-OSS models (openai/gpt-oss-20b, openai/gpt-oss-120b) are Mixture-of-Experts
(MoE) models with swigluoai activation and per-expert bias. They are served in
vLLM through the OneComp mixed_gptq plugin, but need a few extra steps beyond
the standard GPTQ + vLLM flow:
- Quantize the MoE experts as 4-bit GPTQ, with
group_size=64. - Apply two vLLM runtime patches before serving.
- Disable the FP8 DeepGEMM warmup.
This page covers the full workflow. For the generic GPTQ + vLLM flow, see vLLM Inference.
Why GPT-OSS needs special handling¶
hidden_size= 2880 is not divisible by 128. vLLM's Marlin MoE kernel is unavailable for this shape, so the experts are routed through the WNA16 (MoeWNA16Method) grouped-weight path instead. That path halves the group size to 64 internally, so the experts must be quantized withgroup_size=64(2880 / 64 = 45) for the on-disk scales to match.- Experts carry gate/up/down bias, which the stock WNA16 fused-MoE kernel does not support.
- Experts use
swigluoai, not SiLU, which the stockMoeWNA16Methodhard-asserts against.
OneComp provides a MoeWNA16Method subclass (GptOssWNA16MoEMethod) plus two
source patches to close these gaps.
Requirements¶
Install vLLM with the vllm extra so conch-triton-kernels is present:
On NVIDIA Blackwell (B200, sm100), Conch is required for the mixed_gptq linear
layers when the Marlin kernel cannot handle GPT-OSS weight shapes.
1. Quantize with 4-bit MoE experts¶
Quantize with GPTQ(wbits=4) and keep the experts 4-bit by passing
moe_quant_experts=True to Runner. group_size=64 is required because
hidden_size=2880 is not divisible by 128:
from onecomp import Runner
from onecomp.model_config import ModelConfig
from onecomp.quantizer import GPTQ
runner = Runner(
model_config=ModelConfig(model_id="openai/gpt-oss-20b"), # or gpt-oss-120b
quantizer=GPTQ(wbits=4, groupsize=64), # required: 2880 % 128 != 0
moe_quant_experts=True, # keep experts GPTQ INT4
)
runner.run()
runner.save_quantized_model("./gpt-oss-20b-mixed_gptq")
With moe_quant_experts=True, the experts are saved as per-expert
GPTQLinear tensors — the same on-disk layout as the attention projections:
model.layers.{L}.mlp.experts.{i}.gate_proj.{qweight,qzeros,scales,g_idx}
model.layers.{L}.mlp.experts.{i}.up_proj.{qweight,qzeros,scales,g_idx}
model.layers.{L}.mlp.experts.{i}.down_proj.{qweight,qzeros,scales,g_idx}
and remain listed in the saved quantization_config, so the mixed_gptq plugin
serves them 4-bit. Without the flag (the default), experts are dequantized and
fused into dense bf16 tensors — larger on disk and served full-precision.
group_size
group_size=64 is mandatory for the 4-bit expert path. group_size=128 (or
the channelwise -1) will reload with garbage text because the WNA16 kernel
expects group size 64 for hidden_size=2880.
2. Save / load (Hugging Face format)¶
The checkpoint is a standard Hugging Face directory (sharded *.safetensors +
config.json + quantization_config). No special save call is required; the
runner writes it to ONECOMP_SAVE_DIR.
To sanity-check that the experts were saved as 4-bit (per-expert GPTQ) rather than dense fused tensors:
from onecomp.utils.unfuse_moe import verify_saved_moe_quant_checkpoint
n = verify_saved_moe_quant_checkpoint("./gpt-oss-20b-mixed_gptq")
print(f"per-expert qweight tensors: {n}")
It raises if the checkpoint accidentally contains dense fused gate_up_proj
tensors or deduplicated $ keys.
3. Apply vLLM runtime patches¶
Before constructing LLM(...), patch the installed vLLM:
This applies two idempotent, marker-guarded source patches (safe to run repeatedly; re-running is a no-op once patched):
| Patch | What it does |
|---|---|
gpt_oss_gptq_moe |
Injects a _load_weights_gptq_moe per-expert GPTQ weight-loading path into vLLM's GptOssModel.load_weights, so per-expert qweight/qzeros/scales/g_idx tensors load into the fused w13_* / w2_* MoE params. |
gpt_oss_wna16_bias |
Adds per-expert bias to the WNA16 fused-MoE Triton kernel (fused_moe_kernel_gptq_awq), threads the bias through the dispatch, and forces the Triton path when a bias tensor is present (the compiled CUDA WNA16 kernel has no bias). |
Patch-verified vLLM version
These source patches anchor on specific source strings in vLLM's
fused_moe.py / gpt_oss.py. They are verified against vLLM 0.20.2.
The --extra vllm range (vllm>=0.10,<0.22) is broader than the verified
set: on other versions the anchors may either fail to match (apply_all
raises a RuntimeError, which is safe) or match a subtly changed block and
produce unintended behavior. apply_all logs the installed vLLM version and
emits a warning when it is outside the verified set — check serving output
if you see that warning.
Use --dry-run to validate the patterns without writing files:
The expert routing itself (wrapping vLLM's MoeWNA16Method in
GptOssWNA16MoEMethod) is registered automatically by the mixed_gptq plugin
entry point — no extra step is needed.
4. Serve¶
Disable the FP8 DeepGEMM warmup (OneComp checkpoints do not need it) and load
the checkpoint through vLLM's offline LLM interface: