Skip to content

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 example sanctions-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:

  • split only lists validation_size, because its other settings (test share 0.1, seed 42) are the defaults.
  • sft needs two links: training data from split.train and the model from base.model. Its optional validation input is not connected, so it is not listed.
  • push_to_hub: false keeps the adapter on the machine that trained it, so this pipeline needs no Hugging Face key.

Edit and apply

  1. Edit the text in the YAML tab. Apply YAML becomes active as soon as you change something.
  2. 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 a nodes section 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:

tuneline run-local pipeline.yaml

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_TOKEN for Hugging Face, OPENAI_COMPAT_API_KEY and OPENAI_COMPAT_BASE_URL for an OpenAI-compatible API, WANDB_API_KEY for 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.