Pipeline YAML¶
Read and edit a whole pipeline as text in the YAML tab, share it as a file, and run it from the command line with tuneline run-local.
Every pipeline can be written as a short YAML file. It holds exactly what the canvas holds: the steps, how they are linked, the settings you changed, and where each step sits on the canvas. Use it to:
- review a pipeline at a glance, or compare two versions of it in a diff tool;
- make many edits at once (for example change a setting in several steps);
- copy a pipeline to another account, or keep it in version control;
- run a pipeline on any machine without the web app.
Open the YAML tab¶
In the pipeline editor, switch from Canvas to YAML in the tabs above the canvas. The text is generated from the canvas and updates as you edit the canvas, until you start typing in it.
Buttons above the text:
- Copy YAML copies it to the clipboard.
- Download saves it as
<pipeline-name>.yaml. - Apply YAML replaces the canvas with your edited text (see Edit and apply).
- Discard edits throws away your changes and shows the canvas's YAML again.
A run keeps the YAML it used: open the run page, Spec tab, Graph (YAML) (read-only).
The format¶
# Tuneline Studio pipeline. Import it on the canvas or run it with: tuneline run-local pipeline.yaml
name: <pipeline name>
description: <optional description>
nodes:
<step id>:
type: <block type>
label: <optional display name>
needs:
<input port>: <other step id>.<output port>
with:
<setting>: <value>
at: [ <x>, <y> ]
| Key | Meaning |
|---|---|
name, description |
The pipeline's name and description. |
nodes |
One entry per step, keyed by the step id (for example sft). Ids start with a lowercase letter and use a-z, 0-9 and _, up to 40 characters. They are the names you see in logs and use in quality gate rules. |
type |
The block type, for example data.load, train.sft, eval.golden, eval.gate. The block reference lists every type with its ports and settings. |
label |
Optional. The name shown on the canvas when you renamed the step. |
needs |
The step's incoming links: each input port and the step.port output it is connected to. For example train: split.train connects the Train output of the split step to this step's Training data input. Each input takes one link. |
with |
Settings. Only settings that differ from the block's defaults are written; anything left out uses the default. |
at |
Position on the canvas, [x, y] in pixels. Optional: steps without it are laid out in a grid. |
Steps are written in the order they run (inputs before the steps that use them). The comment on the first line is informational and names the command that runs the file on your own machine, tuneline run-local (see below).
Placeholders¶
Text settings can contain placeholders that are filled in when the pipeline runs:
{pipeline}: the pipeline's name as a short slug, for examplesanctions-alert-triage. Used by default in repository and endpoint names.{run}: the run number.{app_url}: the address of the Tuneline Studio app, for example in the sample dataset URLs of the templates.
Put quotes around values that start with {, as in the example below: in YAML, an unquoted { starts a mapping.
A complete example¶
This is the YAML tab of a pipeline created from the CPU smoke test (no GPU needed) template. It loads 60 sample chats, trains SmolLM2-135M-Instruct with LoRA for 20 steps and scores it with ROUGE-L:
# Tuneline Studio pipeline. Import it on the canvas or run it with: tuneline run-local pipeline.yaml
name: CPU smoke test (no GPU needed)
description: Trains a 135M-parameter model for 20 steps on 60 sample chats. Runs on any computer in
a few minutes, to check your setup end to end.
nodes:
load:
type: data.load
with:
source: url
url: "{app_url}/samples/tiny-chat.jsonl"
at: [ 40, 40 ]
chat:
type: data.to_chat
needs:
data: load.data
with:
input_format: messages
at: [ 40, 170 ]
base:
type: model.base
with:
repo_id: HuggingFaceTB/SmolLM2-135M-Instruct
at: [ 320, 170 ]
split:
type: data.split
needs:
data: chat.data
with:
validation_size: 0.0
at: [ 40, 300 ]
sft:
type: train.sft
needs:
train: split.train
model: base.model
with:
method: lora
lora_r: 8
lora_alpha: 16
max_steps: 20
max_seq_length: 256
per_device_train_batch_size: 1
gradient_accumulation_steps: 1
gradient_checkpointing: false
precision: fp32
push_to_hub: false
at: [ 320, 430 ]
eval:
type: eval.golden
needs:
test: split.test
model: sft.model
with:
metrics:
- rouge_l
max_samples: 6
max_new_tokens: 48
at: [ 40, 560 ]
Things to notice:
splitonly listsvalidation_size, because its other settings (test share 0.1, seed 42) are the defaults.sftneeds two links: training data fromsplit.trainand the model frombase.model. Its optional validation input is not connected, so it is not listed.push_to_hub: falsekeeps the adapter on the machine that trained it, so this pipeline needs no Hugging Face key.
Edit and apply¶
- Edit the text in the YAML tab. Apply YAML becomes active as soon as you change something.
- Press Apply YAML.
Tuneline Studio then reads the text and checks it with the same rules as the canvas:
- If the text is not valid YAML, you see the error with its line number, for example
Line 12: ..., and nothing changes. A file without anodessection gives "YAML must have a 'nodes' mapping". - If the pipeline has problems, you see "This YAML has problems the canvas will show after applying:" with the list. Press Keep editing to fix them first, or Apply anyway to load it and fix them on the canvas.
- Otherwise the canvas is replaced and you see "Canvas updated from the YAML".
Applying replaces the whole canvas, and the pipeline takes the name and description from the YAML. Press Ctrl+Z on the canvas to undo it.
Typical problems and what they mean:
| Message | Fix |
|---|---|
sft: unknown node type 'train.sfft' |
Check the type against the block reference. |
Node id 'Split' must start with a letter and use a-z, 0-9 or _ |
Use lowercase ids such as split. |
sft has no input 'data' |
The port name after needs: is wrong. Training blocks call it train. |
sft.train expects ChatDataset, but load.data gives Dataset. Add a 'Format as chat' node between them. |
Insert a data.to_chat step. |
eval: input 'Test data' is not connected |
Add the missing link under needs. |
gate: cannot read rule 'accuracy is high' (use e.g. 'exact_match >= 0.9') |
Quality gate rules are metric operator number. See quality gates. |
The pipeline has a loop. Links must flow one way. |
A step (indirectly) needs its own output. |
To start a new pipeline from a YAML file, create a pipeline from the Blank canvas template, open the YAML tab, paste the file and press Apply YAML.
Note
Settings that point to things in your account, such as an uploaded dataset (dataset_version_id), a golden set (eval_set_id) or a registered model (model_version_id), are ids that only exist in the account that created them. After importing a pipeline from someone else, pick your own dataset, golden set or model in those steps.
Run a pipeline from the command line¶
The Tuneline runner can run a pipeline YAML file on your own machine, without the web app and without an account:
The runner is installed when you connect a computer in Settings → Your computers (it lives in ~/.tuneline/venv; on Windows, %USERPROFILE%\.tuneline\venv\Scripts\tuneline.exe). See Your own computer and the runner CLI reference.
Options:
| Option | What it does |
|---|---|
--set node.param=value |
Overrides one setting, for example --set base.repo_id=Qwen/Qwen3-0.6B or --set sft.max_steps=50. Repeat it for several settings. |
--dataset ID=FILE |
Uses a local file for an uploaded dataset: ID is the dataset_version_id in the YAML. Repeat it for several datasets. |
--app-url URL |
The value of {app_url}, for example https://tuneline-studio.vercel.app so the templates can download their sample data. Defaults to the TUNELINE_APP_URL environment variable. |
--events FILE |
Also writes every event (logs, metrics, step statuses, artifacts) to a JSON Lines file. |
--workdir DIR |
Where to keep downloads and outputs. Defaults to TUNELINE_WORKDIR or ~/.cache/tuneline. |
--quiet |
Prints the log lines only. |
For example, to run the smoke test above with a different base model:
tuneline run-local cpu-smoke-test.yaml \
--app-url https://tuneline-studio.vercel.app \
--set base.repo_id=HuggingFaceTB/SmolLM2-360M-Instruct
The runner checks the pipeline first (the same checks as the canvas) and stops with "The pipeline is not valid:" and the list of problems if something is wrong. Otherwise it prints the log as the steps run and, at the end, the outputs of each step. It exits with code 0 when the run succeeded and 1 otherwise, so you can use it in scripts.
Differences from runs started in the web app:
- Keys come from environment variables, not from Settings: for example
HF_TOKENfor Hugging Face,OPENAI_COMPAT_API_KEYandOPENAI_COMPAT_BASE_URLfor an OpenAI-compatible API,WANDB_API_KEYfor Weights & Biases. - Nothing is cached between runs, and nothing appears on the Runs page.
- Steps that push to Hugging Face still push to the account of
HF_TOKEN.