deepseek-ai/DeepSeek-V4-Pro
DeepSeek V4 flagship MoE (1.6T total / 49B active) with hybrid CSA+HCA attention, manifold-constrained hyper-connections, Muon-trained on 32T+ tokens, and three-tier reasoning.
Frontier 1.6T/49B reasoning MoE with native FP4+FP8 weights, MTP and DSpark speculative decoding, and 1M-token context
Guide
Overview
DeepSeek-V4-Pro is the flagship of the V4 preview family: a 1.6T-total / 49B-active Mixture-of-Experts model. It pairs a hybrid attention stack — Compressed Sparse Attention (CSA) + Heavily Compressed Attention (HCA) — with Manifold-Constrained Hyper-Connections (mHC) to reach 27% of V3.2's per-token inference FLOPs and 10% of V3.2's KV cache at 1M context. Pre-trained on 32T+ tokens with the Muon optimizer for faster convergence; post-training is a two-stage pipeline (domain-specific expert cultivation + unified consolidation via on-policy distillation).
Checkpoint is FP4+FP8 mixed: MoE expert weights are stored in FP4 while the remaining (attention / norm / router) params stay in FP8.
An NVFP4 variant (nvidia/DeepSeek-V4-Pro-NVFP4) is also available — NVIDIA
modelopt re-quantizes the MoE experts to standard NVFP4 while attention, shared
experts, router head, and MTP stay FP8. Pick it from the Variant row; it runs on
Blackwell GPUs with the FP4 indexer cache.
Checkpoints
Four checkpoints are on the Variant row. They differ in which weights you serve and which draft module ships with them — the speculative method itself is picked on the Spec Decoding row.
| Variant | Repo | Draft | Notes |
|---|---|---|---|
| FP8 (0813) (default) | deepseek-ai/DeepSeek-V4-Pro-0813 | DSpark | Official release, preview structure + DSpark |
| FP8 (Preview) | deepseek-ai/DeepSeek-V4-Pro | MTP | Preview FP4+FP8 mixed weights |
| NVFP4 | nvidia/DeepSeek-V4-Pro-NVFP4 | MTP | modelopt re-quant, Blackwell |
| DSpark | deepseek-ai/DeepSeek-V4-Pro-DSpark | DSpark | Preview weights + fused DSpark module |
0813 is the official DeepSeek-V4-Pro release and the default here, superseding the preview with substantially stronger agentic capability — 87.9 on Terminal Bench 2.1, 62.7 on DeepSWE and 42.7 on HLE (60.0 with tools), versus 72.1, 12.8 and 37.7 for the preview. It is built on the preview model structure with a DSpark speculative decoding module attached. The preview weights remain available as the FP8 (Preview) variant for reproducing earlier results.
DSpark is not new weights — it is the preview checkpoint with a speculative
decoding module attached (see DeepSpec).
Both fused checkpoints add a dspark_* block to config.json; the preview and NVFP4
checkpoints have no such block, which is why the DSpark method is offered only on the
two variants that carry the draft. Selecting either one auto-enables Spec Decoding
with method: dspark, emitting:
--speculative-config '{"method":"dspark","num_speculative_tokens":7,"draft_sample_method":"probabilistic"}'
The fused checkpoints are ~893 GB on disk versus ~865 GB for the preview — the draft module is the difference. Both require vLLM 0.25.0, above this recipe's 0.20.0 baseline; the Install block bumps automatically when either is selected.
Reasoning modes
The chat template exposes three reasoning-effort modes:
- Non-think — fast, intuitive responses.
- Think High — explicit chain-of-thought for complex problem-solving and planning.
- Think Max — maximum reasoning effort; requires
--max-model-len >= 393216(384K tokens) to avoid truncation.
Recommended sampling: temperature = 1.0, top_p = 1.0.
On the 0813 variant the effort levels are named low / high / max, and
DeepSeek recommends top_p = 0.95 for agentic scenarios (1.0 otherwise) with
temperature = 1.0. Allow up to 384K output tokens at the high and max
levels.
Note that the 0813 release ships no Jinja chat template — the repo provides an
encoding/ folder with encode_messages / parse_message_from_completion_text
helpers instead. Serving through vLLM with --tokenizer-mode deepseek_v4 (the
Tool Calling pill) applies the built-in DeepSeek-V4 encoding, so the OpenAI-
compatible endpoint works without the helper scripts.
OpenAI Client Example
For DeepSeek-V4, keep reasoning controls in chat_template_kwargs, as it exposes a
custom Think Max mode via "reasoning_effort": "max".
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
model = "deepseek-ai/DeepSeek-V4-Pro-0813"
messages = [{"role": "user", "content": "What is 17*19? Return only the final integer."}]
# Non-think
resp = client.chat.completions.create(
model=model,
messages=messages,
)
# Think High
resp = client.chat.completions.create(
model=model,
messages=messages,
extra_body={
"chat_template_kwargs": {
"thinking": True,
"reasoning_effort": "high",
},
},
)
# Think Max
resp = client.chat.completions.create(
model=model,
messages=messages,
extra_body={
"chat_template_kwargs": {
"thinking": True,
"reasoning_effort": "max",
},
},
)
Recommended deployments
- B300 (8× GPU): single-node DP + EP with
--data-parallel-size 8. - H200 (8× GPU): DP + EP with
--data-parallel-size 8. Context is capped at 800K tokens (--max-model-len 800000) to leave KV headroom with dense params replicated across ranks — applies to both single-node and multi-node H200. - MI355X (8× GPU): validated with ROCm + AITER (
VLLM_ROCM_USE_AITER=1),--gpu-memory-utilization 0.9,--max-num-seqs 128,--max-num-batched-tokens 8192, and--distributed-executor-backend mp. - GB200 NVL4 (4× GPU per tray): the ~960 GB mixed-precision checkpoint does not
fit on one tray; run multi-node DP + EP across 2 trays (8 GPUs total) with
--data-parallel-size 8. Pick the "Multi-Node" tab and set nodes to 2.
MI355X (8×288GB)
export VLLM_ROCM_USE_AITER=1
vllm serve deepseek-ai/DeepSeek-V4-Pro \
--host localhost \
--port 8001 \
--dtype auto \
--kv-cache-dtype fp8 \
--tensor-parallel-size 8 \
--max-num-seqs 512 \
--max-num-batched-tokens 8192 \
--distributed-executor-backend mp \
--trust-remote-code \
--gpu-memory-utilization 0.9 \
--tokenizer-mode deepseek_v4 \
--reasoning-parser deepseek_v4 \
--tool-call-parser deepseek_v4 \
--enable-auto-tool-choice \
--compilation-config '{"mode": 3, "cudagraph_mode": "FULL_DECODE_ONLY"}'
MI355X is validated on GSM8K dataset:
Launch command
MODEL=deepseek-ai/DeepSeek-V4-Pro
lm_eval --model local-completions \
--model_args model=$MODEL,base_url=http://0.0.0.0:8001/v1/completions,num_concurrent=128,max_retries=10,max_gen_toks=2048,timeout=60000 \
--batch_size auto \
--tasks gsm8k \
--num_fewshot 8 \
--output_path . 2>&1 | tee -a eval.log
Reported result
local-completions ({'model': 'deepseek-ai/DeepSeek-V4-Pro', 'base_url': 'http://0.0.0.0:8001/v1/completions', 'num_concurrent': 128, 'max_retries': 10, 'max_gen_toks': 2048, 'timeout': 60000}), gen_kwargs: ({}), limit: None, num_fewshot: 8, batch_size: auto
|Tasks|Version| Filter |n-shot| Metric | |Value | |Stderr|
|-----|------:|----------------|-----:|-----------|---|-----:|---|-----:|
|gsm8k| 3|flexible-extract| 8|exact_match|↑ |0.9538|± |0.0058|
| | |strict-match | 8|exact_match|↑ |0.9545|± |0.0057|
KV Cache Offloading
Agentic and multi-turn workloads reuse long prefixes whose KV state can exceed on-GPU capacity. The KV Offload row attaches a host-DRAM KV tier to any serving strategy — pick one of three connectors:
- Simple —
SimpleCPUOffloadConnector: spills KV blocks to a per-rank region of CPU DRAM on each node. The simplest way to extend effective KV capacity for a single instance. - Mooncake —
MooncakeStoreConnector: pools CPU DRAM into a distributed shared KV store — either embedded (each rank's vLLM worker runs a Mooncake client that donates a DRAM segment) or standalone (a per-nodemooncake_store_serviceowns the node's DRAM and contributes it to the pool, decoupling cache lifetime from the engine). A cluster-widemooncake_mastercoordinates the pool; across 2+ instances, GPU workers share it for cross-instance prefix reuse. Install from the extra-install block above; see the Mooncake docs. - LMCache —
LMCacheMPConnector: a node-local KV pool served by a companionlmcache serverprocess, launched beforevllm serve. Single-node strategies only. Install from the extra-install block above; see the LMCache docs.
Agentic benchmark reproduction (InferenceX MI355X sweep)
The command above is the default serving configuration. The SemiAnalysis InferenceX MI355X benchmark lane for this checkpoint is a separate high-concurrency benchmark configuration — not the recipe default. To reproduce that sweep, start from the default command above and apply these deltas:
Applied to both arms:
- Enable
VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4(previously commented out). - Enable
VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1. DSv4-Pro is a mixed checkpoint (MXFP4 routed experts, FP8 shared expert) and vLLM gates the fused shared-expert path on this flag, which defaults to off, so the checked-in recipe was not running the configuration the validated manual runs used. The flag is mutually exclusive with expert parallelism inside vLLM, which is consistent with both arms running EP 1. - Raise
--gpu-memory-utilizationfrom0.8to0.86. - Pin
--max-num-batched-tokens 8192instead of the nightly default of16384. On the TP8 initialization check this raised GPU KV-cache capacity from4,730,981to8,524,228tokens and reduced peak activation memory from11.44 GiBto8.9 GiB.
Applied to the DP-attention arm only:
- Cap
--max-num-seqsatCONCrather than2*CONC. The limit is per scheduler and DP-attention runs one scheduler per rank. The pure TP8 arm keeps the existing2*CONCheadroom for AgentX subagent fan-out. - Add
--prefill-schedule-interval 8and--long-prefill-token-threshold 16384.
With --max-num-batched-tokens 8192 now pinned for both arms,
--long-prefill-token-threshold 16384 sits above the token budget and therefore
never binds. It is inert rather than harmful, and the DP-attention point was
measured with it present.
--compilation-config '{"mode":3,"cudagraph_mode":"FULL_AND_PIECEWISE"}' is
unchanged; it was already in the checked-in recipe.
Export the AITER and INT4 quantized all-reduce environment variables before launch:
export VLLM_ROCM_USE_AITER=1
export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4
export VLLM_ROCM_USE_AITER_MOE=1
export VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1
export VLLM_ENGINE_READY_TIMEOUT_S=10800
export VLLM_PREFIX_CACHE_RETENTION_INTERVAL=32768
vllm serve "$MODEL_PATH" --served-model-name "$MODEL" \
--host 0.0.0.0 \
--port "$VLLM_BACKEND_PORT" \
--trust-remote-code \
--async-scheduling \
--distributed-executor-backend mp \
--kv-cache-dtype fp8 \
--max-num-batched-tokens 8192 \
--gpu-memory-utilization 0.86 \
--moe-backend aiter \
--compilation-config '{"mode":3,"cudagraph_mode":"FULL_AND_PIECEWISE"}' \
--speculative-config '{"method": "mtp", "num_speculative_tokens": 3, "rejection_sample_method": "synthetic", "synthetic_acceptance_length": 2.49}' \
--tokenizer-mode deepseek_v4 \
--tool-call-parser deepseek_v4 \
--reasoning-parser deepseek_v4 \
--enable-auto-tool-choice \
--enable-prefix-caching \
--no-disable-hybrid-kv-cache-manager \
--max-num-seqs "8"
Fixed-sequence benchmark reproduction (InferenceX MI355X 8K/1K)
This is a second, separate InferenceX lane — not a variation of the Agentic sweep above. It is a fixed-sequence measurement at input length 8192 and output length 1024 on one 8× MI355X node, run as two arms: STP (no speculative decoding) and real MTP with two draft tokens. Neither arm is the general recipe default, and neither is a recommendation for other AMD workloads.
The checkpoint is deepseek-ai/DeepSeek-V4-Pro — the FP8 (Preview) pill in
the Variant row, whose mixed FP4+FP8 weights InferenceX labels fp4. It is not
the 0813 default variant and not the DSpark checkpoint.
Source configuration
| Item | Value |
|---|---|
| InferenceX PR | #2792 |
| Config keys | dsv4-fp4-mi355x-vllm (STP), dsv4-fp4-mi355x-vllm-mtp (MTP) |
| Hardware | one node, 8× MI355X |
| Image | vllm/vllm-openai-rocm:nightly-7c5dc571cbd1064ecc8a9b1045637ff647aa22cb |
| Image digest | sha256:f0bdaf5217a09949842b45c1ea1f12260d3205ec81f143b320dfc2eb3ec95e55 |
| Parallelism | TP 8, DP 1, EP 1 — no --enable-expert-parallel |
| Workload | ISL 8192, OSL 1024; concurrency 4, 8, 16, 32, 64, 128, 256, 512 |
| Requests per point | 10 × concurrency |
The image is pinned to an immutable nightly tag rather than a floating
:nightly, because the measurements depend on the ROCm DeepSeek-V4 kernel state
in that specific build. The Install block's AMD default stays on :nightly
deliberately — pin the tag above only when reproducing these numbers.
STP launch (no speculative decoding)
export VLLM_ROCM_USE_AITER=1
export VLLM_ROCM_USE_AITER_MOE=1
# Kept explicit for parity with the upstream ROCm recipe knobs. See the
# shared-expert note below — vLLM may self-disable this fusion.
export VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1
export VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4
vllm serve deepseek-ai/DeepSeek-V4-Pro \
--port "${PORT:-8000}" \
--tensor-parallel-size 8 \
--data-parallel-size 1 \
--async-scheduling \
--no-enable-prefix-caching \
--distributed-executor-backend mp \
--gpu-memory-utilization 0.8 \
--kv-cache-dtype fp8 \
--trust-remote-code \
--moe-backend aiter \
--tokenizer-mode deepseek_v4 \
--reasoning-parser deepseek_v4 \
--compilation-config '{"mode":3,"cudagraph_mode":"FULL_AND_PIECEWISE"}'
MTP arm (real speculation, 2 draft tokens)
The MTP arm is the same launch plus one flag. Everything else — environment, parallelism, memory, cache, executor, MoE backend, parsers, compilation — is identical:
--speculative-config '{"method":"mtp","num_speculative_tokens":2}'
This is real MTP: draft tokens are verified against the target model. ROCm support for the DeepSeek-V4 MTP head landed in vllm-project/vllm#43385. The same two-token config is available from the command builder — enable Spec decoding and pick the MTP mode with the FP8 (Preview) variant selected.
Left at engine defaults
This lane deliberately passes no --max-model-len, --max-num-seqs,
--max-num-batched-tokens, or --block-size, and no tool-calling flags. That
differs from this recipe's general AMD configuration, which does set several of
them — one reason this reproduction is documented separately rather than folded
into the default command.
Benchmarking the MTP arm needs chat formatting
MTP-style speculation is trained against chat-formatted input. Benchmarking it
with raw completion prompts silently depresses the acceptance rate, so measure
it against the chat endpoint, which applies the DeepSeek-V4 chat template that
--tokenizer-mode deepseek_v4 installs:
CONC=32
vllm bench serve \
--model deepseek-ai/DeepSeek-V4-Pro \
--host localhost \
--port "${PORT:-8000}" \
--backend openai-chat \
--endpoint /v1/chat/completions \
--dataset-name random \
--random-input-len 8192 \
--random-output-len 1024 \
--num-prompts "$((CONC * 10))" \
--max-concurrency "$CONC" \
--ignore-eos \
--trust-remote-code
InferenceX drives its own benchmark client with a private DeepSeek-V4 encoder rather than the tokenizer's built-in template, so the numbers on its dashboard are not byte-identical to what the command above produces. Use the chat endpoint for any MTP acceptance measurement regardless.
Shared-expert fusion may self-disable
VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1 is exported for parity with the
ROCm recipe, but it is a request, not a guarantee. vLLM gates the fused
shared-expert path on its own eligibility check, and for this mixed FP4+FP8
checkpoint that check does not currently pass, so the fusion self-disables at
startup. Treat the flag as harmless recipe parity and check the server log
before assuming the fused path executed.
How this differs from the Agentic sweep above
| Setting | Fixed-sequence 8K/1K | Agentic sweep |
|---|---|---|
| Workload | ISL 8192 / OSL 1024, conc 4–512 | agentic-coding traces |
--gpu-memory-utilization | 0.8 | 0.86 |
| Prefix caching | --no-enable-prefix-caching | --enable-prefix-caching |
| Speculation | none (STP) or real MTP, 2 tokens | synthetic MTP, 3 tokens |
--max-num-seqs | not passed | 8 |
--max-num-batched-tokens | not passed | 8192 |
The Agentic lane's synthetic acceptance length is a benchmark-comparability device. This lane never uses it: the STP arm has no draft at all, and the MTP arm verifies against the real target.
Provenance
Validation for this configuration comes from InferenceX, not from this repository — no MI355X benchmark was rerun here.
- InferenceX PR: #2792
- STP script:
dsv4_fp4_mi355x_vllm.sh - MTP script:
dsv4_fp4_mi355x_vllm_mtp.sh - Config matrix:
configs/amd-master.yaml - Successful sweep: run 33538769698,
which ran at commit
7a209b121932696b7efd437ac50d19c53efc7a94. All eight concurrency points passed on both arms, pluslm-evalGSM8K eval-only jobs at concurrency 128 and 512. Commits after that point on the PR branch do not touch either fixed-sequence script or these two config entries. - ROCm DeepSeek-V4 MTP support: vllm-project/vllm#43385