llm_sft: conversations
Supervised fine-tuning teaches a model to answer the way your conversations answer. Use it when you have dialogues, one turn or many, whose assistant turns are the replies you want. The model learns every assistant turn and only those: user and system turns are context.
Rows
{"messages": [{"role": "user", "content": "What is 9 plus 2?"}, {"role": "assistant", "content": "9 plus 2 is 11."}]}
A row may start with a system turn, holds any number of user and assistant turns, and ends with an assistant turn. The base model's chat template
formats them, so a Qwen3 model and a Qwen3.5 model see their own format.
Config
configs/llm/sft.yaml
# Supervised fine-tuning on conversations: the loss is on every assistant turn.
# As shipped this is a minutes-long pilot on the sample rows; point `data.sources` at your rows and drop `max_steps`.
pipeline:
recipe: llm_sft
name: sft-qwen3.5-0.8b
seed: 20260920
output_dir: ./output
# stages: [data] # default: data, train, validate
model:
architecture: hybrid # Qwen3.5: linear-attention + full-attention layers, vision tower frozen
name: Qwen/Qwen3.5-0.8B # or Qwen/Qwen3.5-2B @ 15852e8c16360a2fea060d615a32b45270f8a8fc
revision: 2fc06364715b967f1860aea9cf38778875588b17
data:
sources:
- name: local_jsonl
path: samples/llm_sft.jsonl # rows: {"messages": [{"role": ..., "content": ...}, ...]}
validation: 0.1
training: {epochs: 1, lr: 1.0e-5, batch_size: 4, accumulation: 2, max_length: 512, max_steps: 4}
validation:
max: {loss: 5.0} # the validate stage fails the run above this held-out loss
configs/llm/sft_transformer.yaml is the same recipe on Qwen3-0.6B, and configs/llm/sft_lora.yaml trains a LoRA
adapter instead of every weight.
Use
uv run llmclick run configs/llm/sft.yaml
- Gate:
validation.max: {loss: ...}on the held-out conversations;perplexityis reported too. - Output:
output/sft-qwen3.5-0.8b-<hash>/validate/checkpoint, asave_pretraineddirectory with its tokenizer. - Next: score it on your rows with
evaluation_customand against the base model withevaluation_compare.
Source: configs/llm/sft.yaml. This page is generated; edit the source and run npm run sync.