vLLM/Recipes
Search
MiniMax

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

moe427B / 26B1,048,576 ctxvLLM 0.24.0+textmultimodal

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) and non-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 128 is 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-len to 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.0
  • top_p = 0.95
  • top_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.

ConcurrencyTP--max-num-seqsHost KV offloadCUDA graph capture sizes
142none1,2,4,8
182none1,2,4,8
10416none1,2,4 then every 4 up to 64
2048SimpleCPUOffloadevery 4 from 4 to 32
25416SimpleCPUOffloadevery 4 from 4 to 64
30445SimpleCPUOffloadevery 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-size mismatch. 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 with No common block size for 16).
  • Parsers. --tool-call-parser and --reasoning-parser both use minimax_m3 — distinct from minimax_m2 used by earlier releases.
  • Long context KV cache. See Context Length & GPU Memory above — cap --max-model-len or 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:

ModeRepoKV headsDraft KV cache
MHA (default)Inferact/MiniMax-M3-EAGLE364baseline
GQAInferact/MiniMax-M3-EAGLE3-GQA416× 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