Skip to main content
flash train --cost prints a pre-flight estimate before you submit a run:
Use it before any non-trivial run: it validates the config and prices the training work without starting paid training or allocating a training GPU. GRPO and OPD quote locally from the catalog. SFT returns a bounded static estimate from the pinned environment package in the same command. On an SFT config, omitting max_examples (or setting it to 0) trains on every row. The submit-time quote is the amount Flash checks against your prepaid org balance. Successful runs are billed at the quoted Flash cost. A cancelled run is prorated from that quote by the share of the work it completed, capped at the quote - see Charges and cancellations.

GRPO and OPD quote locally; SFT reads packaged data

GRPO and OPD quote offline from the catalog, so --cost returns immediately without contacting the server. They need a stated horizon to price: set [train] max_steps for an exact update count, or [train] max_examples for the prompt-pool size epochs run over. A config that states neither is refused rather than quoted:
Because it stays local, that quote checks only local things: the TOML, the algorithm’s knobs, the catalog, the resource fit, the horizon, and the price. It cannot tell you whether your project and environment are reachable, whether your balance covers the run, or whether the teacher is available. Run --dry-run for those before a real submit. SFT uses an authenticated static estimate from the pinned environment package. Flash reads packaged JSON or JSONL rows, uses their raw input and output fields, and applies the statically readable training contract. Contract lookup follows contract_text, then contract_path, then TRAINING_CONTRACT.md.
  • No paid training starts, no training GPU is allocated, and there is no training charge or separate profile job.
  • Flash does not execute environment.py, load_environment(), dataset hooks, prompt construction, filtering, or scorer code.
  • A missing, empty, invalid, unreadable, or oversized dataset fails before GPU allocation. The limit is 32 MiB for the selected packaged dataset or inline records, and 256 KiB for the training contract.
  • The estimate returns directly in the command, with nothing else to follow.
The estimate is intentionally conservative about what it can know. Environment code may add prompts, few-shot examples, tool schemas, filtering, or other transformations that the static read cannot execute. Actual training may retain fewer rows, truncate more content, or run fewer effective steps than this static workload estimate predicts. The accepted submit-time quote remains the billing boundary: successful runs bill at that quote, while cancellations are prorated and capped at it. The SFT output therefore labels the workload values as packaged-dataset estimates rather than exact measurements.

The counts come from the published environment, not your working copy

An SFT estimate reads the published environment package your config points at, so --cost and --dry-run name the environment id and commit the counts came from:
Local edits you have not pushed are not in that estimate. If the numbers look stale, run flash env push --name NAME --project PROJECT_UUID [path] again to republish, then re-estimate - the output says so when the counts came from a published managed or GitHub environment. A GitHub id pinned to an exact commit will not pick up later changes at all until you move the pin. Inline [environment.params] records are different: those rows come from your config, so the package supplied the environment but not the dataset, and the output labels them accordingly.

How cost is calculated

flash train --cost reprices a run the same way the platform bills it:
The rate is per card, so a multi-card run is priced for every card it held. A single-card run occupies one and the last term drops out. The preview separates Setup, Train, and Billable time. Setup is not billed. Train covers the estimated training work, and Billable is the time used for the charge, including required finalization. Work before the first optimizer metric can therefore still be billable. Per-step time reflects user-selected work: GRPO scales with completion count and length (prompts_per_step × group_size × max_completion_tokens); SFT scales with the estimated training tokens; and OPD samples student completions before the managed teacher grades them. Teacher tokens are not billed to you. The estimator prices the cheapest eligible GPU automatically. A scalar [gpu] type pins one class; a list names acceptable classes that the estimator and allocator cost-rank together. The same constraint persists across submissions and retries. When you omit both [gpu] type and [gpu] count, the quote prices the shape Flash will actually auto-size to: the smallest geometry-safe card count your configuration fits on, ranked by cost per step. A configuration that needs more memory than one card holds is therefore quoted and billed as a multi-card run rather than rejected. Set [gpu] count (or --gpus N) to cap that. Authoring [gpu] type, as either a scalar or a list, without a count stays a single-card constraint, so an oversized run is rejected at preflight rather than quoted across several. See Multi-GPU runs. Serving is priced separately; see Serving billing.

What affects training cost

You control the main levers in the config:
  • Base model. Smaller models are cheaper and faster for smoke tests.
  • Algorithm. SFT usually costs least. GRPO and OPD both sample and score the model’s own completions before each update, so they cost more per step. Every algorithm is billed on GPU time; OPD’s managed teacher is not billed to you.
  • Epochs and exact step horizons. More epochs increases cost when Flash derives the update count. For SFT, GRPO, and OPD, positive max_steps sets the exact optimizer-update horizon; GRPO and OPD need that or max_examples to be quotable at all.
  • Required saves. Each save_at_steps entry adds required finalization work, so save cadence is a controllable cost lever.
  • Sequence length. Larger max_context_tokens and max_completion_tokens increase work per example. Keep them large enough for your prompt and answer, but do not oversize them by default.
  • Batch size and dataset size. For SFT, cost scales with the number of examples trained over and the batch/epoch settings.
  • On-policy sample count. For GRPO and OPD, group_size controls how many completions are sampled per prompt. Larger groups cost more.
  • Reward latency. If your GRPO reward calls an external model or service, slow grading can increase wall-clock time.

Reading the preview

A preview includes the model, algorithm, setup estimate, training estimate, billable training time, and total:
Setup is non-billable preparation. Train is the estimated training interval, and Billable is the portion used for the charge, including required finalization as well as optimizer updates. Treat the preview as the quote for the config you submit. If you edit the environment, dataset, model, algorithm, or [train] settings, run --cost again. When max_steps is positive, the preview uses it as the exact update count for SFT, GRPO, or OPD. Otherwise the count is derived from epochs, retained examples, and the optimizer batch (batch_size for SFT, prompts_per_step for GRPO and OPD).

Charges and cancellations

  • A run that completes successfully is billed at the submitted quote.
  • A run cancelled before its first training step is not charged for training.
  • A run cancelled after training starts is prorated from the quote you accepted, on the basis of the hardware it actually rented, and is capped at that quote - a cancellation can never cost more than letting the run finish.
  • Setup is not billed. Train and required finalization contribute to the Billable amount shown in the accepted quote.
  • flash runs status <run-id> shows the current or final cost record.

Serving billing

Serving is billed per token after deployment: (prompt − cached) × input + completion × output + cached × cached, at the per-model rates in Supported models. Prefix caching is automatic; the cached rate applies to a reused prefix. See Billing for how it works. Serving a base model with no adapter (a base-model id in the model field) is billed the same way, to the org whose API key made the request — not to an adapter owner. Tear down deployments you are done using:

Lowering cost

Validate on a smaller base model with short smoke tests before scaling epochs, max_steps, or the retained dataset size, and lower group_size and max_completion_tokens until the reward or teacher wiring is proven. For SFT, keep a held-out split and stop adding epochs once held-out quality stops improving. flash runs checkpoint <run-id> lets you deploy a good intermediate checkpoint rather than assuming the final step is best.

Why a later quote can change

The quote can change when you edit the config, publish different environment contents, change the dataset size, or submit after catalog/pricing updates. The authoritative number is the quote returned for the run you submit.