load_environment() function returns the
dataset, prompt builder, and reward logic that Flash uses for SFT, GRPO, and OPD, and
local validation.
Task records
Author dataset rows withinput and output:
The algorithm decides which column the model learns from. SFT trains
directly on
output, the gold answer. GRPO and OPD use only input: the
model generates its own answers from the prompt, and learns from your reward
(GRPO) or a teacher’s token-level grading (OPD). output is optional for both.
GRPO reads it only if your score_response uses it as a reference; OPD ignores
it entirely, since the teacher, not your reward, is the training signal.
load_task_examples(...) accepts a local file path or an iterable of records.
- File formats:
.jsonl,.json,.csv,.txt, or.bson. - Field mapping:
input->example.input,output->example.output,metadata->example.metadata. - Original row: the untouched record stays available as
example.record.
dataset/train.jsonl
input plus an optional output; alternate prompt or target
key names are not accepted. Records are canonicalized to exactly
input/output/metadata.
Message-shaped SFT targets
For SFT,output is the gold completion appended after the environment’s
prompt messages. A scalar output becomes one assistant message. To teach a
multi-turn trajectory or native tool calling, set output to
{"messages": [...]} or a bare list of chat messages. Flash preserves those
assistant, tool-call, tool-result, and reply messages when it builds the SFT
example.
dataset/train.jsonl
output is validated rather than coerced, so a malformed
trajectory fails instead of collapsing into one bare turn:
{"messages": ...}must hold a list, and every entry in it must be an object.{"messages": [...]}may not carry sibling keys - that shape is exactly one key.- A list mixing message objects with non-objects is rejected.
output is still rendered into a single assistant message, so the
strictness applies to targets that look like chat messages, not to plain answers.
Use Environment.sft_completion(example) when your environment must
synthesize or transform the gold completion before SFT.
Validate thinking-model SFT targets
SFT on a thinking model (thinking = true) expects each gold completion to
literally contain a <think>...</think> block. Catch missing blocks locally
before submitting a run:
UserWarning naming the
first few. Unlabeled records (no output) are skipped.
Image inputs
Every catalog model is multimodal, so a prompt can include images and Flash trains and serves on them. Images belong in the prompt, not in the gold completion: an image inside an SFToutput message is rejected.
Build a multimodal prompt the OpenAI way: a user message whose content is a
list of parts, mixing text with one or more image parts. Flash accepts image,
image_url, and input_image parts, and each image source can be a data:
URI, raw bytes, a PIL image, or a package-root-relative path under dataset/
(e.g. dataset/photo.jpg). Remote http(s) URLs are not accepted; see
below:
environment.py
image (single) or images (a list).
These are the one exception to the field whitelist above: the multimodal loader
reads them from the original row (example.record) and appends them to the
first user message, so they survive even though they are not part of the
canonical input/output/metadata mapping. Either way, one example may hold
up to 8 images.
Remote URLs
Remotehttp(s) image URLs are not supported, and there is no flag to
enable them: Flash never fetches a user-supplied URL at training time, so the
training input stays fixed at submit. Include the image in the environment
package as a relative path, or embed it as a data URI. A relative path is
resolved from the package root and must stay inside dataset/
(e.g. dataset/photo.jpg).
Algorithm notes: SFT trains on image prompts with a text completion, and
GRPO carries the prompt’s images through the episode. OPD needs a teacher
that can see the image - select a vision-capable teacher_model, or the run is
rejected rather than distilled from a teacher that never saw it. See
image-bearing OPD. Package image
files under dataset/ so they upload with the environment (see
What gets uploaded).
Load sidecars
Read packaged files relative to__file__ so paths work locally and in a managed
run.
environment.py
build_prompt_messages, score_response) is covered
in Environments.
Then select the split from your Flash config:
[environment.params] values are passed to your load_environment(**kwargs).
split is also honored by Flash itself: for an environment packaged with
dataset files, split = "eval" selects dataset/eval.jsonl (or .json) as
the dataset Flash trains on: SFT targets and GRPO problem selection alike. If
the environment packages a default train split but the requested split file
does not exist, the run fails at load time instead of silently falling back to
train.jsonl. An explicit dataset_path param takes precedence over split.load_environment() builds self.dataset in code, those rows are what
Flash trains on - the packaged file is only the fallback for an environment that
exposes no dataset of its own. Filtering, subsampling, augmentation, and
deduplication done in Python are honored rather than overwritten by a re-read of
the file. That holds even when your filter matches nothing: an empty in-code
dataset fails rather than quietly falling back to the unfiltered file and
training on the rows you meant to exclude. An explicitly selected dataset_path,
records, or side split still wins over an in-code dataset.
What gets uploaded
For a local environment directory,flash env push includes:
environment.py, always at the artifact root.- Sibling Python helper files.
- Sidecar directory named
dataset. - Common sibling data files such as
.jsonl,.json,.csv,.txt,.md,.parquet,.tsv,.yaml, and.yml.
.env files and files
matching *.key, *.pem, *.pfx, *.p12, credentials*, or SSH key names
(id_rsa*, id_ed25519*, and similar) are excluded. Keep the artifact small:
environment uploads are capped at 64 MB compressed, 256 MB uncompressed, and
5000 files. For large corpora, keep the data in an external store and pass the
identifier or URL through [environment.params].
When you push a single .py file (or a folder with just one top-level .py),
only that entrypoint, a sibling README.md/TRAINING.md, and any dataset/
tree are packaged, and sibling helper modules are not. An evaluations.py is
not packaged in single-file mode either; push the folder if you want
flash env eval suites to travel with the
environment.
Next steps
Single-turn environments
Load these records inside an environment class.
Training
Train SFT, GRPO, or OPD on your dataset.