Imported from vllm-ascend/vllm-ascend-recipes (
.claude/skills/add-recipe/SKILL.md). Install upstream withnpx skills add vllm-ascend/vllm-ascend-recipes --skill add-recipe. Copyright stays with the author.
Add a new vLLM-Ascend recipe
Recipes are YAML files at models/en/<Provider>/<Model>.yaml (English, source of truth) with a models/zh/<Provider>/<Model>.yaml mirror (identical field structure, Chinese descriptions). The site is a static Astro app generated from these files; src/lib/schema.ts (zod) is the validation authority.
End-to-end steps
- Confirm the model id. Get the exact
<org>/<repo>string (striphttps://modelscope.cn/models//https://huggingface.co/prefixes). The page URL is derived from the YAML path (models/en/<Provider>/<Model>.yaml→/<provider>/<model>), andmodel.model_idshould be the exact org/repo. - Fetch model metadata. Pull
config.jsonfrom HF/ModelScope:architecture(moeifnum_experts/*MoE*arch names, elsedense),parameter_count/active_parameters,context_length(max_position_embeddings, ortext_config.max_position_embeddingsfor VL models). - Read the model README — don't skip. Mine it for:
min_vllm_version/nightly_required,dependencies, parser flags (--tool-call-parser,--reasoning-parser,--enable-auto-tool-choice), MTP/quantized companion repos (→spec_decodingfeature orvariantswithmodel_idoverride), recommended serve flags, and hardware guidance. - Cross-check vllm-ascend support. Verify the model works on the vllm-ascend version you claim; required flags go into
model.base_args, base env intomodel.base_env. Copy any--speculative-configJSON verbatim from the README. Reference the official tutorial — pulldocs/source/tutorials/models/<Model>.mdfrom the matching vllm-ascend tag (e.g.v0.23.0rc1) and use it as the single source of truth for the recipe: scenario division (single-node / multi-node DP / PD separation / request forwarding), serve flags, env vars and per-scenario parameters must match the tutorial. Do not invent scenarios or parameters the tutorial doesn't cover. - Author
models/en/.... Follow the schema below. Use an existing recipe (e.g.models/en/Qwen/Qwen3-30B-A3B.yamlormodels/en/DeepSeek/DeepSeek-V4-Flash.yaml) as a template. Keep the tutorial content in our fields (overview/prerequisites/env_setup/scenarios); leaveguideempty. - Mirror to
models/zh/...1:1. Same field structure (meta/model/features/variants/strategies/overrides/dependencies/config_params/scenarios/extra_config), only descriptions in Chinese. If the zh file is missing, the site falls back to English. - Register CI verification when required. Adding a recipe alone does not make it eligible for runtime CI or the site's verification badge. If the model/configuration is meant to be verified, add its exact recipe path, runner, mode, and four-part scenario selector to
.github/verification-targets.yaml. Register every configuration intended to count toward the model's green/yellow/red verification summary. Do not add configurations that cannot yet be scheduled on an available runner. - Register the runner weight alias when required. Do not put weight paths or weight files in
.github/verification-targets.yaml. For a single-node verification target, first arrange for the weights to be baked or mounted in the runner image, then add the recipemodel.model_idtomodels/_cache_paths.yamlwith its on-runner cache directory. The verification script resolvesyour_model_pathfrom this mapping and skips safely if the image does not actually contain the weights. - Make CI curl verification runnable. Every curl command that CI executes must use
http://<server_ip>:<port>orhttp://<node0_ip>:<port>; the verifier normalizes these to its local server and selected port. Do not hardcode:8000in executable verification commands. Keep tutorial-provided request assets unless evidence shows they are the failing dependency: first confirm that the request reached the local API. Keep/v1/modelsreadiness distinct from a successful inference request. On a curl failure, preserve and inspect stderr/response before changing model flags. - Validate. Run
pnpm validate(zod schema + interlock errors), thenpnpm check:recipes(field-level / upstream-alignment rules, see "Validation" below), then./scripts/format.sh(validate + typecheck + lint + prettier, mirrors CI). Preview withpnpm devat/{provider}/{model}. - Commit. Stage the recipe YAML(s), and include
.github/verification-targets.yaml/models/_cache_paths.yamlonly when they were intentionally updated for CI verification. Never stagepublic/or generated files. Message:feat(recipe): add <Provider>/<Model>(orfix(recipe): ...for updates).
Upstream contribution mode
Use this mode when the final destination is vllm-project/recipes. The upstream site generates user-facing commands from taxonomy.yaml and recipe YAML; it must not depend on private runners, mounted caches, or CI-only scenario fields.
Before editing
- Check upstream
mainfor an exact recipe path. If it exists, start from that file rather than copying ourmodels/enversion. If it does not exist, confirm the model ID and create one file atmodels/<hf_org>/<hf_repo>.yaml. - Check upstream
taxonomy.yamlfor the hardware key. Add a hardware profile first when absent; do not encode hardware names as strategy IDs. A profile must state brand, generation, display name, device count, VRAM, single-/multi-node behavior, scalability, and whether it is restricted. - Confirm that the claimed hardware is tested end to end. Only tested hardware may be listed as
verified; untested hardware stays absent.
Convert the Ascend-specific recipe
- Map custom strategies such as
single_node_A2orsingle_node_A5to upstream strategies such assingle_node_tp,single_node_tep, orsingle_node_dep. - Put hardware-specific flags and images in
hardware_overrides.<hardware>orvariants.<variant>.hardware_overrides.<hardware>. - Represent a different checkpoint as a
variantsentry with its exactmodel_id, precision, VRAM minimum, andsupported_hardware. - Keep
meta.hardwareas verification metadata, not as a substitute for a runnable command. - Convert private
scenarios, runner labels, mounted weight paths, and CI-only fields into public recipe fields (variants,features,hardware_overrides,strategy_overrides, andguide). Never publish paths such as/root/.cache/...or labels such aslinux-aarch64-a5-8. - Split combined or provider-specific files when upstream has separate model IDs. Do not overwrite a similarly named but different checkpoint.
- Keep the recipe self-contained: users must be able to download the checkpoint and reproduce the command from public information.
Example for a single-hardware quantized checkpoint:
meta:
hardware:
ascend_950dt: verified
variants:
ascend_w4a4:
model_id: "Eco-Tech/GLM-5.1-w4a4c8-mxfp4"
precision: mxfp4
vram_minimum_gb: 768
supported_hardware: [ascend_950dt]
hardware_overrides:
ascend_950dt:
docker_image: "<public-ascend-image>"
extra_args: ["--quantization", "ascend"]
extra_env:
PYTORCH_NPU_ALLOC_CONF: "expandable_segments:True"
compatible_strategies:
- single_node_tep
The example is a shape guide: use values verified for the specific model and hardware, not copied defaults.
Evidence required in the PR
Include the exact hardware model and device count, checkpoint, container or vLLM/vLLM-Ascend version, launch command, startup evidence, /v1/models response, and one successful inference request. Include feature evidence when the recipe advertises tool calling, reasoning, MTP, or quantization. If benchmarked, link the reproducible benchmark command and distinguish measured facts from recommendations.
Upstream validation and PR hygiene
Run the upstream checks from an upstream checkout:
node scripts/build-recipes-api.mjs
pnpm build
The generated API must parse the taxonomy and recipe without errors, the model path and model_id must agree, all hardware and strategy keys must exist, and the page must render a runnable command. Do not commit generated public/ output unless upstream instructions explicitly require it.
Keep a focused PR: hardware taxonomy plus one model variant is preferable to a bulk migration. Use a signed-off commit (Signed-off-by: <GitHub author> <account email>) if the upstream DCO check requires it. Do not merge the PR yourself; leave review and CI gates to upstream maintainers.
Community task template
Copy and adapt this when assigning an upstream-oriented task:
Task: Add <model> single-node support for <hardware>.
Required:
- use the upstream recipe if one already exists;
- verify or add the hardware profile in taxonomy.yaml;
- use upstream single_node_* strategies;
- model checkpoint, precision, VRAM, image, flags, and env must be public and reproducible;
- put hardware-only behavior in variants/hardware_overrides;
- provide end-to-end evidence: startup, /v1/models, and inference;
- run node scripts/build-recipes-api.mjs and pnpm build;
- keep private runner labels, cache paths, and CI scenarios out of upstream files;
- submit a focused signed-off PR and do not merge it directly.
Evidence: <hardware/device count> · <checkpoint> · <software version> · <commands/logs> · <PR URL>
YAML schema (top-level, 总-分)
Top-level fields
| Field | Required | Notes |
|---|---|---|
meta |
yes | Display metadata (see below) |
model |
yes | Model info + upstream fields (see below) |
overview / weight_download / env_setup / scenarios / references |
yes | Our tutorial fields; scenarios is the CI-execution baseline |
prerequisites / quantization / verification / performance / evaluation / tuning / faq |
no | Optional page sections |
features |
no | Upstream feature declarations (label / description / args / env); boolean toggles live here |
opt_in_features |
no | Feature keys that default OFF (must reference features) |
variants |
no | Upstream variants; default variant required |
compatible_strategies |
no | Deployment strategies, interlocked with scenarios[].strategy |
hardware_overrides / strategy_overrides |
no | {extra_args, extra_env} per hardware / strategy; PD recipes additionally declare strategy_overrides.pd_cluster.prefill/decode.nodes (see below) |
dependencies |
no | Extra installs: note + command |
guide |
no | Upstream tutorial body — keep "" (content lives in our fields) |
extra_config |
no | Toggleable additional-config chips (see scenarios) |
config_params |
no | Editable value params substituted via {{name}} |
meta
title, slug, provider, description, date_added (never change) required; optional date_updated, difficulty (beginner|intermediate|advanced), tasks, performance_headline, related_recipes, hardware (atlas_800_a2/a3 → verified|experimental|unsupported).
model
model_id, architecture (dense|moe), parameter_count, active_parameters (MoE; null dense), context_length, modality required. Optional upstream fields: base_args (flags every scenario needs), base_env (env every scenario needs), docker_image (string or per-hardware object atlas_800_a2/a3), nightly_required (true when min version isn't stable), install (tabs pip/docker: false hides, object overrides command/note).
features / opt_in_features
features:
spec_decoding: # upstream key — never use `mtp`
label: MTP Spec Decoding
description: MTP speculative decoding
args: ["--speculative-config", '{"num_speculative_tokens": 1, "method": "mtp", "enforce_eager": true}']
flashcomm1:
label: FlashComm1
env: { VLLM_ASCEND_ENABLE_FLASHCOMM1: "1" }
prefix_caching:
label: Prefix Caching
args: ["--enable-prefix-caching"]
flag_when_false: "--no-enable-prefix-caching" # page extension
opt_in_features: [prefix_caching] # default OFF; features absent here default ON
Every feature needs args or env. flag_when_false (page extension) is the text rendered when the toggle is OFF.
Feature chips on the page pick their behavior from the step content automatically:
- referenced by a
{{key}}placeholder or%%CONFIG:key%%marker → toggle chip (on/off both render,opt_in_featuresdecides the default); - flags already hardcoded in every step's command → always-on chip ("included in the baseline");
- never referenced and never hardcoded → default-OFF toggle; enabling appends the feature's
args(orenvexports) to the renderedvllm servecommand.
variants / compatible_strategies
variants:
default: # required whenever variants is present
precision: W8A8 # upstream enum bf16|fp8|nvfp4|fp4|int4|int8|awq|gptq|mxfp4; W8A8 = Ascend extension
vram_minimum_gb: 341 # ceil(params × bytes_per_param × 1.2)
description: ...
w8a8_mtp: # quantized variant in another repo
model_id: Eco-Tech/DeepSeek-V4-Flash-w8a8-mtp
precision: W8A8
vram_minimum_gb: 341
compatible_strategies: [single_node_A2, single_node_A3, pd_cluster]
config_params and placeholders
config_params holds only editable VALUE params (default / type / description). Steps reference them with {{name}}; boolean toggles come from features via the same {{name}} syntax (on → args/env, off → flag_when_false). Rendered flags are highlighted in the chip color (%%HL%% markers are injected automatically; copy buttons get clean text).
Only parameters with a single tutorial baseline become
config_params. Scenario-specific values (e.g. different--max-model-lenper precision / hardware, like GLM-5's 200000/40960/32768/131072) stay literal in the step command — a top-level default cannot represent them all.
scenarios and extra_config
scenarios:
- npu: Atlas 800I A3
precision: W8A8
deployment: 单节点-多卡
case: 高吞吐
tags: [a3-single] # a2-single | a3-single | pd-multinode → CI routing
strategy: single_node_A3 # must be listed in compatible_strategies
steps:
- title: Start the server
content: |-
```bash
vllm serve ... --max-model-len {{max_model_len}} \
{{spec_decoding}} \
%%CONFIG:dsa-cp%%--additional-config '{"enable_dsa_cp": true}' %%/CONFIG:dsa-cp%%
```
extra_config:
- key: dsa-cp
label: DSA CP
%%CONFIG:key%%...%%/CONFIG:key%% keeps the wrapped text when the chip is on, removes it when off; optional per-step config_values (enabled/disabled) replaces instead.
PD-cluster scenarios + declarative topology
Multi-node PD recipes (tags: [pd-multinode] / strategy: pd_cluster) must declare strategy_overrides.pd_cluster so the site can render the node selector + Cluster env panel and generate the per-node commands:
compatible_strategies: [..., pd_cluster]
strategy_overrides:
pd_cluster:
prefill:
nodes: { default: 1 } # prefill node count
decode:
nodes: { default: 1, atlas_800_a2: 4 } # per-hardware overrides win over default
nodes= the number of nodes for that role. Derive it from the tutorial'slaunch_online_dp.pycommands:nodes = dp-size // dp-size-local.- Use per-hardware keys (
atlas_800_a2/atlas_800_a3) when different hardware has different topology (e.g. DeepSeek-V4-Flash is 1P1D on A3 but 1P4D on A2's 8-machine PD). - Independent multi-P groups are NOT derivable from
dp-size // dp-local: a recipe with 2 independent prefill groups each--dp-size 4 --dp-size-local 4still declaresprefill.nodes: 2explicitly. Don't try to infer the count from one launch command. - The imperative
scenariosbelow remain the CI source of truth;strategy_overrides.pd_clusteris the declarative site data.parallelism/vllm_args/envmay also be added for upstream-compatible script generation, but the current Ascend site only consumesnodes.
Launch command convention — collapse the tutorial's per-node launch commands into exactly 2 commands (first = prefill, second = decode):
# Prefill — each prefill node is its own DP master (dp-address = node IP)
python launch_online_dp.py --dp-size 4 --tp-size 4 --dp-size-local 4 --dp-rank-start 0 --dp-address xx.xx.xx.1 ...
# Decode — one DP group across nodes (dp-rank-start increments per node)
python launch_online_dp.py --dp-size 8 --tp-size 4 --dp-size-local 4 --dp-rank-start 0 --dp-address xx.xx.xx.3 ...
node_entry.py fills --dp-address (prefill → own IP, decode → master) and --dp-rank-start (decode → group_offset × dp-size-local) at runtime. Do NOT write four separate p0/p1/d0/d1 commands — the controller only reads launch_blocks[0] (prefill) and [1] (decode) and misassigns the rest.
Placeholders the Cluster env panel substitutes — keep these in the step code blocks, don't hardcode real values:
- Dotted node IPs
141.xx.xx.N/xx.xx.xx.N:Nis the 1-based pod index (prefill first, then decode). The site maps them to$PREFILL_NODE_*/$DECODE_NODE_*. local_ip="141.xx.xx.N"→ the node's own IP.nic_name="xxx"→$IFACE_NAME(fabric NIC).node0_ip="xxxx"→ prefill master IP ($PREFILL_NODE_1).<prefill_ip>/<decode_ip>→ prefill/decode master IP (Qwen3-235B style).
use_ascend_directinside the prefillkv_connector_extra_configappears only on prefill node 0 in some tutorials (e.g. Kimi-K2.6) — treat it as a tutorial inconsistency; put it on all prefill nodes or drop it consistently (DeepSeek-V4-Flash has none).
Hard rules
- Boolean toggles live ONLY in
features;config_paramsis values only. - Default state derives from
opt_in_features(absent = on) — don't add adefaultfield to features. scenario.strategy⊆compatible_strategies; tags must match the pipeline routing (a2-single / a3-single / pd-multinode).- A configuration counts toward the site's verification status only after it is explicitly registered in
.github/verification-targets.yaml; recipemeta.hardwareandscenariosalone do not create a CI target. - Keep verification metadata separate from weights:
.github/verification-targets.yamlselects the target and runner, whilemodels/_cache_paths.yamlmaps a model ID to an already available runner-cache directory. - Ascend install is docker-only:
install.pip: false;guide: "". en/andzh/field structures must be identical.- The official vllm-ascend tutorial (
docs/source/tutorials/models/<Model>.md) is the source of truth for scenario content and serve parameters; mirror it, don't improvise. - Keep the scenario serve commands the CI-execution source of truth; when editing flags, update base_args/base_env/features too.
- Resolve
{{ vllm_ascend_version }}literals in env_setup to the pinned version — the site only substitutes|vllm_ascend_version|, so curly-brace placeholders render verbatim to users.
Content conventions (learned from page QA)
- en files use English display values, zh files use Chinese:
deployment/caseinmodels/en/**must be English (e.g.Single-Node,Multi-Node PD Separation); the zh mirror keeps Chinese. - No backslash escapes in prose: write
1~2 cards(plain tilde), never1\~2— the page renders\~literally. - Install order:
env_setup.containeris the recommended path; the page defaults the tab to container when both exist. Keepcontainerbeforepipin the YAML. - Performance section carries BOTH accuracy and benchmark: the "More Info" tab renders
performance.accuracy+performance.benchmark— don't ship only one. Always link AISBench/vllm-benchmark, never mention them bare. - Use official hardware names: write
Atlas 300I DUO(orAtlas 800I A2/A3), not generic "Atlas inference products". - Weight download is required: every recipe must have
weight_download(the page renders weight chips near the top from it). - Blockquotes: lines starting with
>are rendered as styled blockquotes by the site — don't use literal>inside prose expecting it to stay text. - Never nest code blocks inside blockquotes: lines like
> ```bashmake the renderer emit code with a literal>prefix. Keep the>note as plain text and put the command in a standalone fenced block below it. - No English section names in zh prose: in
models/zh/**, refer to sections by their Chinese page titles (e.g. "参见下方“功能验证”部分", never "参见下方verification部分"). The YAML field keys stay as-is (verification:); only prose changes. - No mixed-language product names in zh: write
Atlas 300I DUO, not "Atlas 300I DUO昇腾产品" (or similar suffixes). Keep zh product names identical to en (brand names are not translated). - Image version is model-linked, not global: resolve
{{ vllm_ascend_version }}to the version the tutorial specifies for that model (e.g. Qwen3.5-27B/Qwen3.6-27B →v0.18.0rc1, with Atlas 300I DUO →v0.23.0rc1-310pper tutorial), not one global version. Keep the tutorial's own "validated against" / "supported starting" statements untouched. meta.tasksmust not duplicatemodel.modality: the page renders both as tags, sotasks: [text]+modality: textshows "text" twice. Only add tasks values that differ from the modality.- Weight download placement: the page renders
weight_downloadchips automatically inside the Prerequisites tab — don't duplicate weight links inoverview/prerequisitesprose. overviewis a concise model description only: 1–2 short paragraphs about the model itself (architecture / parameter count / family / purpose). Do NOT put supported hardware, software features, deployment topology, or version-validation notes inoverview— those belong inmeta.hardware,features,scenarios, andmodel.min_vllm_versionrespectively. Drop the "This document will show…" boilerplate.- No hardware badges at the top of the page:
meta.hardwareis CI/status metadata, not a header badge. Hardware availability is communicated through the scenario selector (scenarios[].npu) and the preparation/deployment sections — do not duplicate it in the page header oroverview.
Atlas 300I DUO (310p)
When the tutorial covers Atlas 300I DUO (inference products), mirror it faithfully:
meta.hardwaregainsatlas_300i_duo: verified;model.docker_imagegainsatlas_300i_duo: "<image>-310p".env_setup.containergets a300I DUOentry using the-310pimage (mount only the inference devices: davinci0 + davinci_manager/devmm_svm/hisi_hdc).- Add a scenario with
npu: Atlas 300I DUO,tags: [310p-single],strategy: single_node_310p(addsingle_node_310ptocompatible_strategies); 300I is TP-only (--dtype float16, conservative--max-model-len, per-tutorial values stay literal). scripts/verify-recipe.shskips300Iscenarios on the A2/A3 runners — keep that skip in place.
Referenced helper scripts
When a tutorial's PD/multi-node steps reference helper scripts (launch_online_dp.py, run_dp_template.sh, load_balance_proxy_server_example.py), either embed them in the step (like DeepSeek-V2-Lite) or link to the upstream examples (https://github.com/vllm-project/vllm-ascend/blob/main/examples/...) — never leave a dangling filename with no source.
Validation (pnpm validate)
The zod schema (src/lib/schema.ts) enforces, besides field types, these interlock rules:
opt_in_featuresreferences declaredfeatures;variantspresent →defaultvariant exists;scenario.strategyis listed incompatible_strategies;- step
{{name}}placeholders resolve toconfig_paramsorfeatures; %%CONFIG:key%%markers resolve to anextra_configkey or feature.
Field-level validation (pnpm check:recipes)
scripts/validate-recipe-fields.ts runs on every PR, push to main, and the
nightly prepare stage (before any cluster is touched). It checks what the zod
schema cannot express:
- Required sections:
meta(title/slug/provider/description/date_added),model,overview,weight_download(non-empty sources),env_setup,scenarios,references. - Upstream-aligned model fields:
model_idmust be<org>/<name>;architecture∈ dense|moe;variants→defaultexists and every variant hasprecision; everyfeaturehasargsorenv;opt_in_features ⊆ features;config_params.type∈ number|string|bool. - Strategy & Ascend conventions:
scenario.strategymust be listed incompatible_strategies;guide == "";model.install.pip === false(docker-only). - Scenario / step fields: each scenario has npu/precision/deployment/case;
non-empty steps with title+content;
{{name}}placeholders resolve to the top-level or scenario-levelconfig_params/features;%%CONFIG:key%%resolves toextra_config/features; script-backed scenarios requiretest_id/npu_per_node/service-checkand every{{script:x}}reference must exist. - en/zh parity: the zh mirror must have the same field-path structure as the en file.
Run it locally after editing a recipe — a real example it caught:
Qwen3-30B-A3B used strategy: multi_node_dp without listing it in
compatible_strategies.
Commit checklist
pnpm validate+pnpm check:recipes+./scripts/format.shgreen;zh/mirror committed with theen/change;- If runtime verification is expected, the intended scenario selectors are registered in
.github/verification-targets.yaml; any required runner cache alias is registered inmodels/_cache_paths.yamlonly after the weights are available in that runner image; - No
public/or generated files staged.