Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Run the entire Windows ML CLI pipeline (export → optimize → quantize → compile) in one command.
When to use this
Use winml build when you want to go from a Hugging Face model ID (or an
existing .onnx file) to a deployment-ready artifact in a single invocation,
without manually chaining winml export, winml optimize, winml quantize,
and winml compile. A build config file — generated by winml config — controls every
stage of the pipeline.
Synopsis
winml build [options]
Flags
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--config |
-c |
path | None |
WinMLBuildConfig JSON file, generated by winml config. If omitted, config is auto-generated from -m. |
--model |
-m |
string | None |
Hugging Face model ID or path to an existing .onnx file. |
--export-type |
choice | generic |
Output selector: generic builds the stock single/composite ONNX model; optimized builds the family's registered runtime-optimized recipe (today the onnxruntime-genai CPU/NPU bundle) for the resolved --ep/--device. optimized fails fast if the family has no recipe or the resolved target is not one the recipe supports. |
|
--output-dir |
-o |
path | None |
Directory for all build artifacts. Mutually exclusive with --use-cache. |
--submodel |
string | all components | Build a named component of a composite model instead of every component. | |
--use-cache/--no-use-cache |
flag | false |
Store artifacts in the Windows ML CLI global cache (~/.cache/winml/). Mutually exclusive with --output-dir. |
|
--rebuild/--no-rebuild |
flag | false |
Overwrite existing artifacts and re-run the full pipeline. | |
--quant/--no-quant |
flag | true |
Run the quantization stage (use --no-quant to skip), overriding the config. |
|
--no-compile / --compile |
flag | None |
Override compilation. --compile forces enable (config must have a compile section). --no-compile forces skip. Default: inherit from config. |
|
--optimize/--no-optimize |
flag | true |
Run the optimization stage (use --no-optimize to skip). |
|
--ep |
string | None |
Target execution provider for the analyzer (e.g., qnn). Falls back to the compile config EP if not set. |
|
--device |
-d |
string | auto |
Target device for the analyzer (e.g., npu, gpu). Default: auto (auto-detect). |
--precision |
-p |
string | auto |
Target precision (e.g., fp16, int8, w8a16). With -c, applied only when --device or --precision is passed. |
--analyze/--no-analyze |
flag | true |
Run the analyzer loop during build (use --no-analyze to skip). |
|
--max-optim-iterations |
integer | None |
Maximum autoconf re-optimization rounds (3 enforced internally when not set). --no-analyze implicitly sets this to 0. |
|
--shape-config |
path | None |
JSON shape overrides used while auto-generating a Hugging Face export config, for example {"height": 480, "width": 480}. Only valid when --config is omitted. |
|
--input-specs |
path | None |
JSON input tensor specs to merge into the Hugging Face export config. Symbolic string dimensions infer dynamic axes. | |
--export-config |
path | None |
JSON ONNX export config overrides to merge into the Hugging Face export config. | |
--dynamic-axes |
path | None |
JSON dynamic axes mapping for Hugging Face ONNX export, for example {"input_ids": {"0": "batch", "1": "sequence"}}. |
|
--trust-remote-code/--no-trust-remote-code |
flag | false |
Allow executing custom code from model repositories. Use only with trusted sources. | |
--allow-unsupported-nodes/--no-allow-unsupported-nodes |
flag | false |
Allow unsupported nodes to remain in the graph instead of failing the build. | |
--help |
-h |
flag | Show this message and exit. |
How it works
winml build reads a WinMLBuildConfig JSON file (from winml config) that
encodes device, precision, export, quantization, and compilation settings.
When -m is a Hugging Face model ID, the full pipeline runs: export → optimize
→ quantize → compile. When -m points to an existing .onnx file, the export
stage is skipped. During optimization, the optional analyzer feedback loop
(--max-optim-iterations) recommends further transformations before later
quantization and compilation stages. --no-analyze disables that loop, not the
need to validate the result. Individual stages can be suppressed with --no-quant,
--no-compile, and --no-optimize without touching the config file.
When generating a configuration without -c, compilation is off unless you pass --compile. With an existing configuration, --compile requires a non-null compile section; generate it with winml config --compile first. An auto precision choice is target-dependent, so specify --precision fp32 --no-quant for a floating-point baseline.
Use --rebuild when intentionally rebuilding existing artifacts. The output location contains a final artifact and intermediates from the stages that actually ran; a skipped stage doesn't produce a new artifact. Run perf and eval separately to measure performance and quality rather than treating a successful build as deployment validation.
Tip
Reproducible CI/CD builds
Check the config into source control to record the pipeline settings. Also pin tool versions, model and dataset revisions, calibration inputs, and the target runtime environment when comparing builds. Set "auto": false to disable automatic configuration discovery. A configuration file alone doesn't guarantee identical artifacts across machines or versions.
Genai bundles for decoder LLMs (CPU/NPU)
For a registered decoder-LLM family (currently Qwen3), --export-type optimized switches winml build from the stock per-model ONNX output to a
complete onnxruntime-genai
bundle directory:
| File | Role | Precision |
|---|---|---|
ctx.onnx |
Transformer prefill graph | w8a16 (default) |
iter.onnx |
Transformer decode graph | w8a16 (default) |
embeddings.onnx |
Token embedding table (CPU) | fp32 |
lm_head.onnx |
Vocab projection (CPU) | w4a32 |
genai_config.json + tokenizer |
onnxruntime-genai runtime metadata | — |
# One command: HF decoder LLM → full onnxruntime-genai bundle
winml build -m Qwen/Qwen3-0.6B -o out/qwen3-bundle --export-type optimized
--export-type optimized resolves --ep/--device the same way a generic
build does — an explicit value is honored, otherwise the host is probed — and
then builds the recipe for that resolved target. The Qwen3 recipe supports
CPU, QNN/NPU, VitisAI/NPU, and OpenVINO/NPU. Other targets fail fast (naming the ep/device)
instead of silently producing a generic model. Pin the provider when needed:
# Qualcomm Snapdragon NPU
winml build -m Qwen/Qwen3-0.6B -o out/qwen3-bundle --export-type optimized --ep qnn --device npu
# AMD Ryzen AI NPU
winml build -m Qwen/Qwen3-0.6B -o out/qwen3-bundle --export-type optimized --ep vitisai --device npu
# CPU, without an NPU provider
winml build -m Qwen/Qwen3-0.6B -o out/qwen3-bundle --export-type optimized --ep cpu --device cpu
An explicit target skips host detection, which is useful for reproducible CI. An
unregistered family, a pre-exported .onnx input, or module mode also fail fast.
--output-dir is required (the bundle is a directory) and --use-cache is not
supported. Precision choices are recipe-specific: the Qwen3 recipe requires
w8a16 for its transformer and rejects incompatible overrides. CPU companions
retain their recipe-defined precisions.
Note
Backward-compatible shortcut
When --export-type is omitted, a registered family with an explicit
--ep qnn on an NPU target still routes to its optimized bundle. The NPU
target may be explicit (--device npu) or resolved from auto — whether
--device auto is typed or --device is left off entirely:
winml build -m Qwen/Qwen3-0.6B -o out/qwen3-bundle --device npu --ep qnn
# or let device auto-detection pick the NPU (--device may be omitted):
winml build -m Qwen/Qwen3-0.6B -o out/qwen3-bundle --ep qnn
--export-type generic always forces the stock composite build, even for a
registered family on the NPU.
See Qwen3 — Genai Bundle for the full walkthrough.
Examples
# Full pipeline: HF model → export → optimize → quantize → compile
winml build -c config.json -m microsoft/resnet-50 -o output/
The build reports each enabled stage and its final artifact path. Skipped stages don't produce new intermediates. See Output layout for files to retain.
# Start from a pre-exported ONNX file (skips export stage)
winml build -c config.json -m resnet50.onnx -o output/
# Export and optimize only — skip quantization and compilation for quick testing
winml build -c config.json -m bert-base-uncased -o output/ `
--no-quant --no-compile
# Force a clean rebuild, overwriting any cached artifacts
winml build -c config.json -m facebook/convnext-tiny-224 -o output/ --rebuild
# Use the global cache and cap optimizer iterations for faster turnaround
winml build -c config.json -m microsoft/resnet-50 `
--use-cache --max-optim-iterations 1
# Build with a dynamic batch axis during Hugging Face export
winml build -m microsoft/resnet-50 -o output/ `
--dynamic-axes dynamic_axes.json
Common pitfalls
- Either
--output-diror--use-cacheis required; they are mutually exclusive. Omitting both raises an error immediately. --use-cacheis not supported in module mode. When the config is a JSON array (module mode), only--output-diris accepted.- The config file must come from
winml config. The schema is strict; unknown keys are rejected. - Export-shape flags only affect Hugging Face export. They are rejected for pre-exported ONNX inputs because the export step has already happened.
- Existing artifacts are reused by default. Pass
--rebuildto force a fresh run after changing the config. - Genai bundles require
--output-dir, not--use-cache. An optimized decoder-LLM bundle (--export-type optimized, or the--device npu --ep qnnshortcut) writes a directory of components and rejects--use-cache.
See also
- winml export
- winml compile
- Config and build
- How it works
- Config Schema — generated JSON sections and common settings
- Output Layout — what each output file contains
- Supported Models — validated model architectures