flash train. Every run
requires project, model, and environment.id. algorithm defaults to
sft. Run the submit-time checks
without starting a run using flash train config.toml --dry-run; it allocates no
training GPU, though an SFT config with no cached workload profile starts a
billed profile run first (see flash train).
Top level
[environment]
[environment.params]; those values are recorded on
the run. Every name you list under [environment].secrets must resolve to a
value in your shell, .env, or .env.local when you submit. Names such as
FREESOLO_API_KEY, RUN_ID, and GITHUB_TOKEN are reserved by Flash.
Scorer dependencies
If your reward function imports a third-party package the managed runtime does not ship, declare it under[environment] pip and the worker installs it before
your environment loads:
pip = "pymongo" is rejected with the bracketed form to use. Entry syntax is
validated at submit, before a GPU is allocated, because a malformed entry would
otherwise fail mid-install on hardware you are already paying for:
- Only requirements, never pip options. A leading
-(--no-deps,--target=...,--extra-index-url=...) is rejected: those change how the mandatory worker requirement installs. - No credentials in a URL. The spec is stored and uploaded in plaintext, so a token in a direct or VCS requirement URL would be written to the run record. Any userinfo before the host is rejected, as is any query string.
[environment] secrets supplies values to your environment at
runtime, after installation, so it cannot authenticate pip. Vendor the package
into the folder you publish, or depend on a publicly installable one.
Your requirements install alongside Flash’s own managed worker requirement rather
than replacing it, so the runtime your environment loads into is never displaced.
A transient package-index failure is retried before the run is given up on; a
genuine resolution or build failure is terminal, because retrying it would only
burn GPU time.
A dependency you forgot to declare otherwise surfaces on the worker as a scorer
that cannot import. flash env test runs against your local interpreter, so a
package installed on your machine but missing from pip passes locally and
fails only once the run starts - declare everything your scorer imports, rather
than relying on a local pass.
[train]
[train] is one flat table shared by all three algorithms. Keys that apply
everywhere are below; the rest are scoped by algorithm and a knob the run’s
algorithm cannot consume is rejected at submit rather than silently ignored. See
Knobs are scoped by algorithm.
--dry-run resolves warm-start rank and alpha for you. Local --cost may warn
and estimate with defaults instead.
Knobs are scoped by algorithm
There are no[sft], [grpo], or [opd] tables: every knob lives under
[train], and the error names the key you set. --dry-run surfaces these
without allocating a GPU.
GRPO and OPD need a stated horizon
SFT measures its dataset, so an uncapped SFT config prices fine. GRPO and OPD quote offline from the catalog with nothing measuring the pool, so a config that sets neithermax_examples nor a positive max_steps is refused rather than
quoted:
[environment.params] max_examples does not count: it reaches
your environment as an opaque load_environment() kwarg that the starter
templates ignore, so only [train] max_examples is applied by the worker.
The optimizer batch has a different name per algorithm
SFT authorsbatch_size; GRPO and OPD author prompts_per_step. They are not
interchangeable, so each is rejected under the other algorithm, naming the key
you meant:
batch_size into examples-per-update
against your real tokenized dataset. Under GRPO and OPD there is no profile:
prompts_per_step is the optimizer batch, and each step samples
prompts_per_step x group_size completions. Do not carry a value across when
porting a config: a typical SFT batch_size is far smaller than the 64 GRPO
and 8 OPD defaults.
SFT-specific
Its only algorithm-only key isbatch_size - every rollout knob is rejected,
because SFT trains on your dataset’s completions and never generates.
When sequence packing is off
Flash packs multiple examples into one sequence when it can prove the packing is boundary-safe, which every catalog model on the managed worker image qualifies for. Multimodal rows are never packed.--cost, --dry-run, and train all
warn when your run cannot pack.
An unpacked run trains exactly one example per optimizer update, so
batch_size no longer groups examples. It is not inert, though - it still keys
the workload profile and sizes the GPU for an auto-sized run, so changing it can
bill another profile run and move the card you land on.
The default learning rate is tuned for a batched update, so expect noisier steps
and lower learning_rate if you are comparing against a packed run.
GRPO-specific
OPD-specific
OPD derives updates from epochs, retained prompts, andprompts_per_step unless
positive max_steps sets an exact horizon; one of those or max_examples is
required. An SFT warm-start is recommended.
There is no auxiliary EOS loss. For termination problems, use an SFT warm-start,
verify teacher quality, set a hard prompt budget, add suitable
stop_sequences,
and inspect truncated_rollouts.
The local --cost estimate may itemize teacher usage for diagnosis, but only GPU
time is charged.
Managed teachers
The teacher is platform-managed:teacher_model takes one of these friendly
aliases, and a provider or repository identifier is never accepted. An
unsupported value is rejected before a GPU is provisioned.
Image-bearing OPD
Distilling a prompt that contains an image requires a teacher that can see it. Select one of the image-capable aliases above; any other teacher is rejected, with the aliases you can use named in the error. When the images are in your dataset file, Flash sees them at submit and rejects a text-only teacher before a GPU is allocated. When your environment code attaches the image instead - building it insidebuild_prompt_messages, say -
nothing can see it until that code runs, so the same rejection happens on the
worker after allocation. Both fail the run rather than distilling blind.
The restriction is not bureaucratic. A text-only teacher answers a request
carrying an image with a normal 200 and no indication that it ignored the
pixels, so without the check a run would train, bill, and quietly distil from a
teacher that never saw the image. Flash verifies the image survived into the
teacher’s own tokenization and fails the run if it did not.
Multi-turn image-bearing OPD is not supported and is rejected up front.
Single-turn image prompts are the supported shape. Requires Flash 1.1.42.
Structured outputs
structured_outputs constrains GRPO and OPD rollouts; SFT rejects it. Set
exactly one JSON schema, regex, choice, or json_object constraint. Optional
whitespace controls are documented in the guide. Combining constraints or using
unsupported grammar forms is rejected. With thinking = true, reasoning remains
free-form and the grammar begins after </think>. See
Structured outputs.
[gpu]
A pinned GPU class is honored on retries and in cost estimates. Use
type when
hardware identity matters; everything else about allocation is managed.
Multi-GPU runs
Omit bothtype and count and Flash sizes the run for you. It picks the
smallest geometry-safe card count your configuration actually fits on, then ranks
the fitting shapes by cost per step. A run that needs more memory than one card
holds is placed on two, four, or eight instead of being rejected.
Only rentable shapes are ever provisioned: 1, 2, 4, and 8.
Setting count turns it into a hard ceiling that never escalates:
3 therefore never buys 4 cards - it permits 1 or 2. An explicit
count = 1 on a run that does not fit one card is an error rather than a silent
escalation, and it names the smallest count that would work:
Pinning
type without a count stays a single-card pin, so naming a
specific card never quietly bills you for four of them. Auto-sizing applies
only when you omit both.flash train --gpus N sets the same ceiling from the command line without
editing the config. Cost is quoted for the shape the run actually occupies, so a
multi-card run is priced on every card it held.
[wandb]
Optional Weights & Biases logging labels. These values are
non-secret; set WANDB_API_KEY in your local environment when submitting a run
to enable logging to your own W&B account.
Overrides & composition
Set any value at submit time without editing the file. The override flag is--set (repeatable, dotted keys):
--config overlays merge onto it, and
--set/--gpus win over both, applied left to right. An absent
--gpus is indistinguishable from no flag, so a [gpu] count authored in the
file is never silently downgraded.