* [Model] Add MiniMax M3 text backbone skeleton + SwiGLU-OAI clamp activation Port the MiniMax M3 (text backbone) into vLLM's custom model layout: - Add MiniMaxM3SparseForCausalLM under vllm/models/minimax_m3/nvidia with the decoder/model/causal-LM wiring; attention and MoE bodies plus weight loading are left as stubs. Dense MiniMaxM3MLP is fully ported. - Add MiniMaxM3SparseForConditionalGeneration as a minimal LM-routing wrapper (KimiK25-style init_vllm_registered_model on text_config) and register both architectures. - Add MiniMaxM3Config (model_type minimax_m3_vl) wrapping MiniMaxM3TextConfig so config.get_text_config() extracts the backbone; register in the config registries. Generalize silu_and_mul_with_clamp to SwiGLU-OAI: - Add alpha (scales the activation's sigmoid) and beta (added to the non-activated half) to the CUDA kernel, ops.h, and torch_bindings schema. Defaults alpha=1.0, beta=0.0 are bitwise-identical to the previous silu(gate)*up, so existing callers (DeepSeek V4) are unaffected. - SiluAndMulWithClamp(alpha, beta) used by MiniMaxM3MLP with alpha=swiglu_alpha, beta=1.0, matching the reference gate*sigmoid(alpha*gate)*(up+1). AI assistance (Claude) was used for this change. Signed-off-by: Yongye Zhu <yongye@inferact.ai> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * [Model] MiniMax M3: implement MoE block + weight-name mapping Implement the sigmoid-routed MoE block for MiniMax M3 and map module names to the checkpoint so weight loading works for the ported modules. MoE block (MiniMaxM3MoE): - fp32 router via GateLinear (bf16 activations upcast to fp32; fp32 weights and logits), matching minimax_m2/sglang precision. - FusedTopKBiasRouter routing (scoring_func from config, sigmoid + e_score_correction_bias + renormalize), verified to match sglang's TopK (select-with-bias, weight-without-bias, routed_scaling on output). - swigluoai activation (from config.hidden_act) + swiglu_limit; shared expert fused into FusedMoE so the shared partial is reduced with the routed output. Weight loading: - Name the MoE submodule `block_sparse_moe` (dense stays `mlp`) to match the checkpoint; decoder forward selects per layer. - load_weights handles gate_up fusion (dense MLP + shared experts) and expert w1/w2/w3 -> w13/w2 fusion; wrappers delegate via AutoWeightsLoader, skipping vision/mm/mtp. Not-yet-ported modules (attention) are skipped until they land. The expert GEMM/activation kernel correctness and attention/weight loading for the remaining modules are not part of this change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * [MiniMax M3] Port attention modules and wire up MXFP8 checkpoint loading Port the weight-bearing dense (MiniMaxM3Attention) and sparse (MiniMaxM3SparseAttention) attention modules so the checkpoint's self_attn.* tensors map onto real params (forward still stubbed; this targets weight loading). Add qkv stacked mapping and the weight_scale_inv -> weight_scale remap in load_weights. Load MiniMax-style MXFP8 checkpoints (quant_method: "mxfp8" + ignored_layers) via the ModelOpt MXFP8 config: register "mxfp8" in method_to_config and normalize the minimal checkpoint schema to the ModelOpt schema in ModelOptMxFp8Config.from_config (same on-disk format). Use setdefault for online shorthands so the checkpoint config wins over the "mxfp8" online shorthand. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Yongye Zhu <yongye@inferact.ai> Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * [MiniMax M3] Add DeepGEMM MXFP8 MoE backend with swigluoai support Extend DeepGemmExperts to support MXFP8 activations (FP8 e4m3 + UE8M0 1x32 block scales) via the grouped GEMM with recipe (1, 32), reusing the oracle/fp8 weight-conversion path. Generalize deepgemm_post_process_fp8_weight_block to derive the transform recipe from the block shape ((1, 1, 32) for MXFP8) and accept uint8 E8M0 scales. Unify the fused gated-activation+quant triton kernels around y = (up + beta) * gate * sigmoid(alpha * gate): silu is alpha=1, beta=0 (bit-identical to before); swigluoai uses alpha/beta from config. Thread gemm1_alpha/gemm1_beta from the FusedMoE layer through the MXFP8 quant config into the kernels, and add swiglu_alpha/swiglu_beta to the layer and MiniMax M3 config/model (beta sourced from config, not hardcoded). Wire Fp8MoeBackend.DEEPGEMM into the MXFP8 oracle (selectable via --moe-backend deep_gemm), resolving directly to DeepGemmExperts (the Triton fallback cannot handle the 1x32 scheme). Advertise SWIGLUOAI in _supports_activation so swigluoai selects DeepGEMM rather than falling through to another backend; gate the MXFP8 scheme to Blackwell (SM100). Verified on GB200: packed-kernel parity (silu defaults unchanged, swigluoai matches torch ref), (1,32) weight-prep transform, and a TP=4 launch selecting the DEEPGEMM MXFP8 backend with full weight load (the run then stops at the still-stubbed attention forward, as expected). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Yongye Zhu <yongye@inferact.ai> Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * [MiniMax M3] Implement dense attention forward Implement MiniMaxM3Attention.forward (dense path): qkv projection, split, per-head QK norm (GemmaRMSNorm, qk_norm_type="per_head"), partial RoPE, attention, and output projection. Mirrors the sglang reference dense path and vLLM's canonical per-head-norm convention. attention_output_gate is False for M3, so the gate branch is omitted. The sparse attention forward (index branch) remains stubbed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Yongye Zhu <yongye@inferact.ai> Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * [MiniMax M3] Drop dead index value/output projection branch For M3, sparse_disable_index_value matches sparse_attention_freq exactly ([0,0,0,1,...,1]): the only layers with the flag unset (0-2) are the non-sparse layers built as MiniMaxM3Attention. Every layer that constructs MiniMaxM3SparseAttention therefore always disables the index value/output projections, so index_{v,o}_proj are never created. Remove the unreachable else branch, the disable_index_value parameter and field, and the now-unused _disable_index_value_layer_ids helper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Yongye Zhu <yongye@inferact.ai> Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * [MiniMax M3] Add sparse-attention backend + merged attention layer Scaffold the lightning-indexer sparse-attention path: - MiniMaxM3SparseBackend (registered as MINIMAX_M3_SPARSE): block-sparse GQA backend; get_kv_cache_shape serves both the main K/V cache and the single-vector index-key side cache. - MiniMaxM3IndexerCache: side KV cache for per-token index keys, key-only so it uses a single-vector MLAAttentionSpec rather than a K+V FullAttentionSpec. - MiniMaxM3SparseMetadata (+ prefill/decode sub-metadata) and its builder, splitting the batch via split_decodes_and_prefills. - MiniMaxM3SparseImpl: subclasses AttentionImplBase so it can take a custom forward(query, index_query, kv_cache, index_kv_cache); no alibi / sliding window / logits soft cap. forward is a stub pending the kernel port. MiniMaxM3SparseAttention is merged into a single AttentionLayerBase: it owns the projections, per-head QK norm and RoPE, binds the backend + impl, registers the main K/V cache, and holds the index cache. Its forward computes q/k/v and the index q/k, pre-inserts K/V and index-K into their caches, then calls the sparse impl with only the queries. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Yongye Zhu <yongye@inferact.ai> Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * [MiniMax M3] Implement sparse-attention forward + MXFP8 DeepGEMM MoE e2e Port the MiniMax M3 lightning-indexer sparse attention to a Triton backend and fix the MXFP8 DeepGEMM MoE path so the model runs end to end. Attention (vllm/v1/attention/ops/minimax_m3_sparse_ops.py + backend): - Triton kernels (paged, page == sparse block == 128): index block-score + bitonic top-k, and GQA block-sparse flash attention over the selected blocks. - MiniMaxM3SparseImpl.forward: decode-first split, dispatching the same kernels per phase (a decode token is a 1-token prefill). Index and main caches use separate block tables. - Dedicated MiniMaxM3IndexerBackend for the key-only index cache so the main GQA cache (num_kv_heads==1 at TP>=4) is not mistaken for the index layout. - get_supported_kernel_block_sizes()==[128] (one sparse block per KV page). MXFP8 DeepGEMM MoE: - Prepare-phase activation quant emits float32 per-(1,32) group scales for the DeepGEMM backend (use_deep_gemm_packed_mxfp8 on the quant config), matching the FP8 128-block path with group=32. - deepgemm_moe_permute / ep_scatter take a block_size so the activation-scale group (32) is honored through the expert permute. - workspace_shapes uses the contiguous-layout M alignment (not block_shape[0], which is 1 for MXFP8 and under-sized the workspace). GSM8K (5-shot, TP=4) flexible-extract 0.921 / strict 0.919. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Yongye Zhu <yongye@inferact.ai> Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * draft vl impl Signed-off-by: Isotr0py <Isotr0py@outlook.com> * try to load Signed-off-by: Isotr0py <Isotr0py@outlook.com> * don't rename o_proj Signed-off-by: Isotr0py <Isotr0py@outlook.com> * fix vit loading Signed-off-by: Isotr0py <Isotr0py@outlook.com> * ooops Signed-off-by: Isotr0py <Isotr0py@outlook.com> * ooops Signed-off-by: Isotr0py <Isotr0py@outlook.com> * [MiniMax M3] Enable decode CUDA graphs + dedicated split-K decode kernels (#7) Two changes to the sparse-attention backend: 1. Full decode CUDA-graph support. The metadata builder now declares AttentionCGSupport.UNIFORM_SINGLE_TOKEN_DECODE and precomputes all per-step kernel args (cu_seqlens_q, prefix_lens, max_query_len, num_actual_tokens) in build(), removing the .item() host sync and the per-step torch.zeros/cumsum/diff from the impl forward. Derived decode prefix lengths are written into a persistent buffer so the captured graph reads stable addresses across replays. 2. Dedicated split-K decode kernels (mirroring the sglang reference) instead of reusing the prefill kernels with BLOCK_SIZE_Q=1, which left the GPU idle at decode (one query token per request). The index score now splits over seq blocks and the GQA attention splits over the selected top-k blocks with an LSE merge (flash-decoding). Chunk counts depend only on shape constants, so the grid is fixed within a CUDA graph. Verified: a parity test against the prior (GSM8K 92.1) prefill-as-decode path matches exactly on top-k selection and on attention output (bf16 noise) across seq lengths 128-2048. Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> * [MiniMax M3 VL] Multimodal (ViT) support: vendored processor, ViT fixes, encoder features Make MiniMaxAI/Minimax-M3-preview serve as a VL model: - registry: move ...ForConditionalGeneration to _MULTIMODAL_MODELS - vendor the HF processor (image/video/composite) so no --trust-remote-code, constructed directly in get_hf_processor; Qwen-style smart_resize - vision_tower: disable post_layernorm (matches reference), fp32 RoPE, backend-aware encoder metadata enabling flashinfer_cudnn ViT - model: supports_encoder_tp_data + fix --mm-encoder-tp-mode data DP branch - mm_preprocess: cap dummy video frames; smart_resize token counting AI-assisted (Claude Code); WIP, pending human review + test re-run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [MiniMax M3 VL] Align video timestamps with the MiniMax reference Request video metadata (fps + sampled frame indices) via MultiModalDataParser(video_needs_metadata=True) and forward it as VideoMetadata so the processor emits per-frame "]<]X.X seconds[>[" markers. _get_prompt_updates reconstructs the same markers from the metadata (using the HF formula frames_indices[frame*temporal_patch_size]/fps) so the prompt replacement stays byte-aligned with the processor output. Falls back to no timestamps when metadata is absent (dummy/profiling videos), keeping both paths consistent. Verified: processor emits the expected timestamps; the piecewise replacement exactly matches the tokenized video region; server video requests succeed (no placeholder mismatch) and image inference is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * m3 video loader and processor cleanup Signed-off-by: Isotr0py <Isotr0py@outlook.com> * Fix pre-commit lint/type errors in MiniMax M3 VL files The new MiniMax M3 VL files live outside vllm/model_executor/models (which mypy excludes), so they are linted and type-checked in CI. Make all hooks pass: - ruff: reorder default_weight_loader import (isort); drop trailing whitespace in vision_tower.py. - typos: allowlist `tpos` (temporal position id, parallels the existing hpos/wpos vision-RoPE naming). - mypy: - annotate round/ceil/floor_by_factor as `int | float` (matches ernie45_vl); they are called with float values. - `# type: ignore[call-arg]` on the ImagesKwargs/VideosKwargs/ ProcessingKwargs `total=False` subclasses (matches ovis/isaac/etc.). - cast dummy-option overrides to ImageDummyOptions/VideoDummyOptions and the videos mm_data value to `list` before iterating. - assert multimodal_config is not None before reading mm_encoder_tp_mode. - skip None results when building mm_input_by_modality so the strict `dict[str, dict]` annotation holds and no None reaches the embedders. Verified locally: ruff-check, ruff-format, typos, check-spdx-header, check-root-lazy-imports, and mypy (3.10/3.11/3.12/3.13) all pass on the changed files. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Roger Wang <hey@rogerw.io> --------- Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> Signed-off-by: Isotr0py <Isotr0py@outlook.com> Signed-off-by: Roger Wang <hey@rogerw.io> Co-authored-by: Yongye Zhu <zyy1102000@gmail.com> Co-authored-by: Isotr0py <Isotr0py@outlook.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Easy, fast, and cheap LLM serving for everyone
| Documentation | Blog | Paper | Twitter/X | User Forum | Developer Slack |
🔥 We have built a vLLM website to help you get started with vLLM. Please visit vllm.ai to learn more. For events, please visit vllm.ai/events to join us.
About
vLLM is a fast and easy-to-use library for LLM inference and serving.
Originally developed in the Sky Computing Lab at UC Berkeley, vLLM has grown into one of the most active open-source AI projects built and maintained by a diverse community of many dozens of academic institutions and companies from over 2000 contributors.
vLLM is fast with:
- State-of-the-art serving throughput
- Efficient management of attention key and value memory with PagedAttention
- Continuous batching of incoming requests, chunked prefill, prefix caching
- Fast and flexible model execution with piecewise and full CUDA/HIP graphs
- Quantization: FP8, MXFP8/MXFP4, NVFP4, INT8, INT4, GPTQ/AWQ, GGUF, compressed-tensors, ModelOpt, TorchAO, and more
- Optimized attention kernels including FlashAttention, FlashInfer, TRTLLM-GEN, FlashMLA, and Triton
- Optimized GEMM/MoE kernels for various precisions using CUTLASS, TRTLLM-GEN, CuTeDSL
- Speculative decoding including n-gram, suffix, EAGLE, DFlash
- Automatic kernel generation and graph-level transformations using torch.compile
- Disaggregated prefill, decode, and encode
vLLM is flexible and easy to use with:
- Seamless integration with popular Hugging Face models
- High-throughput serving with various decoding algorithms, including parallel sampling, beam search, and more
- Tensor, pipeline, data, expert, and context parallelism for distributed inference
- Streaming outputs
- Generation of structured outputs using xgrammar or guidance
- Tool calling and reasoning parsers
- OpenAI-compatible API server, plus Anthropic Messages API and gRPC support
- Efficient multi-LoRA support for dense and MoE layers
- Support for NVIDIA GPUs, AMD GPUs, and x86/ARM/PowerPC CPUs. Additionally, diverse hardware plugins such as Google TPUs, Intel Gaudi, IBM Spyre, Huawei Ascend, Rebellions NPU, Apple Silicon, MetaX GPU, and more.
vLLM seamlessly supports 200+ model architectures on Hugging Face, including:
- Decoder-only LLMs (e.g., Llama, Qwen, Gemma)
- Mixture-of-Expert LLMs (e.g., Mixtral, DeepSeek-V3, Qwen-MoE, GPT-OSS)
- Hybrid attention and state-space models (e.g., Mamba, Qwen3.5)
- Multi-modal models (e.g., LLaVA, Qwen-VL, Pixtral)
- Embedding and retrieval models (e.g., E5-Mistral, GTE, ColBERT)
- Reward and classification models (e.g., Qwen-Math)
Find the full list of supported models here.
Getting Started
Install vLLM with uv (recommended) or pip:
uv pip install vllm
Or build from source for development.
Visit our documentation to learn more.
Contributing
We welcome and value any contributions and collaborations. Please check out Contributing to vLLM for how to get involved.
Citation
If you use vLLM for your research, please cite our paper:
@inproceedings{kwon2023efficient,
title={Efficient Memory Management for Large Language Model Serving with PagedAttention},
author={Woosuk Kwon and Zhuohan Li and Siyuan Zhuang and Ying Sheng and Lianmin Zheng and Cody Hao Yu and Joseph E. Gonzalez and Hao Zhang and Ion Stoica},
booktitle={Proceedings of the ACM SIGOPS 29th Symposium on Operating Systems Principles},
year={2023}
}
Contact Us
- For technical questions and feature requests, please use GitHub Issues
- For discussing with fellow users, please use the vLLM Forum
- For coordinating contributions and development, please use Slack
- For security disclosures, please use GitHub's Security Advisories feature
- For collaborations and partnerships, please contact us at collaboration@vllm.ai
Media Kit
- If you wish to use vLLM's logo, please refer to our media kit repo
