Train a first model
This page shows how to train your first model with supervised fine-tuning. You then evaluate the model and read its score. The data and descriptors come from the support triage example, which classifies a support message as one of 77 intents.
Before you begin, deploy a trainer in your Akka project, then install and authenticate the akka CLI. For more information, see Akka Optimize CLI.
Prepare the data
Training examples use chat-format JSONL. Each line contains one JSON object with messages in the system, user, and assistant roles. Supervised fine-tuning teaches the model to produce the assistant message. The following example shows one training row:
{"messages":[
{"role":"system","content":"Classify the support message. Answer with JSON: {\"intent\": ...}"},
{"role":"user","content":"My card still has not arrived."},
{"role":"assistant","content":"{\"intent\":\"card_arrival\"}"}
]}
Write a training file and an evaluation file from separate rows. The model is scored on the evaluation file, so don’t include any of its rows in the training file. The example’s prepare_dataset.py writes both files. Run the following command in the example directory:
python3 prepare_dataset.py --rows "$ROWS" --eval-rows "$EVAL_ROWS"
Register the datasets
To register the files, run:
akka-optimize datasets create -f data/train.jsonl --name support-triage-train
akka-optimize datasets create -f data/eval-tuned.jsonl --name support-triage-eval
akka-optimize datasets create -f data/eval-frontier.jsonl --name support-triage-eval-frontier
Each command prints the dataset’s content hash. The name is an alias for that hash. The third file is for scoring an untuned model; see Compare with the base model.
Create the workload
A workload specifies the evaluation dataset and grader for every candidate for this task. The default grader, json-label-match, compares the fields of a JSON answer with those of the expected answer.
To create the workload, run:
akka-optimize training workloads create support-triage --dataset support-triage-eval --grader json-label-match
Select the base model
A run can use only a base model that the deployment allows and that someone has selected. List the allowed models, then select the model for this example:
akka-optimize training base-models list
akka-optimize training base-models select unsloth/Llama-3.2-1B-Instruct --wait
Selecting a model registers it and, if the deployment supports shared caching, caches its weights. The --wait option waits until the model is ready. Without this option, the command returns immediately, and the run waits for the model if necessary. For more information, see Base models.
Start a run
A run descriptor specifies the workload, selected base model, and training configuration. The example’s run.json contains the following descriptor:
{
"kind": "run",
"workload": "support-triage",
"baseModel": "unsloth/Llama-3.2-1B-Instruct",
"config": {
"dataset": "support-triage-train",
"method": "sft",
"hyperparams": {"lora": {"rank": 8}, "optimizer": {"learningRate": 0.0001}, "training": {"epochs": 2}},
"maxSeqLength": 2048,
"model": {"precision": "BF16"}
},
"execution": {"gpus": 1, "saveEvery": 20, "keepAdapters": 4},
"description": "two epochs at rank 8",
"configName": "r8-e2"
}
Validate the descriptor, then start the run and follow it to completion:
akka-optimize training runs start -f run.json --dry-run
akka-optimize training runs start -f run.json --wait --exit-status
--dry-run validates the descriptor against the service without training. --wait follows the run. If you interrupt the command, the run continues training. Use training runs wait RUN_ID to reconnect to it.
A completed run registers its model. Read the run to find the model:
akka-optimize training runs get RUN_ID
Replace RUN_ID with the run ID that training runs start printed.
Evaluate the model
Score the model on the evaluation dataset, then read the report:
akka-optimize training evaluations start --model MODEL_ID --dataset support-triage-eval --wait --exit-status
akka-optimize training evaluations report EVALUATION_ID
Replace the following:
-
MODEL_ID: the model ID from the run detail. -
EVALUATION_ID: the evaluation ID thattraining evaluations startprinted.
The report shows the mean score and the number of unscored examples. training evaluations predictions EVALUATION_ID lists each predicted answer with its expected answer.
Compare with the base model
To measure the effect of training, score the untuned base model on the same rows. The example’s base-model.json registers the model as a baseline:
{
"servingModel": {
"variant": "BASE",
"baseModel": "unsloth/Llama-3.2-1B-Instruct",
"revision": "5a8abab4a5d6f164389b1079fb721cfab8d7126c"
}
}
An untuned model needs the list of intents in every request. The baseline is therefore scored on support-triage-eval-frontier, which contains the same rows with that longer prompt. Register and score the baseline:
BASE=$(akka-optimize trained-models register -f base-model.json -o json --jq .modelId)
BASELINE=$(akka-optimize training evaluations start --model "$BASE" \
--dataset support-triage-eval-frontier --workload support-triage -o json --jq .evaluationId)
akka-optimize training evaluations wait "$BASELINE" --exit-status
Read both scores:
akka-optimize training workloads scores support-triage
akka-optimize training evaluations report "$BASELINE"
workloads scores tabulates the scores of every configuration under the workload’s evaluation settings. The baseline uses a different dataset, so read its report separately.
Next steps
-
For every field of a run descriptor and the reinforcement methods, see Training runs.
-
For metrics, hyperparameters, and TensorBoard while a run trains, see Observe a run.
-
For complete worked examples, see Cookbook.