Recipe YAML schemaÂļ
The authoritative reference for a recipe YAML, models/<hf_org>/<hf_repo>.yaml,
whichever repository the file lives in (this repo's models/ today;
recipes/ in vllm-project/vllm, vllm-omni, âĻ as recipes move). It is versioned with the renderer that reads it:
change it in the same pull request as any code that adds or changes a field.
CONTRIBUTING.md, CLAUDE.md and the
add-recipe skill link here rather than
repeating it.
Two tools enforce and assist it:
- Machine-readable schema â
/recipe.schema.json, generated fromtaxonomy.yamlandstrategies/bysrc/lib/recipe-schema.js. Every build checks every recipe against it: unknown or misspelled keys, wrong types, and ids outside the vocabulary are errors (the renderer would otherwise ignore them silently). Point your editor at it for completion and inline errors â with the YAML language server (VS Code's Red Hat YAML extension), start the file with# yaml-language-server: $schema=https://recipes.vllm.ai/recipe.schema.json. -
Starter template â
templates/recipe.yaml: the required fields plus the common ones (text or multimodal, dense or MoE), withTODOs to fill in. -
Annotated example â every field in order, with inline notes.
- Field reference â semantics, precedence, and rendering consequences.
- VRAM formula
Annotated exampleÂļ
Top-level keys, in this order:
meta:
title: "DeepSeek-V3.2" # display name
slug: "deepseek-v3.2" # kebab-case; keep consistent with title
provider: "DeepSeek" # human-readable label
description: "âĻ" # one-sentence summary
date_added: 2026-04-20 # initial catalog addition; never change
date_updated: 2026-04-20 # latest material recipe change
tasks:
- text # one or more of: text, multimodal, omni, embedding
performance_headline: "âĻ" # optional pithy line for cards
related_recipes: ["deepseek-ai/DeepSeek-V3.1"] # optional list of "<org>/<repo>" ids
# Optional â `verified` only for GPUs you've ACTUALLY tested end-to-end;
# `supported` lists a restricted profile without that claim; `unsupported`
# marks a confirmed blocker. Missing GPUs are assumed to work silently.
hardware:
h200: verified
mi355x: verified
model:
model_id: "deepseek-ai/DeepSeek-V3.2" # MUST match the filename path
min_vllm_version: "0.18.0" # earliest vLLM release that supports this model
docker_image: "vllm/vllm-openai:v0.18.0" # optional â override the Docker image:tag shown in Install â Docker. String form pins NVIDIA only (AMD/TPU still use their brand defaults). For per-brand pins, use the object form:
# docker_image:
# nvidia: "vllm/vllm-openai:gemma4"
# amd: "vllm/vllm-openai-rocm:gemma4"
# tpu: "vllm/vllm-tpu:gemma4"
# Missing keys fall back to `:latest` for that brand (vllm/vllm-openai, vllm/vllm-openai-rocm, vllm/vllm-tpu).
nightly_required: true # optional â set when `min_vllm_version` hasn't shipped yet. Swaps the default pip command to `uv pip install -U vllm --pre --extra-index-url https://wheels.vllm.ai/nightly/cu130` and adds a "nightly" pill to the Install header. Users on CUDA 12.9 are pointed to the /cu129 index via the note.
# Optional â control the Install block's pip/Docker tabs. Each key accepts
# either `false` (hide the tab entirely) or an object with { command?, note? }.
# Use `note` for a one-liner above the code block; use `command` to fully
# replace the generated install script (e.g. nightly wheel, pinned version).
#
# Tab ORDER follows the YAML key order. Put `docker` before `pip` to make
# Docker the first tab and the default when the block opens (useful when the
# recipe is easier via Docker â e.g. a pinned image vs. a multi-step pip).
install:
docker: # listed first â Docker is the default tab
note: "Recommended: the pinned image ships all dependencies"
pip:
command: "uv pip install vllm --pre --index-url https://wheels.vllm.ai/nightly"
note: "nightly wheel required â stable release does not yet support this model"
architecture: moe # dense | moe
parameter_count: "671B" # total params with B/T suffix
active_parameters: "37B" # same as parameter_count for dense models
context_length: 163840 # integer (tokens)
supports_dcp: true # optional â MLA-attention models (DeepSeek, Kimi-K2 family)
base_args: # flags always needed
- "--trust-remote-code"
base_env: # env vars always needed
VLLM_USE_DEEP_GEMM: "0" # MoE kernel selection itself is done via --moe-backend args
default_frontend: rust # optional â python (default) | rust; preselects the Frontend pill
rust_frontend: unsupported # optional â only when Rust is confirmed to fail (e.g. a parser it hasn't registered); explain why in the guide
# Optional â extra install steps beyond `uv pip install -U vllm`.
# Rendered as a code block above the vllm serve command.
dependencies:
- note: "DeepGEMM required for FP8 MoE kernels"
command: "uv pip install git+https://github.com/deepseek-ai/[email protected] --no-build-isolation"
- note: "Set VLLM_USE_DEEP_GEMM=0 to skip DeepGEMM (recommended on H20)"
command: "export VLLM_USE_DEEP_GEMM=0"
optional: true
features:
tool_calling: # names are conventions, not required keys
description: "Enable âĻ"
args: ["--enable-auto-tool-choice", "--tool-call-parser", "<name>"]
reasoning:
description: "âĻ"
args: ["--reasoning-parser", "<name>"]
spec_decoding: # USE spec_decoding, NOT mtp â unified key for MTP / Eagle3 / ERNIE-MTP
description: "âĻ"
args: ["--speculative-config", '{"method":"mtp","num_speculative_tokens":1}']
long_context: # RoPE/YaRN context extension â always opt-in (see below)
description: "âĻ"
args: ["--hf-overrides", '{"rope_parameters":{"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}}',
"--max-model-len", "131072"]
env: # optional â env set only while the feature is on
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1" # needed when the window exceeds max_position_embeddings
opt_in_features: # features that default OFF (users tick them on)
- spec_decoding # spec decoding is opt-in unless docs insist
- long_context # always opt-in: static YaRN costs short-prompt quality
variants:
default: # ALWAYS include a `default` variant
precision: fp8 # bf16|fp8|nvfp4|fp4|int4|int8|awq|gptq|mxfp4
vram_minimum_gb: 805 # params à bytes à 1.2 (see formula below)
description: "âĻ"
nvfp4: # optional additional variants
model_id: "nvidia/*-NVFP4" # only if the quantized checkpoint is a different HF repo
precision: nvfp4
vram_minimum_gb: 403
extra_args: ["--kv-cache-dtype", "fp8", "--moe-backend", "flashinfer_cutlass"]
compatible_strategies: # subset of the 8 strategy ids in strategies/*.yaml
- single_node_tp # always include as baseline
- single_node_tep # for MoE
- single_node_dep # for MoE
- multi_node_tp
- multi_node_tp_pp # TP within node + PP across â vLLM's recommended multi-node default
- multi_node_dep # for MoE
- multi_node_tep # for MoE
- pd_cluster # only if the recipe documents PD
# Optional per-generation tweaks.
# Key by `hopper` / `blackwell` / `amd` for per-family overrides, OR use
# `nvidia` as a brand-wide fallback that applies to every NVIDIA GPU when
# no generation-specific block is present.
hardware_overrides:
blackwell:
extra_args: []
extra_env: {}
amd:
extra_args: []
extra_env:
VLLM_ROCM_USE_AITER: "1"
# A variant's `hardware_overrides.<exact_gpu_id>` block may also declare that an
# install path does not exist on that GPU. Use it only when the pinned image
# carries kernels that are not in vLLM main, so the flags this hardware
# generates would abort on an official wheel â not merely because Docker is the
# easier route. The pip tab disappears on that GPU alone; every other hardware
# keeps it.
#
# variants:
# default:
# hardware_overrides:
# dgx_spark_gb10:
# docker_image: "eugr/spark-vllm-b12x:latest"
# install:
# pip: false
# Optional per-strategy tweaks. Rare. PD recipes use this to shape each pool.
#
# For `pd_cluster`, each role (prefill / decode) accepts:
# nodes â how many dedicated nodes the pool uses (default 1)
# parallelism â "tp" (tensor-parallel pool) | "dep" (data-parallel + expert-parallel)
# default "tp"
# tp â TP width per DP rank when parallelism=dep (default 1);
# unused for parallelism=tp (the whole pool is one TP group)
# vllm_args â extra flags appended to this role's `vllm serve`
# env â extra env vars for this role
# parallel_flag â (rare) override the auto-selected flag for parallelism=tp
#
# The Nodes row in the UI exposes `nodes` as per-pool inputs; the values here
# set the defaults. Kimi-K2.5 on GB200 illustrates the DEP-PD pattern:
strategy_overrides:
pd_cluster:
prefill:
nodes: 1
parallelism: dep
tp: 1 # DP = nodes à gpus_per_node / tp = 4
env: {}
decode:
nodes: 4
parallelism: dep
tp: 1 # DP = 16 on 4x GB200
vllm_args: ["--compilation-config", '{"cudagraph_mode":"FULL_DECODE_ONLY"}']
env: {}
# Default TP-per-role PD (simpler pattern, one engine per pool):
# pd_cluster:
# prefill: { nodes: 1, parallelism: tp } # TP = gpus_per_node
# decode: { nodes: 1, parallelism: tp }
#
# Cap TP below the node's gpu_count for small models that fit on fewer GPUs
# (Gemma 4 runs on 1 GPU even on an 8-GPU node):
# single_node_tp:
# tp: 1 # clamped to [1, gpu_count];
# # UI shows "using N of M GPUs"
# # under the Hardware pill when
# # effective TP < gpu_count.
# # Only read for single_node_tp â
# # TEP/DEP and multi-node ignore.
# Markdown guide. Rendered on the recipe page under the command builder.
# Covers Overview, Prerequisites, Launch, Benchmarking, Troubleshooting, References.
guide: |
## Overview
...
## Prerequisites
- **Hardware**: 8x H200
- **vLLM**: >= 0.18.0
## Launching the Server
```bash
vllm serve deepseek-ai/DeepSeek-V3.2 --tensor-parallel-size 8 ...
```
## References
- [Model card](https://huggingface.co/deepseek-ai/DeepSeek-V3.2)
Multiple speculative-decoding methodsÂļ
Keep the flat features.spec_decoding.args form when a recipe has one method.
When the same served checkpoint can use multiple mutually exclusive methods,
replace args with a modes map:
features:
spec_decoding:
description: "Speculative decoding â pick a drafting method."
default_mode: mtp
modes:
mtp:
label: "MTP"
description: "Native multi-token prediction head."
args: ["--speculative-config", '{"method":"mtp","num_speculative_tokens":2}']
eagle3:
label: "EAGLE3"
description: "Community-trained external draft model."
args: ["--speculative-config", '{"method":"eagle3","model":"community/model-eagle3","num_speculative_tokens":5}']
opt_in_features: [spec_decoding]
default_mode is the recommended selection when the feature is enabled. A
mode can use variants: [default, fp8] to limit it to particular served
checkpoints and hardware: { hopper: unsupported } to disable it on a GPU
family. Per-mode hardware_overrides.<generation>.args can replace its config
for one hardware generation.
The served checkpoint and speculative method are separate axes: only a
variant's model_id changes vllm serve <checkpoint>; a mode contributes only
the speculative arguments. If a draft is baked into a separately served
checkpoint, model it as a variant and couple its recommended method with
default_modes:
variants:
fused_eagle3:
model_id: "community/model-with-eagle3"
label: "EAGLE3"
precision: fp8
vram_minimum_gb: 128
default_modes:
spec_decoding: eagle3
Declaring default_modes also enables that feature by default for the variant,
even when it appears in opt_in_features. The build validator rejects mixed
args + modes, unknown mode/variant references, and variants with no usable
mode.
Long-context extension (long_context)Âļ
Add this feature only when the model card documents a specific extension
config â never invent a YaRN factor. Keep it in opt_in_features: every card
that ships one says the same thing, that static YaRN applies a constant scaling
factor and therefore costs quality on short prompts, and the wider window also
inflates the KV budget.
Two things to get right when translating a model card:
- Use
--hf-overrides, not--rope-scaling. Most cards still print--rope-scaling '{...}', but that flag was removed from vLLM'sModelConfigby 0.26 â a recipe emitting it breaks on any current wheel, even when the recipe'smin_vllm_versionfloor is old enough that the flag once existed. - Use the
rope_parameterskey. Transformers v5 renamed the config fieldrope_scalingârope_parameters, and vLLM 0.29 readshf_config.rope_parameters. On a VL/omni checkpoint the block nests undertext_configâ a top-level override silently misses the decoder's config.
So a card's --rope-scaling '{"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}'
becomes:
long_context:
description: "YaRN RoPE scaling to the card's validated 131,072-token context. âĻ"
args:
- "--hf-overrides"
- '{"rope_parameters":{"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}}'
- "--max-model-len"
- "131072"
Add env: { VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1" } whenever the target window
exceeds the checkpoint's max_position_embeddings (cards show it in the launch
line when it's needed). Features emit last and arg dedupe is last-wins, so both
flags cleanly shadow a --max-model-len already present in base_args â don't
edit base_args to make room.
Some cards describe an extension path that is not a flag toggle: a local
config.json swap, a removed engine (VLLM_USE_V1=0), or instructions given
only for another serving framework. Leave those out of the feature and describe
them in the guide instead.
Unreleased, source-only support: put the complete clone/checkout/build
sequence in model.install.pip.command and set model.install.docker: false.
Field referenceÂļ
Top-level keys, in this order:
metaâ title, slug, provider, description, date_added, date_updated, difficulty (deprecated â nothing reads it; omit it in new recipes), tasks[], performance_headline, related_recipes[], optionaldefault_hardware, optionaldefault_variant, optionalhardware: { gpu_id: verified | unsupported }.default_variantis a map in the variant-tpkeyspace (exact GPU id > generation > brand >default), e.g.{ amd: mxfp4 }: when the active variant can't run on the selected hardware,pickFittingVariantswitches to this variant if it runs there, instead of the largest-footprint fit. It steers the command builder's hardware switch; the JSON API renders every variant separately and is unaffected.date_addedis the immutable day the recipe first entered the catalog and drives the homepage's "Latest recipes" ranking;date_updatedrecords the latest material recipe change. Hardware states:verified= tested end-to-end (green â badge);unsupported= not yet runnable on this hardware today â compat gap / missing kernel / upstream blocker that could lift later (pill rendered but disabled + struck through, tooltip says "Not yet supported");supported= declared without a verified claim â only needed for arestrictedprofile (DGX Spark/Station, RTX Pro, TPU, Xeon), which appears in the picker only when listed here; absent = silent default, assumed to work. Any other value is a schema error. Don't useunsupportedfor "untested" â only when you've confirmed it currently fails.default_hardwareis a single GPU profile id (b300,dgx_spark_gb10, âĻ) â the hardware the page and the JSON API open on. Precedence: URL?hardware=> the user's stored global preference (set only by an explicit pill click) >default_hardware> thepickDefaultHardwareheuristic (B200 for Blackwell-constrained variants, else H200). A returning visitor's own GPUs therefore still win â this key only replaces the model-blind heuristic. It's validated and fail-open: an id that's unknown to the taxonomy, precision-incompatible with the resolved variant, markedunsupported, or arestrictedprofile the recipe doesn't declare inmeta.hardwarefalls through silently to the heuristic. Authoring rule: set it to the hardware the guide's numbers, theperformance_headlineand theverifiedbadge were taken on â not to the biggest GPU. Landing on averifiedprofile is what makes the command block's green "Verified on" badge the built-in explanation for the choice, so no extra banner is needed; pointing it at an unverified GPU loses that badge and is worse than leaving the key absent. Most important for the JSON API, which has no URL or localStorage â default_hardwareis the only way an author steersrecommended_command(everything else stays addressable underby_hardware).modelâmodel_id,min_vllm_version,architecture(denseormoe),parameter_count,active_parameters,context_length,base_args[],base_env{}, optionaldefault_frontend: python | rust(defaults to Python), optionalrust_frontend: unsupported. Frontends are defined once intaxonomy.yaml â frontends({ label, env? }, pill order = key order); synthesis merges the selected frontend'senvinto every rendering â Rust's isVLLM_USE_RUST_FRONTEND: "1", Python sets nothing. Keep that variable in the taxonomy entry, never inbase_env; usedefault_frontendto express recipe defaults. Setdefault_frontend: rustfor recipes that recommend it. The selector is saved per recipe and in?frontend=python|rust; the JSON API uses the same recipe default.rust_frontend: unsupported(the general form is<frontend_id>_frontend; Python is the baseline and can't be opted out) disables the Rust pill with a tooltip, andresolveFrontendfalls back to Python for every path â URL, saved state, JSON API â so no rendering ever carries the Rust env for that recipe. Same rule asmeta.hardware: unsupported: only when Rust is confirmed to fail today (typically a--tool-call-parser/--reasoning-parserthe Rust frontend hasn't registered, which aborts startup), not for "untested"; put the reason in the guide, and remove the key once a vLLM release fixes it. The build rejects unknown frontend ids, any value other thanunsupported, anddefault_frontendnaming an unsupported frontend.dependencies(optional) â list of{ command, note?, optional?, brand?, install_modes? }. Rendered as the "extra install" block abovevllm serve. Use this for DeepGEMM pins,vllm[audio], pinned transformers commits, vllm-omni source installs, etc.optional: truedims the entry and excludes it from the block's "Copy all" button (the user must copy it explicitly).brand: NVIDIA | AMD | Intel(or array) hides the entry when the current hardware pill is a different brand â use for CUDA-only kernels (xformers, DeepGEMM) or ROCm-only wheels. Omitbrandfor platform-agnostic deps (diffusers from source, transformers commits, etc.).install_modesgates the entry by Install tab, and absent means[pip]â the block is pip-scoped by default because the Docker image already bundles the pip installs, so repeating them besidedocker runis noise.install_modes: [pip, docker]opts an entry into both tabs; reserve it for host-side prerequisites Docker cannot satisfy, i.e. a gated checkpointhf downloadmust place on disk beforebuildDockerRuncan bind-mount it (MiniMax-H3). A pip install never wants this. Keep the runnable fetch step here rather than as a#comment on the command â the block's "Copy all" yields executable lines, a comment does not.featuresâ map of{feature_key: { description, args[], env?, label? }}. Naming convention:tool_calling,reasoning,spec_decoding(the unified key for MTP / Eagle3 / ERNIE-MTP â don't usemtp, it was renamed across all recipes),long_context(RoPE/YaRN context extension â see below). Each feature is a boolean toggle by default. Optionallabeloverrides the pill text (default: title-cased key).env{}â env vars set only while the feature is on. Emitted frombuildEnvas the mirror of the featureargsblock inbuildArgs(step 7): applied after every override layer so an enabled feature wins, and gated identically (strategy allowlist, Mooncake-companion skip, active mode) so a feature's env and args can never disagree about whether it's on. Amodesentry may carryenvtoo, andhardware_overrides.<key>.envREPLACES it the same wayargsdoes. Use it for features whose documented launch line is env + flags rather than flags alone âlong_contextneedsVLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"wherever the target window exceeds the checkpoint'smax_position_embeddings. Propagates to every rendering: single-node, head + each worker on multi-node (one env map per deployment), both PD roles, and the Docker-eflags.long_contextâ the context-extension toggle, ALWAYS inopt_in_features: static YaRN holds its scaling factor constant regardless of input length, so leaving it on costs short-prompt quality, and the longer window inflates the KV budget. Args are--hf-overrides '<rope json>'+--max-model-len <extended>; because features emit last anddedupeArgsis last-wins, both cleanly shadow a--max-model-lenalready inbase_args. Use--hf-overrides, never--rope-scalingâ the latter is what most model cards still print, but it was removed from vLLM'sModelConfigby 0.26, and transformers v5 renamed the config fieldrope_scalingârope_parameters(vLLM 0.29 readshf_config.rope_parameters). So a card's--rope-scaling '{...}'translates to--hf-overrides '{"rope_parameters":{...}}', and on a VL/omni checkpoint the block nests undertext_config(a top-level override silently misses the decoder's config). Only add this feature where the model card documents a specific extension config â don't invent a factor.- Single-select sub-modes â when one feature has several mutually exclusive methods (e.g. a model offering more than one speculative method: MTP / DSpark / DFlash), replace the feature's flat
args[]with amodesmap and it renders as a "pick one" segmented row under the feature toggle instead of a boolean. A mode contributes onlyargs(the--speculative-config) â the method, never the served checkpoint. Shape:{ description, default_mode?, modes: { <mode_key>: { label?, description?, args[], variants?, hardware_overrides?, hardware? } } }. Only the selected mode'sargsare emitted, so exactly one--speculative-configis ever produced â no dedupe conflict between sibling methods, and nodisables_featuresgymnastics.default_modepicks the initial mode (else the first key). A mode may restrict itself to specific checkpoints withvariants: [<variant_key>, âĻ]â e.g. the dspark method only exists on the fused DSpark checkpoint, so FP8/NVFP4 offer MTP only (a mode with novariantsis available everywhere). The row renders only when âĨ2 modes are available for the current variant â a single available method is left to the boolean feature toggle (no redundant one-pill row, no disabled cross-axis buttons). The effective mode is resolved byresolveModeKey(variant + hardware availability, then user pick âvariant.default_modesâfeature.default_modeâ first available). Keep the booleanargs[]form for recipes that ship a single method â the two forms coexist and single-method recipes need no change. Selected mode syncs to the URL as?fmode=spec_decoding:dflash(default omitted). Synthesis + UI helpers:defaultModeFor/isModeSupportedincommand-synthesis.js.- Method vs. checkpoint â the two axes stay separate. The served checkpoint (
vllm serve <X>) is always owned by the Variant row (variant.model_id); a mode only picks the--speculative-configmethod. So: a method that adds an externally-trained draft (a separate speculator repo named inside the configmodel, e.g. GLM'sRedHatAI/GLM-5.2-speculator.dspark-preview) is a pure mode â<X>is unchanged. A method that ships as a fused checkpoint you serve instead (the draft is baked in,--speculative-configcarries nomodel, e.g. officialdeepseek-ai/DeepSeek-V4-Pro-DSpark) is a variant (itsmodel_id) plus a mode for the config. Couple them withvariant.default_modes: { <feature>: <mode> }(seevariantsbelow): selecting the DSpark variant flipsspec_decodingto the dspark method by default, while the checkpoint still runs MTP if the user switches the mode back. Don't put--speculative-configin a variant'sextra_args(last-wins dedupe would let the boolean/mode feature shadow it) â keep it in the mode. - Per-mode hardware gating â a mode may carry
hardware_overrides.<gen>.args(per-generation arg swap, same semantics as feature-level) and a tri-statehardware: { <gen_or_gpu_id>: unsupported }to gate a mode to specific GPUs (e.g. a DFlash draft that only ships for Blackwell âhardware: { hopper: unsupported }); the pill is struck-through on incompatible hardware and the selection auto-falls-back to the first supported mode.
- Method vs. checkpoint â the two axes stay separate. The served checkpoint (
- Per-strategy gating â a feature may declare
strategies: [<strategy_id>, âĻ](allowlist; absent = every strategy). Gate a feature when its args collide with a strategy's own flags or its setup doesn't generalize (e.g. a--kv-transfer-configthat would clobber pd_cluster's NixlConnector â features emit last, so last-wins dedupe would win). On excluded strategies the pill renders disabled ("Not available with this strategy"); the toggle state is preserved and synthesis independently skips the feature's args and companion. Helper:isFeatureAllowedForStrategyincommand-synthesis.js. NB: KV offloading itself is NOT a per-recipe feature in this repo â it lives on the universal KV Offload row (taxonomykv_offload+kv_store/), which reuses the same gating idea viaisKvOffloadAllowedForStrategy. - Companion process â a feature may declare
companion: { label, description?, command }for a helper that must run alongsidevllm serveon the same node. While the feature is on, the single-node command block renders PD-style tabs (vLLM Serve ¡ <label>); the companion tab shows the raw command (no docker wrap, no env prelude) with the description as a#comment line. Carried in the JSON API ascompanions[]on single-node renderings. The taxonomy'skv_offload.<key>.companion(LMCache'slmcache server) flows through the same machinery. opt_in_features[]â subset of feature keys that default OFF; others default ON. Typicallyspec_decodingis opt-in. (For a modes-feature, opt-in still governs the on/off toggle; the mode row only appears once the feature is on.)variantsâ must include adefaultvariant. Each hasprecision,vram_minimum_gb, optionaldescription, optionalmodel_idoverride (for quantized checkpoints shipped under a different HF repo, e.g.nvidia/*-NVFP4), optionalextra_args/extra_env, optionallabel(overrides the pill text, which otherwise showsprecision.toUpperCase()â use it to disambiguate two variants of the same precision, e.g. a fused-spec checkpoint âlabel: "DSpark"), optionaldefault_modes: { <feature>: <mode> }(steers a modes-feature's default mode when this variant is selected and auto-enables that feature even if it's inopt_in_featuresâ e.g. the DSpark checkpoint variant turnsspec_decodingon and defaults to the dspark method; see spec_decoding modes above), optionalmin_vllm_version/nightly_required(bump the recipe baseline for a variant that needs a newer vLLM â the Install block shows the higher version and, ifnightly_required, switches to the nightly wheel index + tag; e.g. the DSpark checkpoint requires 0.25.0, currently nightly), optionaltp(per-variant single-node TP override; either a bare number or a hardware-aware map keyed by exact GPU id, generation, brand, ordefault, e.g.{ b300: 1, h200: 2 }. Use it when a variant has documented per-GPU layouts or stricter sharding constraints â typically FP8-block-quantized siblings whosemoe_intermediate_size / TPmust stay divisible byblock_n=128. Do not put--tensor-parallel-sizeinsideextra_args; it gets silently overridden by the strategy emitter), optionalhardware_overrideswith two disjoint keyspaces: a generation key (hopper/blackwell/amd/nvidia) layers ADDITIVELY on top of the recipe-levelhardware_overrides.<gen>baseline â applies to every variant includingdefault(unlike the top-level variantextra_args, which is a non-default checkpoint delta; the generation HO is hardware-conditional config, sodefaultuses it too). Use it for a per-variant hw delta that only some precisions want: e.g. the FP8 checkpoints of DeepSeek-V4 add--moe-backend deep_gemm_mega_moe(an FP8-only MoE kernel) on Blackwell while the NVFP4 variant adds nothing â the recipe-levelblackwellblock holds only the shared--attention_config.use_fp4_indexer_cache=True. Precedence: a per-strategystrategy_overrides.<s>.hardware_overrides.<gen>still REPLACES both the recipe baseline and the variant delta (e.g.single_node_tpdropping the mega-kernel), so strategy HO > (recipe HO + variant HO). The other keyspace, an exact-GPU-id key (b200,mi355x, âĻ), is additive too (non-default variants only) and can also carryvram_minimum_gb(GPU-resident fit budget after CPU weight offload â replaces the variant's fullvram_minimum_gbforfitsSingleNodeon that GPU only; never bump taxonomyvram_gbwith host RAM),docker_image(per-variant-per-GPU image pin),docker_serve_command(e.g."vllm serve"â restated in thedocker runCMD before the model id for a pinned image whose entrypoint is notvllm serve, such as NVIDIA-base community builds that runnvidia_entrypoint.sh; without it the model id is executed as a path) andinstall: { pip: false }â the per-GPU form ofmodel.install.pip: false, declaring that no wheel can run this recipe on that GPU so the Install block hides the pip tab there (and the command block rendersdocker run) while leaving pip intact on every other hardware. Use it when the pinned image carries kernels that aren't in vLLM main, so the generated args would abort on an official wheel â DeepSeek-V4-Flash's B12X flags on DGX Spark. Not for "docker is easier here": a pip path that merely isn't the recommended one stays offered.precision_hardware(optional, variant-level) â overrides the default hardware constraint implied byprecision, using{ brand?, generation? }. Use only for exceptional checkpoints whose runtime fallback expands compatibility beyond the stored format, such as NVFP4 weights that vLLM dequantizes to BF16 on Hopper.supported_hardware(optional, variant-level) â an eligibility allowlist of exact profile ids orarch:<compute_arch>selectors, wherecompute_archis the GPU ISA recorded once intaxonomy.yaml(e.g.sm90,sm100,sm103,sm120,gfx942,gfx950). Eligibility is not a verified serving claim; onlymeta.hardware.<id>: verifiedmakes that claim. Use an architecture selector only when the checkpoint and generated runtime path work across that ISA; combine it with exact ids for profiles that need special kernels, images, or topology. This lets a new same-ISA profile inherit eligible variants after its taxonomy entry is classified, without treating every Blackwell or AMD GPU as interchangeable. Omit the list when the precision constraint alone suffices. Keep exact ids for hardware-specific checkpoints or runtime paths, and usemeta.hardware.<id>: unsupportedonly for a confirmed recipe-wide blocker. Restricted profiles still require an explicitmeta.hardware.<id>declaration before they appear in the picker, including when selected through a URL.compatible_strategies[]â subset of the serving strategy ids. Dense models typically only getsingle_node_tp+multi_node_tp; MoE models can have every serving strategy. Membership doubles as the default support state per GPU: listed = supported on every hardware, unlisted = supported nowhere âstrategy_hardwareoverrides either default per hardware, and a strategy grantedsupportedthere joins the offered set without being listed here (appended after the listed ones; helpereffectiveCompatibleStrategiesincommand-synthesis.js). Do NOT listkv_store_*_mooncakeids here â KV-offload options (Simple + both Mooncake modes) are implicit on every non-omni recipe and feed the "KV Offload" row, not the Strategy row.strategy_min_gpus(optional) â minimum GPUs a strategy needs for this model. Either a bare number (one bar for every strategy) or a map keyed by strategy id ({ multi_node_dep: 16, multi_node_tp: 8 }) so one parallelism can demand more than another â e.g. Kimi-K3 runs TP/TEP from 8 GPUs but needs 16 for DEP. The map takes a second, disjoint keyspace: an exact GPU id (h100: 32, or nested per-strategyh100: { multi_node_dep: 32 }) layering a hardware-conditional floor on top of the strategy bars, highest wins. Use it when one GPU needs a bigger cluster than the recipe baseline â K3's ~1.68 TB of weights fits 2 H200 nodes but needs 4 on H100, soh100: 32, which also dropssingle_node_tpfrom the H100 pill row for free (8 GPUs can't clear a 32-GPU bar). Only exact GPU ids are read, never generations: GPUs of one generation differ in VRAM, which is exactly what moves the floor. Opt-in and fail-open: absent = no floor, so existing recipes are unaffected. A multi-node strategy stays offered and grows the node count to meet its bar when picked (the Nodes row gains the count that first clears it, e.g. 4 on a 4-GPU NVL tray); a single-node strategy can't scale, so it drops out when the floor exceeds one node's GPUs. Applies to PD pools too, keyed by pool parallelism (tp/tep/depâ the matchingmulti_node_*entry) â each pool is sized to its own floor. Helpers:minGpusForStrategy/nodesForStrategy/isStrategyReachableincommand-synthesis.js, shared by the builder and the JSON API. Distinct from the (currently unread)hardware_match.min_gpusinstrategies/*.yaml, which is a per-strategy structural minimum rather than a per-recipe one.kv_cache_strategy_hardware(optional) â per-strategy/per-GPU opt-OUT for the Mooncake pills:{ <kv_store_id>: { <gpu_id>: unsupported } }. Follows the repo's fail-open hardware convention: absent = assumed to work (pill enabled on any scalable GPU);unsupporteddisables the pill and makes the JSON API skip that strategy on that hardware. "Off" and "Simple" need no gating (Simple is defined once intaxonomy.yaml â kv_offload).strategy_hardware(optional) â per-serving-strategy hardware overrides,{ <strategy_id>: { <hw_key>: unsupported | supported } }, layered on the membership default fromcompatible_strategies(listed = supported everywhere, unlisted = nowhere). Each per-strategy map takes the variant-tpkeyspace â exact GPU id > generation > brand (lowercase) >default, first key present wins, an explicitdefault:beating the membership baseline â so both directions are one line per hardware key:unsupportedopts a listed strategy out of a GPU/generation/brand;supportedopts an unlisted strategy in, which also adds it to the offered set (nocompatible_strategiesentry needed â e.g. Kimi-K3 offersmulti_node_tp_dponly via{ h200: supported, gb200: supported, gb300: supported }).unsupportedrenders the Strategy pill disabled with a tooltip, keeps it out of the recommended/active fallback, and makes the JSON API skip that strategy on that GPU. Useunsupportedwhen a listed strategy is genuinely unusable on specific hardware (e.g. multi-node pure-TP on Hopper, which has no cross-node NVLink) â not for "untested". Helpers:isStrategySupportedOnHardware+effectiveCompatibleStrategiesincommand-synthesis.js(shared by the builder and the JSON API).hardware_overridesâ optional per-generation tweaks keyed byhopper,blackwell,amd, or the brand-widenvidia. Generation-specific blocks take precedence over the NVIDIA fallback. Each supplies{ extra_args[], extra_env{} }.strategy_overridesâ optional per-strategy tweaks (rare). Forpd_clusterspecifically:prefill/decodesub-objects set each pool'snodes,parallelism(tp|tep|dep), andtp;router.intra_node_data_parallel_sizepins the router flag that otherwise derives from the pools'max(dp_local); plus optionalpool_modes: [<mode>, âĻ]â narrows the PD-pool parallelism pills INDEPENDENTLY of the Strategy row. PD-pool modes are otherwise derived fromcompatible_strategies[]suffixes (viapdPoolModes), sopool_modesis how you offer TP/TEP as standalone serving strategies while locking disaggregated PD to a subset (e.g.pool_modes: [dep]â both pools DEP-only, single mode hides the pills; synthesis snaps any resolved mode not in the set to the first allowed one, so the JSON API stays consistent too).omni(optional) â vllm-omni online-serving config. Required whenmeta.tasksincludesomni. Shape:{ serve_binary?, port?, task_label?, task_hint?, tasks: [...] }.tasksaccepts bare ids from the catalog (t2i,i2i,t2v,i2v,ti2v,t2a) or{ id, key?, model_id?, vram_minimum_gb?, description?, extra_args?, curl?, benchmark? }overrides â Wan2.2 uses overrides to swap the served checkpoint per task.benchmarkis a static command override for diffusion or other non-LLM endpoints that cannot use the defaultvllm bench servecommand.serve_binary: "vllm-omni serve"swaps the binary; currently unused, and needed only for recipes pinned below vLLM 0.20.0, where thevllmconsole-script does not yet delegate to vllm-omni on--omni. Catalog lives atsrc/lib/omni-tasks.js.keyis the unique selector and URL identity when multiple request presets share one catalogid; absentkeyfalls back toid.task_labelandtask_hintcustomize that selector row.guideâ markdown string (|-block), rendered withreact-markdown+remark-gfm+rehype-slug.
VRAM formulaÂļ
vram_minimum_gb = ceil(params à bytes_per_param à 1.2) â uses total
params (MoE counts inactive experts; they still live in VRAM).
| Precision | Bytes per param |
|---|---|
| bf16, fp16 | 2 |
| fp8, int8, awq, gptq | 1 |
| int4, nvfp4, fp4, mxfp4 | 0.5 |
Examples:
- 70B BF16 â 70 Ã 2 Ã 1.2 = 168 GB
- 671B FP8 â 671 Ã 1 Ã 1.2 = 805 GB
- 235B NVFP4 â 235 Ã 0.5 Ã 1.2 = 141 GB
If a model_id-override variant points to a different base (e.g., a distilled
FP4 checkpoint), use that model's parameter count, not the base.
Mixed-precision quants (NVFP4 / ModelOpt) â don't trust the bytes-per-param table. NVIDIA ModelOpt NVFP4 checkpoints are not uniformly 4-bit: only the MLP linears drop to NVFP4 (W4A16), while attention linears + KV cache stay FP8 and embeddings/norms stay higher precision. hf_quant_config.json shows quant_algo: MIXED_PRECISION in this case. The pure params à 0.5 à 1.2 formula then underestimates â e.g. nvidia/Qwen3.6-27B-NVFP4 is ~21.9 GB on disk, not the 13.5 GB the table implies, so 27B à 0.5 à 1.2 = 17 is wrong (the weights alone exceed it). For any mixed-precision checkpoint, size from the real weight footprint instead:
# total_size is in bytes â GB; then à 1.2 for KV/activation overhead
curl -sL "https://huggingface.co/<org>/<repo>/resolve/main/model.safetensors.index.json" \
| python3 -c "import json,sys; print(round(json.load(sys.stdin)['metadata']['total_size']/1e9*1.2))"
So vram_minimum_gb = ceil(real_checkpoint_GB Ã 1.2) (Qwen3.6-27B-NVFP4 â ceil(21.9 Ã 1.2) = 27). The bytes-per-param table stays correct for uniform quants (plain int4/awq/gptq/fp8, and full-model FP4).