Fine-tune a model
Sign in, load labeled conversations, create an SFT Training, review the cost, and start one Training Run.
Adapt a catalog model to labeled conversations with toloka. A Training is an editable draft. A Training Run is one billed execution. The first run creates the output Model from the Training name and publishes an immutable Model Version.
Copy IDs from command output into the next command. Do not invent them.
Before you start
Section titled “Before you start”You need:
- A supported standalone CLI system: macOS or glibc Linux on ARM64 or x64. Native Windows and musl Linux releases are not available yet. The CLI includes its runtime; see CLI installation.
- A Toloka account on a team. You sign in through your browser; only automation without a browser needs an API key from the Business Console (Company → API keys → Generate API key). See Manage your team and balance.
- A team with a funded balance. Cost estimation is free. Starting a Training Run charges up to the printed maximum charge.
- Labeled conversations. Use the file in Step 3, or your own rows in the same shape.
For prompt compression, see Compress a prompt with gisting.
Step 1 — Install and sign in
Section titled “Step 1 — Install and sign in”curl -fsSL https://platform.toloka.ai/cli/install.sh | shtoloka version --jsontoloka logintoloka whoamiUse the latest CLI release. This CLI-only workflow does not import the SDK and needs no separate runtime. For updates, PATH fixes, and migration, see Updates and migration from Bun global installs. There is no toloka update command; rerun the installer for an immediate update.
login asks how you want to sign in and opens your browser on the Toloka login page. whoami prints the platform URL, the account you signed in with, and Reachable: N project(s) visible.
Step 2 — Create or select a project
Section titled “Step 2 — Create or select a project”The Training, dataset, billing, and resulting Model belong to one project.
toloka project listtoloka project create fine-tuning --name "Support ticket SFT"toloka project currentproject create prints Created project pp.… as fine-tuning. If you have more than one team, pass --team-id. To reuse an existing project:
toloka project add support-sft pp.YOUR_PROJECT_IDtoloka project switch support-sftStep 3 — Put labeled conversations in a dataset
Section titled “Step 3 — Put labeled conversations in a dataset”Each row is a chat. The last turn must be assistant, and at least one turn must be user. Save this file as support-tickets.jsonl:
{"messages":[{"role":"user","content":"Hi, how do I reset my password? I can't find the option anywhere."},{"role":"assistant","content":"question"}]}{"messages":[{"role":"user","content":"This is the third time my order arrived damaged. I'm furious."},{"role":"assistant","content":"complaint"}]}{"messages":[{"role":"user","content":"Just wanted to say your support team was incredibly helpful today, thank you!"},{"role":"assistant","content":"praise"}]}{"messages":[{"role":"user","content":"What are your business hours on weekends?"},{"role":"assistant","content":"question"}]}{"messages":[{"role":"user","content":"The app keeps crashing every time I open the checkout page. Please fix this."},{"role":"assistant","content":"complaint"}]}{"messages":[{"role":"user","content":"Amazing product, it has saved me hours every week. Great job!"},{"role":"assistant","content":"praise"}]}{"messages":[{"role":"user","content":"Can I change the shipping address after placing an order?"},{"role":"assistant","content":"question"}]}{"messages":[{"role":"user","content":"I was charged twice for the same subscription and nobody is responding."},{"role":"assistant","content":"complaint"}]}{"messages":[{"role":"user","content":"Do you offer student discounts?"},{"role":"assistant","content":"question"}]}{"messages":[{"role":"user","content":"The new dashboard update is fantastic, much easier to use now."},{"role":"assistant","content":"praise"}]}Do not split the file yourself. A split column on the dataset puts each row in a part: the Training learns on the train part, validates on the validate part, and never uses the test part, which stays held out so you can evaluate the model on it later. Step 5 creates that column for you.
Create the dataset, then append the rows:
toloka dataset create support-ticketsThen:
toloka dataset upload support-tickets ./support-tickets.jsonl# Uploaded 10 rows to dataset support-tickets.Step 4 — Choose a base model
Section titled “Step 4 — Choose a base model”toloka base-model listThe catalog currently includes qwen3-4b, qwen3-8b, qwen3-32b, and qwen3-235b. This page uses qwen3-8b. The printed ID is what --base-model accepts.
To continue training a model you already fine-tuned, pick one of its Model Versions instead of a catalog entry. The source must be a LoRA adapter Model Version from the same project (one produced by fine-tuning); a full-weights version is rejected. Find the id with:
toloka model versions "Your model name"Step 5 — Create the Training draft
Section titled “Step 5 — Create the Training draft”SFT is the default method. Do not pass --method. Pass the dataset from Step 3:
toloka training create "Support ticket SFT" \ --base-model qwen3-8b \ --dataset support-tickets# Split support-tickets by column split: placed 10 rows, 0 kept their part.# Froze slice Support ticket SFT (dsl.…) with 10 rows.# Created training trg.…--dataset puts every row that has no part yet into train, validate or test (80/10/10, in a new split column), freezes the rows into a slice named after the Training, and trains on that slice. Of the 10 rows, 8 train, 1 validates, and 1 is held out for testing. A slice never changes, so every run of this Training learns on the same rows, and you can always tell which rows a model learned from. To choose other shares or balance the parts by a label, run toloka dataset split support-tickets --ratios 70/10/20 --balance-by <label-column> first; to train on a slice you froze yourself, pass --slice <slice-id>. See Split a dataset and freeze a slice.
When the dataset already has a split column, for example from an earlier Training, --dataset keeps every row’s part, places only rows added since, and freezes a new slice for this Training:
# Split support-tickets by column split: placed 0 rows, 10 kept their part.# Froze slice … (dsl.…) with 10 rows.To warm-start from an existing Model Version, pass --model-version instead of --base-model — training then continues from those adapter weights rather than a fresh initialization. Pass the slice the first Training froze, shown by toloka training get, so both learn on the same rows:
toloka training create "Support ticket SFT v2" \ --model-version mdv.YOUR_VERSION_ID \ --slice dsl.YOUR_SLICE_ID# Created training trg.…The first run still creates a new output Model; the source Version is only the training parent.
Confirm the draft:
toloka training get trg.YOUR_TRAINING_IDThe table shows Method as Supervised fine-tuning (SFT), the Slice and Split column it learns on, and Output Model as - until the first run publishes one.
--lora-rank 8|16|32, --epochs 1..5, --learning-rate, --batch-size 8|16|32|64, and --max-sequence-length 64..16384 set the SFT hyperparameters. Omit them to take the defaults: rank 16, 3 epochs, learning rate 0.00015, batch size 8, and 12,288 tokens. See Base models and settings.
Step 6 — Review the cost
Section titled “Step 6 — Review the cost”toloka training cost trg.YOUR_TRAINING_IDThe command prints a table with training rows, tokens, maximum GPU seconds, and Maximum charge. When a split column now puts rows of the train part in a test part, a Left out as test row says how many; they stay out of training. The test part of the Training’s own split column is never in the train part, so it is not counted there. If the estimate is blocked, the command exits with code 1 and prints Training cannot run with these inputs: followed by one - <message> line per problem. Fix each and calculate again. With --json, a blocked estimate writes nothing to stdout.
Step 7 — Start the Training Run
Section titled “Step 7 — Start the Training Run”toloka training run trg.YOUR_TRAINING_IDThe command calculates a fresh ready estimate and names the Model Version after the Training (Support ticket SFT). Copy the Training Run id (trn.…).
toloka training status trn.YOUR_RUN_IDtoloka training logs trn.YOUR_RUN_IDtoloka training metrics trn.YOUR_RUN_IDStatus values include queued, running, stopping, blocked, completed, failed, and canceled. If the run is blocked, restore billing and run toloka training resume trn.YOUR_RUN_ID. While the run is running, the Progress row shows the stage inside the run; queued or pending there means the run is waiting for GPU capacity and has not started training yet.
A run can train longer than the estimate predicted. It stays running, the charge stays capped at the maximum charge you approved, and the Model Version is published when training finishes. Do not start a second run because the first one is slower than estimated. A run that fails because of the platform is not charged: the whole hold returns to the team balance, even though training status still shows the GPU seconds it used. When its error says retryable: true, run toloka training run again with the same --estimate-file: a failed run frees its estimate, and the maximum charge stays the same.
training metrics lists the latest value of every metric the run has reported — training loss, learning rate, and the evaluation metrics for the method. Values appear while the run is still training, so you can watch the loss fall instead of waiting for the run to end. Add --key train/loss to print the point history of one metric instead of the summary. A history is returned thinned to --resolution points — 200 by default, between 2 and 500 — and a run longer than that keeps its most recent points, so a thinned or trimmed series says so under the table.
Step 8 — Use the trained model
Section titled “Step 8 — Use the trained model”When status is completed, the table shows the Model Version. The Training now names its output Model:
toloka training get trg.YOUR_TRAINING_IDtoloka model versions mdl.YOUR_MODEL_IDDownload the files. Copy the Model Version id (mdv.…) from the table:
toloka model version download mdv.YOUR_VERSION_ID --out ./support-ticket-sft# Downloaded Model Version mdv.… revision 1 to /…/support-ticket-sftYou trained the model. To test it, deploy it. You can use our partner, Nebius.
If something fails
Section titled “If something fails”| What you see | What it means | What to do |
|---|---|---|
Not logged in. Run toloka login once to sign in through your browser on this machine: | No login is in effect. | Run toloka login, or set TOLOKA_API_KEY. |
No project selected. Run toloka project create for a new project, toloka project add for an existing project, or cd into a checkout. | No project is selected. | toloka project create, toloka project add, or pass --project-id. |
Dataset "…" does not exist … no pipeline in source declares it. | The dataset has to exist before rows can be uploaded. | Run toloka dataset create <name>, then upload again. |
--dataset or --slice is required. | The Training names no rows to learn on. | Pass --dataset <dataset> to split it and freeze a slice, or --slice <slice-id>. |
Slice dsl.… freezes no split column | The slice was frozen before the dataset had a split column. | Pass --dataset <dataset>, or run toloka dataset split <dataset>, take a new slice, and pass it. |
Choose exactly one of --base-model and --model-version. | Both source flags were set, or neither was. | Pass one. |
Training from a Model Version requires a LoRA adapter source | --model-version points at full weights. Warm start continues a LoRA adapter Model Version only. | Pass a Model Version produced by fine-tuning, or --base-model. |
Training cannot run with these inputs: | The cost estimate is blocked. The command exits with code 1. | Read each - <message>, fix inputs, calculate again. |
This Training would take up to … hours … which exceeds the 6-hour limit. | The estimated wall time is over the 6-hour limit. | Use qwen3-32b or qwen3-235b (8 GPUs), or reduce rows or epochs. |
A Model Version with this name already exists | A previous run already used this Training name as the version name. | Pass --version-name with a new name. |
status is blocked | Funds or payment stopped the run. | Restore billing, then toloka training resume. |
Another upload is already in progress. Complete or cancel it before starting a new one. | A previous upload to that dataset is still pending. The CLI cannot cancel it. | Wait for it, or upload to a new dataset. |
Related
Section titled “Related”- Train your first model — the same commands as a guided first run
- Training — how Trainings, cost estimates, Training Runs, and Model Versions fit together
- CLI — install, sign in, and project selection
- Compress a prompt with gisting — the gisting method on the same Training commands
- Create and manage datasets — creating a dataset on the Datasets page
- Pricing and billing — how the team balance is drawn down