Skip to main content
Every supported model ships as a python launch script under scripts/, and starting a training run is one command:
This page explains what that command does and how to change what it runs. For the meaning of individual training flags, see Argument Groups and the CLI Reference.

How a launch script starts a training job

A launch script is a recipe, not the training process. It assembles the full train.py command line for one model family, starts a local Ray cluster, and submits the command as a Ray job. The pieces involved: When the script starts, it prints its resolved options as a table, then every shell command it issues with an EXEC: prefix — the log is a complete record of what ran.

The structure of a launch script

The sections below walk scripts/run_qwen3_dense.py; every launcher follows the same layout. The module docstring states the prerequisites (a converted checkpoint, the datasets) and a runnable example, then three parts follow in file order.

Selecting a recipe with --model-name

For some models one launcher provides multiple recipes, selected with --model-name. The per-variant values live in a _RECIPES table at the top of the file:
Single-recipe launchers skip the table and write their values directly in the flag blocks.

ScriptArgs — script options as CLI flags and MILES_SCRIPT_* env vars

The script’s own options are the fields of a ScriptArgs dataclass:
The @U.dataclass_cli decorator exposes each field twice: as a --kebab-case command line option (--model-dir) and as an environment variable with the MILES_SCRIPT_ prefix (MILES_SCRIPT_MODEL_DIR). A value given on the command line beats the environment variable, which beats the field default. The env form is how launch wrappers and cluster tooling inject machine-specific values without editing the script. Options shared by every launcher, from the ExecuteTrainConfig base class and repo convention:

execute() — assembling the train.py flags from grouped blocks

The execute() function builds the train.py command line as one f-string block per concern, then concatenates them:
Each block maps to a section of Argument Groups, which documents the flags themselves: Two blocks have no Argument Groups section: misc_args carries the cluster shape (--colocate, --actor-num-nodes, --actor-num-gpus-per-node), and the wandb flags come from U.get_default_wandb_args, which returns them only when WANDB_API_KEY is set — so wandb logging turns on by exporting the key, with no script change.

Three ways to override a recipe

From lightest to heaviest:
  1. Append flags with --extra-args. The value is appended to the end of the train.py command line, and for a flag given twice the later occurrence wins — so this overrides any flag the recipe already sets:
  2. Set a script option, as a flag or an env var. Anything on ScriptArgs can come from the command line or from MILES_SCRIPT_*:
  3. Edit the script. The launcher is the canonical home of a recipe’s hyperparameters and is meant to be read and edited — change the _RECIPES values or the flag blocks directly for anything you want to keep.

What execute_train runs on your machine

The launcher hands the assembled flags to U.execute_train, which issues the EXEC: commands you see in the log, in order:
  1. Kills leftover sglang, miles, and redis processes and stops any previous Ray cluster.
  2. Starts a fresh cluster with ray start --head, using --num-gpus-per-node GPUs.
  3. Runs the launcher’s before_ray_job_submit hook, if it has one (used for the ssh fan-out below).
  4. Builds the Ray runtime env for the job: PYTHONUNBUFFERED, CUDA_DEVICE_MAX_CONNECTIONS=1, NCCL_NVLS_ENABLE (your exported value if set, otherwise probed with nvidia-smi), MASTER_ADDR, no_proxy, and a PYTHONPATH containing the repo root and --megatron-path, plus anything from --extra-env-vars.
  5. Submits the job: ray job submit -- python3 train.py <architecture flags> <recipe flags>.
Two environment variables skip parts of this sequence: The head-node address defaults to 127.0.0.1 and is taken from MASTER_ADDR; export it on multi-node runs so Ray and torch distributed bind to the right interface.

Multi-step and multi-node launchers

Two launcher shapes go beyond a single execute().

Subcommand pipelines: prepare-* and full-train

Large-model launchers split the pipeline — download, precision cast, torch_dist conversion, training — into subcommands of one script (underscores in the function name become dashes on the CLI):
The full-train subcommand chains all steps and checks a sentinel file before each one, so a completed step is skipped on re-run — after an interruption, relaunch the same command and it resumes where it stopped.

Joining multiple nodes: per-role subcommands and ssh fan-out

A multi-node run needs every node in the Ray cluster before the job is submitted. Launchers express this in one of two ways:
  • One subcommand per node role. scripts/run_nemotron_3_super_120b_a12b.py has worker (joins the head’s cluster and blocks) and train (starts the head, waits until the cluster reports every GPU, then submits); you run one command on each node.
  • ssh fan-out from the head. With --join-ray-workers, scripts/run_qwen3_sft.py sshes every host of an MPI-style hostfile into the cluster (U.ssh_start_ray_workers as the before_ray_job_submit hook), so the whole cluster comes up from a single command on the head node.

Model architecture definitions in scripts/models/

Megatron cannot read the architecture from a HuggingFace checkpoint, so each megatron_model_type has a file in scripts/models/ named exactly after it, exposing one function that returns the architecture flags:
execute_train resolves the file by name and splices its output into the train.py command line ahead of the recipe flags. A variant (a layer-pruned debug model, a LoRA target) derives from its base file with load_sibling_model_args instead of copying it.
Architecture parameters are not self-validating. Two checkpoints from the same family can ship different --rotary-base, vocab padding, or normalization epsilon. Diff the checkpoint’s config.json against the file in scripts/models/ before a first run, and override any drifted value by appending it, e.g. --extra-args "--rotary-base 10000".

Next

  • Argument Groups — which training flags belong to which block, and what they mean.
  • CLI Reference — every flag Miles accepts.
  • Quick Start — downloading and converting a checkpoint, the step before any launcher.
  • Customization — the --*-path plug points for custom rollout, reward, and filter code.
  • Models — the per-model recipe pages built on these launchers.