MiniMaxAI/MiniMax-M3
MiniMax M3 vision-language MoE (427B total / 26B active) for frontier coding, agent toolchains, and 1M-token reasoning via MSA sparse attention — native multimodal (image + video + computer use); BF16 plus MXFP8, NVIDIA Blackwell NVFP4, and AMD MI355X MXFP4 variants. Runs on NVIDIA (Hopper/Blackwell) and AMD CDNA4/CDNA3.
Frontier coding and agent (SWE-Bench Pro 59.0, Terminal-Bench 2.1 66.0); MSA sparse attention; 1M context
Overview
MiniMax-M3 is a frontier vision-language MoE model from MiniMax.
- MSA (MiniMax Sparse Attention) — scalable sparse-attention architecture
that lifts the context window to 1M tokens. MiniMax reports per-token
compute at 1M context reduced to ~1/20 of the previous generation, with
9× prefill and >15× decode speedup vs dense baselines.
- Frontier coding and agent capabilities — SWE-Bench Pro 59.0%, Terminal-Bench 2.1 66.0%, SWE-fficiency 34.8%, KernelBench Hard 28.8%, MCP Atlas 74.2%.
- Native multimodal — image + video inputs, plus computer-use; trained multimodally from step 0.
- Two reasoning modes —
thinking(complex reasoning / agents) andnon-thinking(latency-sensitive), switchable per request.
Prerequisites
- OS: Linux
- Python: 3.10 - 3.13
- NVIDIA: compute capability >= 9.0 (Hopper) recommended; 8x H200 / H20 for a tight single-node BF16 fit, or multi-node TP for long-context headroom
- AMD: MI350X/MI355X (gfx950), MI300X/MI325X (gfx942), ROCm 7.2+. BF16 needs TP=8; the MXFP8 variant runs from TP=4.
--block-size 128is mandatory on every platform (MSA sparse/index cache).
Docker (NVIDIA)
MiniMax-M3 support has not yet shipped in a stable vLLM release — use the dedicated Docker image:
docker pull vllm/vllm-openai:minimax-m3
Docker (AMD ROCm)
Use the nightly image, which is the image the AMD variants of this recipe pin:
docker pull vllm/vllm-openai-rocm:nightly
docker run --rm -it --device /dev/kfd --device /dev/dri --group-add video \
--cap-add SYS_PTRACE --security-opt seccomp=unconfined --ipc=host \
--shm-size=16g -p 8000:8000 \
--entrypoint /bin/bash \
vllm/vllm-openai-rocm:nightly
Launching the Server
NVIDIA — TP8 (8x H200 / H20)
vllm serve MiniMaxAI/MiniMax-M3 \
--tensor-parallel-size 8 \
--block-size 128 \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
TP8 + Expert Parallel
vllm serve MiniMaxAI/MiniMax-M3 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--block-size 128 \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
DP8 + Expert Parallel
vllm serve MiniMaxAI/MiniMax-M3 \
--data-parallel-size 8 \
--enable-expert-parallel \
--block-size 128 \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
AMD ROCm (MI350X/MI355X (gfx950), MI300X/MI325X (gfx942))
On AMD MI300X / MI325X / MI355X, run with CUDA graphs and set the following before any of the serve commands below. It avoids the MiniMax-M3 decode breakable-cudagraph path that would otherwise force eager execution (per @hongxiayang):
export VLLM_USE_BREAKABLE_CUDAGRAPH=0
For gfx950: Prefer using the MXFP8 variant MiniMaxAI/MiniMax-M3-MXFP8 for TP=4 and a smaller
footprint. Use TP=8 for lower latency or long context length, or the default bf16 model.
TP8 (Text or Vision)
vllm serve MiniMaxAI/MiniMax-M3 \
--tensor-parallel-size 8 \
--block-size 128 \
--attention-backend TRITON_ATTN \
--mm-encoder-tp-mode data \
--mm-encoder-attn-backend ROCM_AITER_FA \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
Add the vision-encoder flags (--mm-encoder-tp-mode data --mm-encoder-attn-backend ROCM_AITER_FA) for multimodal serving.
TP8 + --quantization fp8_per_channel
Online per-channel FP8 (PTPC) quantization of the BF16 checkpoint halves the weight footprint (≈100 → ≈50 GiB/GPU, ~1.75× more KV cache) and lifts batched throughput with gsm8k unchanged from BF16 (lossless); These env vars and the flag are for the BF16 checkpoint only.
export VLLM_USE_BREAKABLE_CUDAGRAPH=0
export VLLM_ROCM_USE_AITER=1
export VLLM_ROCM_USE_AITER_MOE=0
vllm serve MiniMaxAI/MiniMax-M3 \
--tensor-parallel-size 8 \
--block-size 128 \
--attention-backend TRITON_ATTN \
--quantization fp8_per_channel \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
TP8 + Expert Parallel
vllm serve MiniMaxAI/MiniMax-M3 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--block-size 128 \
--attention-backend TRITON_ATTN \
--mm-encoder-tp-mode data \
--mm-encoder-attn-backend ROCM_AITER_FA \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
DP8 + Expert Parallel
vllm serve MiniMaxAI/MiniMax-M3 \
--data-parallel-size 8 \
--enable-expert-parallel \
--block-size 128 \
--attention-backend TRITON_ATTN \
--mm-encoder-tp-mode data \
--mm-encoder-attn-backend ROCM_AITER_FA \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
FP8 KV Cache
Add --kv-cache-dtype fp8 to any command for ~1.5× the KV pool — lossless
in our testing across the full native context. Especially worth it for high
concurrency or long context, where KV is the binding constraint.
Context Length & GPU Memory
The full 1M-token window (context_length: 1048576) needs a large KV
cache. To save GPU memory, you can optionally cap the context with
--max-model-len:
vllm serve MiniMaxAI/MiniMax-M3 \
--tensor-parallel-size 8 \
--block-size 128 \
--max-model-len 131072 # 128K instead of the full 1M
AMD ROCm notes: Native context is 512K. To go past it, supply a YaRN rope_scaling on the text config (a top-level override silently misses the decoder's config) and allow the long max length. TP=8 + fp8 KV is the practical combo at 1M:
VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 \
vllm serve MiniMaxAI/MiniMax-M3 \
--block-size 128 \
--kv-cache-dtype fp8 \
--tensor-parallel-size 8 \
--max-model-len 1048576 \
--attention-backend TRITON_ATTN \
--mm-encoder-tp-mode data \
--mm-encoder-attn-backend ROCM_AITER_FA \
--tool-call-parser minimax_m3 \
--enable-auto-tool-choice \
--reasoning-parser minimax_m3 \
--hf-overrides '{"text_config":{"rope_scaling":{"rope_type":"yarn","factor":2.0,"original_max_position_embeddings":524288}}}'
- Set
--max-model-lento the longest prompt + output you actually serve (e.g.32768,131072,262144). A smaller window frees KV-pool headroom for higher concurrency and lets the model fit on fewer GPUs; if you need the full 1M window, consider scaling out with multi-node TP instead.
Client Usage
Recommended sampling parameters (from the model card):
temperature = 1.0top_p = 0.95top_k = 40
Default system prompt:
You are a helpful assistant. Your name is MiniMax-M3 and is built by MiniMax.
Example chat request:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "MiniMaxAI/MiniMax-M3",
"temperature": 1.0,
"top_p": 0.95,
"messages": [
{"role": "system", "content": "You are a helpful assistant. Your name is MiniMax-M3 and is built by MiniMax."},
{"role": "user", "content": "Explain MSA sparse attention in 3 bullets."}
]
}'
Thinking Modes
M3 reasoning is controlled by the thinking_mode, there are three values:
enabled— the model thinks before every response, including after tool results. Use for complex reasoning and agents.disabled— no thinking; the model answers directly. Use for latency-sensitive turns.adaptive(default when unset) — the model decides whether to think based on the task.
Pass it per request through chat_template_kwargs. The same value also tunes
the minimax_m3 reasoning parser, so reasoning and content are
split correctly in every mode.
# Start the MiniMax-M3 model by referring to the command above first.
from openai import OpenAI
client = OpenAI(api_key="EMPTY", base_url="http://localhost:8000/v1")
response = client.chat.completions.create(
model="MiniMaxAI/MiniMax-M3",
messages=[{"role": "user", "content": "Prove there are infinitely many primes."}],
extra_body={"chat_template_kwargs": {"thinking_mode": "enabled"}},
)
msg = response.choices[0].message
print(msg.reasoning) # the <mm:think> block
print(msg.content) # the final answer
Benchmarking
vllm bench serve \
--backend vllm \
--model MiniMaxAI/MiniMax-M3 \
--endpoint /v1/completions \
--dataset-name random \
--random-input 2048 \
--random-output 1024 \
--max-concurrency 10 \
--num-prompt 100
Quantized Variant (MXFP8)
MiniMaxAI/MiniMax-M3-MXFP8
is an MXFP8 checkpoint quantized by NVIDIA from the original FP16 weights —
roughly half the VRAM of the BF16 release. Select the mxfp8 variant above,
or pass the repo id directly to vllm serve:
vllm serve MiniMaxAI/MiniMax-M3-MXFP8 \
--tensor-parallel-size 8 \
--block-size 128 \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
For best MXFP8 throughput, prefer Blackwell (B200/B300) for native MX tensor cores, or AMD CDNA4 (MI350X/MI355X, gfx950) for native MXFP8 matrix cores.
On AMD MI300X, the mxfp8 variant stacks two accuracy-safe scheduling levers from the InferenceX MI300X tuning recipe and avoids the high-concurrency expert-parallel regression by using plain TP8:
export VLLM_ENGINE_READY_TIMEOUT_S=3600
export VLLM_USE_BREAKABLE_CUDAGRAPH=0
export VLLM_ROCM_USE_AITER=1
export VLLM_ROCM_USE_AITER_MHA=0
export TORCH_BLAS_PREFER_HIPBLASLT=1
export NCCL_MIN_NCHANNELS="${NCCL_MIN_NCHANNELS:-112}"
export GPU_MAX_HW_QUEUES="${GPU_MAX_HW_QUEUES:-2}"
vllm serve MiniMaxAI/MiniMax-M3-MXFP8 \
--tensor-parallel-size 8 \
--block-size 128 \
--language-model-only \
--max-model-len "$MAX_MODEL_LEN" \
--attention-backend TRITON_ATTN \
--async-scheduling \
--max-num-batched-tokens 16384 \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
On AMD MI355X the mxfp8 variant additionally enables the AITER kernels,
the fused shared-experts MoE, and INT4 QuickReduce, and pulls the nightly ROCm
image (vllm/vllm-openai-rocm:nightly) — selected automatically in the command
builder. If you launch by hand:
export VLLM_USE_BREAKABLE_CUDAGRAPH=0
export VLLM_ROCM_USE_AITER=1
export VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1
export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4
vllm serve MiniMaxAI/MiniMax-M3-MXFP8 \
--tensor-parallel-size 8 \
--block-size 128 \
--attention-backend TRITON_ATTN \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
MXFP8 high-concurrency options on MI355X
The command above is the default serving configuration and is tuned for the general case. AITER page-16 sparse paged attention helps specifically at long context and high concurrency. It maps MiniMax-M3's top-k 128-token MSA blocks onto AITER page-16 block tables and runs AITER Gluon paged attention over only the selected KV pages.
The high-concurrency configuration is:
# Long context + high concurrency only (isl >= 8k, conc >= 64). Regresses
# short-context / low-concurrency serving.
export VLLM_USE_BREAKABLE_CUDAGRAPH=0
export VLLM_ROCM_USE_AITER=1
export VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1
export VLLM_ROCM_SHUFFLE_KV_CACHE_LAYOUT=1
export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4
export VLLM_ROCM_QUICK_REDUCE_CAST_BF16_TO_FP16=0
export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION_MIN_SIZE_KB=256
vllm serve MiniMaxAI/MiniMax-M3-MXFP8 \
--tensor-parallel-size 4 \
--block-size 128 \
--language-model-only \
--moe-backend aiter \
--kv-cache-dtype fp8 \
--max-num-batched-tokens 32768 \
--attention-backend TRITON_ATTN \
--linear-backend emulation \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
Note: Outside the long-context/high-batch
regime the shuffled layout costs more than it saves; leave it at 0:
export VLLM_ROCM_SHUFFLE_KV_CACHE_LAYOUT=0
Quantized Variant (NVFP4 on Blackwell)
nvidia/MiniMax-M3-NVFP4
is an NVFP4 checkpoint quantized by NVIDIA with ModelOpt. It requires a vLLM
build with MiniMax-M3 NVFP4 support (vllm-project/vllm PR #46380).
Select the nvfp4 variant and B200 hardware in the command builder, or launch the tested B200 baseline directly:
VLLM_FLOAT32_MATMUL_PRECISION=high \
vllm serve nvidia/MiniMax-M3-NVFP4 \
--tensor-parallel-size 8 \
--trust-remote-code \
--block-size 128 \
--tool-call-parser minimax_m3 \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice
Pair it with EAGLE3 speculative decoding (the Spec decoding feature) for
faster decode — the validated B200 benchmark runs the NVFP4 target against the
Inferact/MiniMax-M3-EAGLE3 draft head (3 speculative tokens):
VLLM_FLOAT32_MATMUL_PRECISION=high \
vllm serve nvidia/MiniMax-M3-NVFP4 \
--tensor-parallel-size 8 \
--trust-remote-code \
--block-size 128 \
--language-model-only \
--speculative-config '{"method": "eagle3", "model": "Inferact/MiniMax-M3-EAGLE3", "num_speculative_tokens": 3, "attention_backend": "FLASH_ATTN"}'
For long-context or high-batch workloads where draft KV memory is the binding constraint, swap in the GQA variant:
VLLM_FLOAT32_MATMUL_PRECISION=high \
vllm serve nvidia/MiniMax-M3-NVFP4 \
--tensor-parallel-size 8 \
--trust-remote-code \
--block-size 128 \
--language-model-only \
--speculative-config '{"method": "eagle3", "model": "Inferact/MiniMax-M3-EAGLE3-GQA", "num_speculative_tokens": 3, "attention_backend": "FLASH_ATTN"}'
You may also consider FlashInfer for draft attention if it performs better for your workload, and local argmax reduction to reduce communication traffic:
--speculative-config '{"method":"eagle3","model":"Inferact/MiniMax-M3-EAGLE3-GQA","num_speculative_tokens":3,"attention_backend":"FLASHINFER","use_local_argmax_reduction":true}'
GB200: InferenceX AgentX aggregated (Dynamo + vLLM)
The GB200 AgentX lane in SemiAnalysis InferenceX (minimaxm3-fp4-gb200-dynamo-vllm-agentic-agg-mtp, SemiAnalysisAI/InferenceX#4281) serves the NVFP4 checkpoint with the GQA EAGLE3 draft (three speculative tokens) as one aggregated vLLM worker behind the Dynamo frontend's KV-aware router. TP4 runs on one 4-GPU GB200 tray; TP8 spans two trays. Image vllm/vllm-openai:nightly-5555a2d8f7116b2b4877f66516f4128176cf722a@sha256:8896fd7b29fc4ee7ce839f146cb4757984c476ec79d0234ffa8c995dee6e339a, Dynamo 1.6.0.dev20261016 (pip install ai-dynamo==1.6.0.dev20261016).
In the command builder, pick GB200 and the NVFP4 variant (the builder keeps the current variant when you switch hardware, so select NVFP4 explicitly), turn on Spec Decoding → GQA and Text-only, and use Single-node TP for TP4 or Multi-node TP with 2 nodes for TP8. That renders the worker flags and environment below as a vllm serve command. Direct links: TP4 and TP8 on two trays. The GB200 Verified badge applies to this NVFP4 profile only; the GQA draft and TP8 all-reduce overrides also apply to the other variants on GB200, which were not qualified.
For the host-KV-offload points, don't use the KV Offload → Simple pill as is: its budget is fixed at 220 GiB per rank (880 GiB per 4-GPU tray) with lazy_offload: false, which is more host memory than a GB200 tray can give KV blocks. Replace its --kv-transfer-config with the qualified one below and set VLLM_USE_SIMPLE_KV_OFFLOAD=1. The per-concurrency settings in this table, the Dynamo KV-router frontend and its services stay in this guide.
| Concurrency | TP | --max-num-seqs | Host KV offload | CUDA graph capture sizes |
|---|---|---|---|---|
| 1 | 4 | 2 | none | 1,2,4,8 |
| 1 | 8 | 2 | none | 1,2,4,8 |
| 10 | 4 | 16 | none | 1,2,4 then every 4 up to 64 |
| 20 | 4 | 8 | SimpleCPUOffload | every 4 from 4 to 32 |
| 25 | 4 | 16 | SimpleCPUOffload | every 4 from 4 to 64 |
| 30 | 4 | 45 | SimpleCPUOffload | every 4 from 4 to 180 |
Every list ends with 256,512,1024,2048 and uses {"cudagraph_mode":"FULL_AND_PIECEWISE","cudagraph_capture_sizes":[...]}. Sizes 1 and 2 give the drafter's decode steps full CUDA graphs at concurrency 1.
The InferenceX throughput points replaced block verification with synthetic rejection at the committed golden EAGLE3-GQA acceptance length (2.78 for MiniMax-M3 with three draft tokens, thinking on; minimaxm3_eagle3_gqa.yaml) so every point is measured at the same acceptance rate. Production serving keeps the default rejection sampler, as in the command below; the lane's accuracy evals ran that way.
Services and environment
Start etcd and NATS (JetStream on, 32 MB max payload) once:
etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://<infra-host>:2379
printf 'max_payload: 33554432\njetstream {}\n' > nats.conf && nats-server -c nats.conf
On every worker tray (and on the frontend host, point the same two variables at the services):
export ETCD_ENDPOINTS=http://<infra-host>:2379 NATS_SERVER=nats://<infra-host>:4222
export VLLM_FLOAT32_MATMUL_PRECISION=high VLLM_FLASHINFER_ALLREDUCE_BACKEND=trtllm
export NCCL_CUMEM_ENABLE=1 NCCL_MNNVL_ENABLE=1 NCCL_NVLS_ENABLE=1
export UCX_MEMTYPE_CACHE=n UCX_TLS=cuda_copy,cuda_ipc,rc
Set UCX_NET_DEVICES and NCCL_IB_HCA to the node's RDMA devices. For TP8 across two trays, use VLLM_FLASHINFER_ALLREDUCE_BACKEND=mnnvl instead of trtllm. Loading the 1M-context engine takes a while, so raise VLLM_ENGINE_READY_TIMEOUT_S and VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS well above their defaults.
Worker
python3 -m dynamo.vllm --model nvidia/MiniMax-M3-NVFP4 --served-model-name nvidia/MiniMax-M3-NVFP4 \
--request-plane tcp --device-ids 0,1,2,3 \
--tensor-parallel-size 4 --pipeline-parallel-size 1 --trust-remote-code \
--attention-config '{"backend":"FLASHINFER","use_trtllm_attention":true,"indexer_kv_dtype":"fp8","minimax_m3_msa_decode_backend":"cutlass"}' \
--kv-cache-dtype fp8 --block-size 128 --enable-prefix-caching \
--speculative-config '{"method":"eagle3","model":"Inferact/MiniMax-M3-EAGLE3-GQA","num_speculative_tokens":3,"attention_backend":"FLASHINFER","use_local_argmax_reduction":true}' \
--max-model-len 1048576 --max-num-batched-tokens 16384 --max-num-seqs <S> \
--compilation-config '{"cudagraph_mode":"FULL_AND_PIECEWISE","cudagraph_capture_sizes":[<sizes from the table>,256,512,1024,2048]}' \
--gpu-memory-utilization 0.9 --no-enable-flashinfer-autotune --stream-interval 20 --language-model-only \
--kv-events-config '{"publisher":"zmq","topic":"kv-events","enable_kv_cache_events":true,"endpoint":"tcp://*:5200"}' \
--reasoning-parser minimax_m3 --dyn-reasoning-parser minimax_m3 --dyn-tool-call-parser minimax_m3
The pinned nightly predates the --disable-flashinfer-autotune spelling (added in vLLM #61479), so this command uses --no-enable-flashinfer-autotune; newer images accept both. The command builder renders the same flag for GB200.
For TP8, run the same command on both trays with --tensor-parallel-size 8 --nnodes 2 --node-rank <0|1> --master-addr <first-tray-ip>, adding --headless on node rank 1.
For the host-KV-offload points, also set VLLM_USE_SIMPLE_KV_OFFLOAD=1 and add:
--kv-transfer-config '{"kv_connector":"SimpleCPUOffloadConnector","kv_role":"kv_both","kv_connector_extra_config":{"cpu_bytes_to_use":777389080576,"cpu_bytes_to_use_per_rank":194347270144,"lazy_offload":true}}'
That gives each of the four ranks about 181 GiB of pinned host memory for KV blocks.
Frontend
export ETCD_ENDPOINTS=http://<infra-host>:2379 NATS_SERVER=nats://<infra-host>:4222 DYN_REQUEST_PLANE=tcp
export DYN_TOKENIZER=fastokens DYN_TOKENIZER_CACHE_BYTES=8589934592 DYN_TCP_REQUEST_TIMEOUT=60
python3 -m dynamo.frontend --trust-remote-code \
--router-mode kv --router-kv-events --router-temperature 0 \
--router-session-affinity-ttl-secs 14400 --kv-cache-block-size 128
The KV router uses the workers' KV events to send each request to the worker holding its prefix, and session affinity keeps a conversation on that worker: send a stable conversation ID in the X-Dynamo-Session-ID request header. This Dynamo build warns that --router-temperature is deprecated and will be removed in v1.7; newer builds take router_temperature in the default policy parameters of --router-policy-config.
Quantized Variant (MXFP4 on MI355X)
amd/MiniMax-M3-MXFP4
uses static OCP MXFP4 weights and dynamic OCP MXFP4 activations produced with
AMD Quark. It targets AMD Instinct MI355X (gfx950) and requires a ROCm
nightly containing the Quark MXFP4 fix from vLLM PR #45794.
Select the mxfp4 variant and MI355X hardware in the command builder, or launch the tested TP8 baseline directly:
vllm serve amd/MiniMax-M3-MXFP4 \
--tensor-parallel-size 8 \
--trust-remote-code \
--block-size 128 \
--attention-backend TRITON_ATTN \
--mm-encoder-tp-mode data \
--mm-encoder-attn-backend ROCM_AITER_FA \
--tool-call-parser minimax_m3 \
--enable-auto-tool-choice \
--reasoning-parser minimax_m3
MXFP4 AgentX on MI355X
The opt-in AgentX preset follows InferenceX #4418 on its pinned ROCm image: TP4 at concurrency 1, 4, 5, 8, 10, 12, 15, 20, 24 and 32 enables monokernel; TP2 at 1 and 2 uses ordinary decode. Both use Model Runner V2, the three-token GQA EAGLE3 draft and real target verification, with no offload. These text-only MXFP4 settings are workload-specific; the general serving configuration remains unchanged. Synthetic acceptance is for throughput reproduction only, as described in the preset's runbook.
Troubleshooting
--block-sizemismatch. MSA's sparse block size is 128; the vLLM KV cache block size must match. Using the default (16) misaligns the sparse attention indexing (on AMD it crashes withNo common block size for 16).- Parsers.
--tool-call-parserand--reasoning-parserboth useminimax_m3— distinct fromminimax_m2used by earlier releases. - Long context KV cache. See Context Length & GPU Memory above — cap
--max-model-lenor scale to multi-node TP if you OOM. - Vision encoder. The encoder is small, so at high TP the Encoder
Parallel option runs it data-parallel (
--mm-encoder-tp-mode data) to avoid TP comm overhead; it also turns on the vision-encoder attention backend (FlashInfer on NVIDIA,--mm-encoder-attn-backend FLASHINFER; AITER FlashAttention on AMD,ROCM_AITER_FA) and the host-shared-memory multimodal processor cache (--mm-processor-cache-type shm). For text-only workloads enable Text only (--language-model-only) to skip loading the encoder and free VRAM — it is mutually exclusive with Encoder Parallel.
EAGLE3 Speculative Decoding
Two Inferact draft heads are available as selectable modes in the Spec decoding
feature — both use method: eagle3 with 3 speculative tokens and share
MiniMax-M3's embedding table and LM head:
| Mode | Repo | KV heads | Draft KV cache |
|---|---|---|---|
| MHA (default) | Inferact/MiniMax-M3-EAGLE3 | 64 | baseline |
| GQA | Inferact/MiniMax-M3-EAGLE3-GQA | 4 | 16× smaller |
The GQA head uses Grouped Query Attention (4 KV heads grouped from 64 query heads) — the only architectural difference from the MHA head. The 16× reduction in draft KV state makes it preferable when draft memory is the binding constraint (long-context serving or large batch sizes).
References
Configurations qualified on specific hardware, layered on the baseline command. Unless marked Opt-in, a preset applies automatically on its hardware and strategy; pick Baseline in the builder to drop it.
One 8-GPU H200 node, TP8, with the GQA EAGLE3 draft (three tokens) and thinking always on; the scheduler batch is twice the concurrency.
8 points · concurrency 1–14 · image vllm/vllm-openai:nightly-83c078d9…@sha256:cb12c3016938…
Runbook
The H200 AgentX lane in SemiAnalysis InferenceX (minimaxm3-fp8-h200-vllm-agentic-mtp, SemiAnalysisAI/InferenceX#4429) serves the MXFP8 checkpoint with the GQA EAGLE3 draft (three speculative tokens) as one aggregated vLLM worker on a single 8-GPU H200 node: TP8, no expert parallelism, no host KV offload.
The InferenceX throughput points replaced block verification with synthetic rejection at the committed golden EAGLE3-GQA acceptance length (2.78 for MiniMax-M3 with three draft tokens, thinking on; minimaxm3_eagle3_gqa.yaml) so every point is measured at the same acceptance rate. The command above does not set it.
TP4 on four of the node's eight B200 GPUs with the GQA EAGLE3 draft (three tokens, local argmax reduction); the larger points add host KV offload.
4 points · concurrency 15–38 · image vllm/vllm-openai:nightly-af7f9488…@sha256:8e2ffbb9f866…
Runbook
The B200 AgentX lane in SemiAnalysis InferenceX (minimaxm3-fp4-b200-vllm-agentic-mtp and minimaxm3-fp4-b200-vllm-agentic-mtp-c10, SemiAnalysisAI/InferenceX#4382) serves the NVFP4 checkpoint with the GQA EAGLE3 draft as one aggregated vLLM worker on a single 8-GPU B200 node. Most points run TP4; the concurrency-10 arm also has a TP8 point.
The host-KV-offload points pin 1,073 GB of host memory for KV blocks across the node (lazy offload).
The Verified badge for this GPU is recipe-wide. This preset covers the NVFP4 variant only; the GQA draft override in features.spec_decoding also applies to the other variants on this GPU, which were not qualified.
The InferenceX throughput points replaced block verification with synthetic rejection at the committed golden EAGLE3-GQA acceptance length so every point is measured at the same acceptance rate. Production serving keeps the default rejection sampler, as in the command above.
Caps the sequences the scheduler keeps active (--max-num-active-seqs) well below the concurrency, with a five- or three-token GQA draft without local argmax reduction.
6 points · concurrency 10–32 · image vllm/vllm-openai:nightly-ac7509e2…@sha256:98adb2311118…
Runbook
The B200 AgentX lane in SemiAnalysis InferenceX (minimaxm3-fp4-b200-vllm-agentic-mtp and minimaxm3-fp4-b200-vllm-agentic-mtp-c10, SemiAnalysisAI/InferenceX#4382) serves the NVFP4 checkpoint with the GQA EAGLE3 draft as one aggregated vLLM worker on a single 8-GPU B200 node. Most points run TP4; the concurrency-10 arm also has a TP8 point.
The Verified badge for this GPU is recipe-wide. This preset covers the NVFP4 variant only; the GQA draft override in features.spec_decoding also applies to the other variants on this GPU, which were not qualified.
The InferenceX throughput points replaced block verification with synthetic rejection at the committed golden EAGLE3-GQA acceptance length so every point is measured at the same acceptance rate. Production serving keeps the default rejection sampler, as in the command above.
One B300 node: TP8 at concurrency 1, TP4 at 20 and 24, TP2 with host KV offload at 24 and 28; GQA EAGLE3 draft (three tokens, local argmax reduction).
5 points · concurrency 1–28 · image vllm/vllm-openai:nightly-49cb2bbf…@sha256:8c1434bfee7d…
Runbook
The B300 AgentX lane in SemiAnalysis InferenceX (minimaxm3-fp4-b300-vllm-agentic-mtp, SemiAnalysisAI/InferenceX#4357) serves the NVFP4 checkpoint with the GQA EAGLE3 draft (three speculative tokens) as one aggregated vLLM worker on a single B300 node: TP8 at concurrency 1, TP4 at concurrency 20 and 24, and TP2 at 24 and 28 with host KV offload.
The TP2 points pin 749 GB of host memory for KV blocks (lazy offload).
The Verified badge for this GPU is recipe-wide. This preset covers the NVFP4 variant only; the GQA draft override in features.spec_decoding also applies to the other variants on this GPU, which were not qualified.
The InferenceX throughput points replaced block verification with synthetic rejection at the committed golden EAGLE3-GQA acceptance length (2.78 for MiniMax-M3 with three draft tokens, thinking on; minimaxm3_eagle3_gqa.yaml) so every point is measured at the same acceptance rate. The command above does not set it.
MXFP4 with the GQA EAGLE3 draft (three tokens), thinking on and no offload; TP4 enables the pinned image's monokernel, while TP2 uses ordinary decode.
12 points · concurrency 1–32 · image vllm/vllm-openai-rocm:nightly-df6603f0…@sha256:81899892d737…
Runbook
This opt-in MXFP4 profile follows InferenceX #4418
at f10885621773d1f900b6b4d002ee37863e583af3: the
agg-variants.yaml SRT bundle
for minimaxm3-fp4-mi355x-vllm-agentic-mtp. It serves
amd/MiniMax-M3-MXFP4 on one
MI355X node, text-only, with no expert parallelism, model offload or KV offload.
Both TP4 and TP2 use Model Runner V2; every point sets max-num-seqs to twice
its client concurrency. INT4 QuickReduce, FP8 KV/indexer caches, the 0.9 memory
fraction and the 128-token graph limit are specific to this workload.
TP4 enables the pinned df6603f monokernel.
It handles supported physical decode widths 1–16 with EAGLE3 K3; larger or
mixed steps fall back to ordinary decode. TP2 omits --monokernel because
this implementation requires TP4. The profile reproduces that image, not
later monokernel implementations or general MiniMax-M3 defaults.
Source run 39890471932 contains the twelve throughput points and their real-verification evals. The audited head's bound serving configurations match that run's source. Reuse run 40416678647 skipped the GPU matrices; it is not a fresh qualification. The earlier #2959 baseline does not qualify this image or monokernel. Performance is reported by InferenceX; local recipe validation does not reproduce GPU performance.
Ordinary serving and accuracy evaluation retain real target verification.
Throughput reproduction alone adds the following keys to --speculative-config:
{"rejection_sample_method":"synthetic","synthetic_acceptance_length":2.78}
The golden 2.78 acceptance length
is for the three-token GQA draft with thinking enabled. Synthetic rejection
bypasses real verification; never use it for users or accuracy evals.
AgentX's AIPERF_APPLY_CHAT_TEMPLATE=true and required vllm: metrics prefix
are benchmark-client settings, not server flags. The source's
dram-utilization: 0.20 is orchestration metadata, not KV offload.