0.9.0

Headlines

Train on preference pairs

A dpo run trains an adapter on a preference dataset, a prompt with a chosen and a rejected answer on each line, from a base model or from a supervised run’s adapter. See Direct preference optimization.

Distill a teacher model into a dataset

akka training distillations runs a teacher model over a chat dataset and registers its accepted answers as a new chat dataset, ready to train on. A teacher that answers with tool calls produces rows that train those calls.

Check row lengths before a GPU is claimed

training datasets analyze measures a dataset under a base model’s tokenizer and chat template without a GPU. A run reads that analysis to refuse, trim or leave out rows longer than maxSeqLength before it claims a GPU, and a dry run shows the lengths. See Row lengths.

Changes

  • Train outside measured envelopes. Training envelopes are advisory by default. Optimize admits an unmeasured run with a warning that it may run out of device memory. The dry run, start response and training runs get show the warning, and the run keeps it if the catalog changes. training base-models get and training capacity label the envelopes as measurements. Set trainer.base-model-catalog.strict-envelopes = true in the applied catalog to require measured envelopes. Engine, host memory, device layout and deployment GPU limits still apply. A model allowed for serving only cannot train. See Measured training envelopes.

  • A reinforcement run that sets rlHyperparams but omits klBeta or temperature trains with the default of 0.04 or 0.7. Previously, an omitted klBeta or temperature trained with 0, which turned off the KL penalty and sampled greedily. akka training runs get --settings shows both values on a new Rollouts line.

  • A pause sent again with the same --checkpoint while the run is still pausing answers with the pause in progress: akka training runs pause says the run is already pausing, and POST /v1/training/runs/{id}/pause answers 200 rather than 202. A pause with another --checkpoint is refused. Previously, the CLI reported that it had submitted a new pause.

  • A resumed run shows its own attempt. It reads as PREPARING until its first training step, akka training runs wait no longer reports the earlier pause on every line, and cancelling it leaves the earlier pause as it ended. Previously, a resumed run showed the earlier attempt’s progress, step and pause.

  • A pause no longer waits for every save a run has queued for upload. When a run saves faster than it uploads, a save with a newer one queued behind it uploads only its adapter weights, and when the run pauses or stops, the queued saves between the upload in progress and the newest are skipped. The newest save and each epoch’s save upload in full. A run also uploads a save with its training state after at most 10 saves, or 5 minutes after the last such save finished uploading, whichever comes first, and skips the saves waiting before it other than epoch saves, so a run that falls behind on its uploads still has a recent save it can resume from. Set execution.resumableSaveEvery and execution.resumableSaveMinutes to change either bound. A save uploaded with only its weights can be registered as a candidate or branched from as an adapter, but a run cannot resume from it. akka training runs get shows how many saves are waiting to upload and how many were skipped. Previously, a pause waited until every queued save had uploaded.

  • A latest pause resumes from the newest save that holds training state, including one the run committed while it stopped, on every engine. Previously, a run could resume from the save it held when the pause was requested and train the updates after it again.

  • When the devices available to Optimize change, waiting work that the devices can never hold fails with the reason, rather than waiting.

  • Optimize sends the current status first when you follow a run, evaluation, pipeline or curation with wait or its /events stream. Changes made while Optimize reads that status can appear in later updates. Changes can still be missed while the follow opens or if delivery fails.

  • Some models are allowed for serving only. You can serve such a model from an endpoint, evaluate it, and use it as a distillation teacher, and Optimize refuses a run over it with the reason. An endpoint, evaluation or distillation over such a model runs on one GPU a replica, and a distillation’s --max-model-length can be at most the context the model is served at. akka training base-models get shows Allowed for: serving only and the devices the model is served on. See Base models.

  • google/gemma-4-26B-A4B-it is allowed for serving only in 0.9.0. Its training envelopes are commented out in the shipped catalogs. You can serve it from an endpoint, evaluate it, and use it as a distillation teacher. Its endpoints serve tool calls with the gemma4 parser. Optimize refuses a training run over it, including under advisory envelopes. Optimize also refuses lora.adaptExperts: true. The serving engine does not apply an adapter’s expert weights for Gemma 4. akka training base-models get shows its active parameters beside its total. See Base models.

  • Train on preference pairs. A dpo run trains an adapter on a preference dataset, a prompt with a chosen and a rejected answer on each line, from a base model or from a supervised run’s adapter through a weights branch. It takes preference.beta (default 0.1) and preference.lossType (sigmoid, the default, or ipo), and trains on one GPU under TRL. An advisory catalog admits an unmeasured dpo run with a warning. A strict catalog requires a matching dpo measurement. A dpo run recomputes activations in the backward pass unless its config sets model.gradientCheckpointing to false. training datasets analyze measures a preference dataset in pairs, where a pair’s length is the longer of the prompt with each answer. Under data.truncation: error, Optimize refuses a dpo run with a pair longer than maxSeqLength before it claims a GPU, or at submission where an analysis is already done, and the dry run’s Lengths section counts pairs. Under error and drop, Optimize also refuses a dpo run whose analysis found a pair the chat template cannot render after its prompt, naming the pair. Where a pass holds more than one pair, which by default is at a maxSeqLength of 1024 or less, a dpo run computes its loss with Liger’s fused kernel, so the logits of every pair in a pass but one are not held in device memory. preference.fusedLoss: false keeps a run on TRL’s own loss. training runs get shows the run’s preference accuracy and reward margin, and which loss it used, and training runs metrics shows the accuracy and margin for each step. See Direct preference optimization.

  • Leave long rows out. data.truncation: drop leaves rows longer than maxSeqLength out of both training and validation, for chat datasets with or without images. The run reports the number of training rows left out as dataFit.tooLong. When the count is positive, training runs get shows it on the Data fit line. Optimize refuses drop with a smoke check, and where it would leave a dataset empty. See Data.

  • Trim the oldest turns. With data.truncation: oldest, Optimize removes whole turns, oldest first, until the conversation fits maxSeqLength. A turn is a user message and the messages after it up to the next user message, and anything before the first user message is a turn of its own. Optimize keeps the system prompt and the final turn, so the final answer is still trained, and removes a tool call and its result together. Under assistantTurns: all, the answers of the removed turns are not trained. Optimize refuses a row that does not fit however many earlier turns it removes, and names it. data.truncation: oldest_or_drop leaves such a row out instead. Both apply to training and validation. Optimize reports training rows trimmed as dataFit.trimmed and turns removed as dataFit.turnsRemoved. When rows were trimmed, Optimize shows both counts on the Data fit line of training runs get. Optimize refuses both values for a dataset with images, a dataset of prepared token rows, and a smoke check. Under both values, Optimize refuses a long row carrying the column named by loss.explicitLossMaskColumn. The mask covers the whole conversation. See Data.

  • Analyze a dataset. training datasets analyze DATASET --model BASE_MODEL measures a dataset under the base model’s tokenizer and chat template without a GPU. It reports the tokenizer and template the figures came from, the median, 90th percentile, 99th percentile and longest row lengths, the rows over each common limit, the longest rows, a suggested maxSeqLength, and the tokens the default loss policy and assistantTurns: all train. Optimize keeps one analysis for each set of examples, base model commit and Optimize version, so two dataset versions or names that hold the same examples share one analysis. With -f, the command estimates the steps and time of the run file’s config and execution, and names whether each value came from the file or the defaults. The base model is then the run file’s baseModel unless --model is given, and Optimize refuses a --model that names another one. --wait waits for the report. In the API, POST /v1/training/datasets/analyses starts an analysis or reads the one already kept, and adds the estimates once it is done. GET /v1/training/datasets/analyses/{analysisId} reads its status and measurements, without estimates. See Analyze a dataset.

  • Long rows refused before a GPU. Under data.truncation: error, Optimize checks a supervised run’s rows against maxSeqLength before it claims a GPU and refuses the run with the long rows named. The check reads a dataset analysis of the run’s training and validation datasets under the run’s base model. If an analysis is already done, Optimize refuses the run at submission, and a dry run reports the same refusal. The refusal names up to 20 rows, longest first, with their lengths, and the analysis and base model commit that measured them. If the check cannot complete, Optimize records that it did not run, and the run still refuses a long row when it reads it. training runs get and the API’s lengthCheck show the analysis that each dataset was checked against. See Row lengths.

  • Row lengths in a dry run. training runs start --dry-run shows the row lengths of a supervised run’s training and validation datasets against the run’s maxSeqLength, in a Lengths section. With a completed dataset analysis for the same examples, base model commit and Optimize version, Optimize names the analysis, the tokenizer, chat template and Optimize version the figures came from, and shows the row count, the median, 90th percentile, 99th percentile and longest row lengths, the rows longer than maxSeqLength, and the suggested maxSeqLength. For a smoke check, Optimize counts only the training rows in its slice. It counts every validation row. When no analysis exists, Optimize shows the training datasets analyze DATASET --model BASE_MODEL command that starts one. If Optimize cannot read the analysis status, it explains why and shows no command. For an analysis that is still pending or running, Optimize names it. For a failed analysis, Optimize gives the reason, and shows the command only if another attempt could succeed. If the base model resolves to no commit, Optimize says so and shows no command. Optimize does not start an analysis during a dry run. For prepared token rows, Optimize shows the longest row recorded by the dataset version. In the API, resolved.lengths carries the same figures. See Row lengths in a dry run.

  • Rows that cannot fit even trimmed, before a GPU. A dataset analysis also records each row’s trimmed length. Optimize measures the shortest length each row longer than 512 tokens reaches with its oldest turns removed. For shorter rows, Optimize records the whole length. training datasets analyze shows, for each common limit, how many of the rows over it are still over with their oldest turns removed. Under data.truncation: oldest, Optimize checks a supervised run’s rows by their trimmed lengths before it claims a GPU, and refuses the run for the rows that cannot fit even trimmed. The refusal names the rows, their trimmed lengths and the analysis that measured them, and suggests a larger maxSeqLength, shorter rows or oldest_or_drop. If an analysis is already done, Optimize refuses the run at submission, and a dry run reports the same refusal. Under oldest_or_drop, Optimize refuses no row for its length. Under both values, the dry run’s Lengths section shows how many long rows the run trims and how many cannot fit even trimmed. Optimize refuses these rows under oldest. Under oldest_or_drop, Optimize leaves them out unless their mask or their tool calls cause a refusal. Where the run sets loss.explicitLossMaskColumn, the analysis cannot tell which long rows carry the mask, and the run refuses those rows when it reads them. See Row lengths.

  • Register large datasets. A chat or preference dataset version can hold its examples in ordered shards, examples-00000.jsonl onwards, instead of one examples.jsonl. A version holds at most 1,000 shards of at most 256 MiB each, and each shard holds at least one example. akka registry datasets register cuts a JSONL file over 256 MiB into shards of up to 256 MiB on line boundaries, sends them one at a time, and registers them as one version. --shard-size cuts at another size, and sends a smaller file in shards too. The cut depends only on the file and the shard size, so the same file registers as the same version on every deployment. If the upload stops, run the same command again within 7 days: it sends only the shards the registry does not hold. akka registry info shows the deployment’s upload and shard limits, and register refuses a file that does not fit them before it sends anything, naming the --shard-size that does. In the API, an upload session at /v1/registry/dataset-uploads takes the shards, and GET /v1/registry/info reports the limits under datasets. See Register a dataset.

  • A supervised, dpo or reinforcement run, an evaluation, a dataset analysis and a distillation read a dataset version held in shards, as each reads one held in examples.jsonl. A supervised run, an evaluation and a dataset analysis need local disk for the rows of a sharded version rather than memory.

  • Distill a teacher model’s answers into training rows with akka training distillations. Start a distillation of a teacher over a chat dataset, follow its progress and its rejected counts by reason, pause, resume or cancel it, and read the rejected outputs with akka training distillations rejections. A distillation first runs a smoke on one GPU, over the first decisions of the dataset or the ones you name, then generates on one GPU per replica.

  • A distillation assembles its accepted answers into a chat dataset. It registers the dataset under the target name, with the teacher and the source dataset in its lineage, and ends in COMPLETED. akka training distillations get shows the registered dataset, and akka training distillations wait returns once the distillation has ended.

  • Train answers that call tools. A chat row’s final message, its answer, may carry text and tool_calls together and leave its calls unanswered, so a distillation whose teacher answers with a call registers its rows rather than failing in ASSEMBLING. A supervised run trains such an answer whole, its text and its calls, whatever loss.trainOnToolCalls says. Optimize trains Gemma 4 E2B, E4B and 12B under chat templates that render an answer’s text before its calls, the order the model writes them in. A dataset analysis names the rows whose answer the chat template refuses or renders without its text or a call, and Optimize refuses a run over them under every data.truncation value before it claims a GPU. A supervised run on one GPU, and a dpo run, under drop, right or oldest_or_drop now also waits for that analysis before it claims a GPU, for up to 30 minutes by default, and goes on with the check marked as not run if the analysis fails or does not finish. A supervised run on more than one GPU uses the analysis only if one is already done. Evaluations and reinforcement runs compare an answer’s text, so they refuse a row whose answer calls tools, and a smoke check scores only the text answers and says how many it left out. Registration refuses an assistant message whose tool calls share an id. See Conversations and tool calls.

  • Rows that offer tools, before a GPU. The registry counts the rows of a chat or preference version that offer tools when the version is uploaded, and akka registry datasets get shows the count on a Tools line. Optimize refuses a reinforcement run, and an sft run over a dataset with images, when a dataset it reads has rows that offer tools, at submission and in a dry run, and names the engine and the reason. Neither renders a row’s tools, so the run would train unlike evaluation and serving. A pipeline stage over an earlier stage’s dataset is checked when it starts. A version whose content was first uploaded before 0.9.0 shows not counted, and Optimize does not refuse a run over it for its tools. See Conversations and tool calls.

  • Text beside earlier tool calls. Any assistant message in a chat row or a preference prompt may carry text and tool_calls together, so datasets taken from agent traffic, where an agent writes a sentence and calls a tool in the same message, now upload as they happened. Every call before the answer is still answered by a tool message. Under the default loss policy such a message is context. Under loss.assistantTurns: all it trains whole, and with loss.trainOnToolCalls: false its text trains without its calls. A dataset analysis names a row where the chat template refuses such a message, or leaves out its text or one of its calls, and Optimize refuses a run over it before it claims a GPU. A template that leaves out an earlier call is refused the same way, whether or not the message carries text. Gemma 4 E2B, E4B and 12B render these messages as they were written. See Conversations and tool calls.

  • A dry run of akka training runs start reads at most 20,000 examples or 64 MiB of the dataset to report its duplicates and conversation shapes, unless the deployment sets other limits, so a dry run over a large or sharded dataset answers without reading all of it. A dataset within both limits is read whole. Above them, the dry run reads the dataset’s first examples, or the first examples of up to 16 evenly spaced shards, and diagnostics.coverage in the response says how many examples it read, the total where it is known, and that the unread rest may differ. The CLI prints that note before the findings. Previously, a dry run read every example.

  • A GRPO or GSPO run on the trl engine with klBeta above 0 that starts from an adapter, through a warm start or a weights branch, continues from its own training when it is resumed after a pause or a retry. Previously, such a run continued from its warm start’s adapter, and a weights branch continued from a fresh adapter on the base model, so the training before the pause or retry was lost. A GRPO or GSPO run on the trl engine that continues an adapter, through a resumed weights branch or a trainingState branch of a run that started from an adapter, also keeps the alpha, dropout and target modules of that adapter, whatever its klBeta. Previously, it took them from its own rlHyperparams.lora, which for a trainingState branch are its parent’s settings rather than those of the adapter its parent trained. Train such a run that was resumed or branched before 0.9.0 again from its warm start or its parent. Train a run branched from it afterwards again too, because the branch inherited the same weights.

  • A supervised, dpo or reinforcement run on the trl engine reserves device memory close to what it allocates, because its job starts with the allocator setting expandable_segments:True unless the deployment configures another. Previously, a run whose rows varied in length could reserve more than twice what it allocated, and a long run could fail for want of memory it was not using.

  • An endpoint restarts at most once when Optimize is updated, from the update after 0.9.0 on. During the update to 0.9.0, an endpoint can still restart several times.

  • A supervised, dpo or reinforcement run, an evaluation, a dataset analysis and a distillation no longer fail while reading their dataset or scoring bundle when other work on the same training machine had prepared datasets or scoring bundles there before them. Previously, such work could fail with a permission error.

  • Evaluations and endpoints over Gemma 4 E2B, E4B and 12B, and over candidates trained from them, render prompts with the corrected chat template that Optimize trains those models under. An evaluation refuses an inference profile whose chat template is not that one, and names the commit to set as the model’s baseModelRevision. A candidate trained before 0.9.0 is now evaluated and served under the 0.9.0 template. Other models use the chat template their repository ships.

  • A GRPO or GSPO run on the verl engine over Gemma 4 E2B, E4B or 12B renders its rollout prompts with the corrected chat template that Optimize trains the model under, and hands verl each prompt as the run gave it. Previously, verl rendered the prompts with the template the model’s repository ships, and an earlier tool call’s arguments could read back with the argument names of other rows' calls.

  • Evaluations and smoke checks ask the model each row’s prompt with the tools the row offers, as a supervised run trains it. Previously, they asked the prompt without its tools.

  • Evaluations and smoke checks over Gemma 3 and Llama 3.2, smoke checks over Ministral 8B, and evaluations over Ministral 8B that do not run on the vLLM engine ask the model a prompt that starts with one beginning-of-sequence token, as a supervised run trains it. Previously, the prompt started with two.

  • A reinforcement run over a text model renders its prompts with the chat template of the base model commit the run names. Previously, it rendered them under the template of the repository’s latest commit.

  • Reinforcement runs and distillations over Ministral 8B render rows with the tokenizer a supervised run uses. Previously, they loaded Mistral’s own tokenizer, which could tokenize a prompt otherwise than a supervised run does.

  • Evaluations over Ministral 8B on the vLLM engine render and tokenize each prompt with the tokenizer a supervised run uses. Previously, vLLM tokenized the prompt with Mistral’s own tokenizer, which could tokenize it otherwise than a supervised run does.

  • A tool call whose arguments are written as a JSON string is trained, evaluated and distilled as the JSON object the string holds. Previously, a Gemma 4 run refused such a row, and other models trained the string as written.

  • A supervised or reinforcement run, an evaluation and a dataset analysis read each tool call’s arguments and each tool’s definition exactly as the row writes them. Previously, a dataset whose rows wrote them in different shapes could fail to load, or a row could be trained with null values for arguments or fields that only other rows name.

  • A row that offers no tools, in a dataset where other rows offer tools, renders without tools on every model. Previously, a Llama 3.2 run refused such a row when it had a system message, and a dataset analysis measured it with tools.

  • A supervised run over Llama 3.2 that renders each message of a row on its own refuses a row that has a system message and offers tools, and names the row. A run on the verl engine renders each message on its own. So does a run on the trl engine where a row of its datasets has several turns, the run states a loss policy other than the default, or data.truncation is oldest or oldest_or_drop and a row is longer than maxSeqLength. The chat template does not render the system message alone with tools. Any other run on the trl engine trains such a row. Previously, such a run and a dataset analysis of such a row failed with the chat template’s own error.

  • A supervised or dpo run over SmolVLM trains each message’s text in a dataset without images, and a dataset analysis, an evaluation and a distillation over SmolVLM render that text too. Previously, SmolVLM’s chat template rendered every message of such a dataset as an empty turn, so the run trained on turns with no text. Train such a run again.

  • A reinforcement run over SmolVLM renders each prompt’s text in a dataset without images. Previously, some such runs rolled out from prompts whose turns had no text. Train such a run again.

  • A reinforcement run on the verl engine fails before training starts when a prompt leaves fewer than maxCompletionLength tokens of maxSeqLength. The failure says how many prompts are longer than that budget and names the first five such rows, as it does on the trl engine. Previously, the run failed only when verl reached such a prompt, after it had started training.

  • chatTemplateSha256 names the chat template the rows or answers were rendered under, wherever Optimize writes or reads it: a dataset analysis’s provenance, a prepared dataset’s descriptor, and each line of an evaluation’s answers. For the Gemma 4 E2B, E4B and 12B commits that Optimize corrects, that is the corrected template. An evaluation’s answer lines now carry chatTemplateSha256 for a model with a single chat template. Previously, a line carried it only for a corrected template. Each answer line also names the base model commit it was answered from, as baseModelRevision, and a retried evaluation keeps only the answers from the commit it resolves to. An evaluation retried after the update answers its rows again.

  • Because of these changes, an evaluation over Gemma 3, Llama 3.2 or Ministral 8B, or over rows that offer tools, can give other answers and scores than the same evaluation before 0.9.0.

  • Every job that reads chat rows or preference pairs checks each row by the rule the registry applies at upload: supervised, dpo and reinforcement runs, evaluations, dataset analyses and distillations. A job names a row it refuses by its line. A reinforcement run now refuses a row that is not a valid chat example, such as one that does not end in an assistant message. Previously, it left such a row out. A refusal for a row’s length reads the same at submission and when the run reads the row.

  • Register preference datasets. akka registry datasets register takes a file of preference pairs as a preference-jsonl-v1 version, in one upload or in shards. A dataset holds chat conversations or preference pairs, not both. Registration refuses a pair it cannot use and names its line. akka registry datasets get and akka registry datasets versions count the version’s pairs. See Preference pairs.

  • A run, an evaluation or an endpoint no longer loses its GPUs to other work while its job is still running.

  • A reinforcement run trains on a chat dataset whose prompts give one field in two shapes, such as a message’s content as a string in one row and as text parts in another, or a tool call’s argument as a number in one row and as a string in another. Previously, such a run failed before its first step, after it had claimed its GPUs.

  • A reinforcement run refuses a row whose prompt the model’s chat template refuses, such as a tool call whose arguments are not a JSON object under the Gemma 4 templates. The refusal names the line and quotes the template’s reason, before training starts. Previously, such a run failed with the template’s error and no line, in some runs only after training had started.

  • A supervised run of a small model in bf16 on the verl engine no longer fails its reference start check on sound arithmetic. When you leave checks.reference.mean_logprob_error out, its bound is three times the rounding the check measures between plain Transformers at the run’s precision and at fp32, and at least 0.03. The check reports that rounding as roundingError. Previously, the bound was 0.03, and runs over models such as SmolLM2-135M, Qwen2.5-0.5B and Gemma 4 E2B stopped before their first update unless they set it.

  • The reference check before a supervised run’s first update allows a larger largest log-probability difference for longer conversations, at the run’s precision and at fp32. Its bounds, checks.reference.max_logprob_error and checks.reference.fp32_max_logprob_error, are 1.0 and 0.002 for conversations of up to 4096 tokens and grow in proportion to the longer compared conversation’s length: 4.0 and 0.008 at 16384 tokens, and 8.0 and 0.016 at 32768. Past 4096 tokens the mean differences, whose bounds do not grow, are the sensitive tests. A bound a run states is kept. A run of Gemma 4 E4B or 12B at about 32768 tokens now trains. Previously, the bounds were 1.0 and 0.002 at every length, and such a run could be refused before it trained. See Checks before the first update.

  • A supervised run on more than one H200 GPU over Gemma 4 E2B, E4B or 12B trains with flex_attention where it does not set config.model.attentionImplementation, and a Gemma 4 E2B or E4B run also turns on liger.rms_norm and liger.geglu where it does not set them. The defaults apply only on H200 devices, where they were measured. Gemma 4 E4B trains 1.18 to 2.98 times as many tokens a second, with no more memory, and Gemma 4 E2B takes the same defaults as E4B. Gemma 4 12B trains 1.28 to 3.14 times as many, and at 32768 tokens uses 4.5 GiB more memory a device. A run that sets either keeps its own value, and a branch trains with its parent’s kernels. The defaults are part of the configuration hash, so a run that sets nothing for them falls in a new comparison column. akka training runs get --settings and a dry run show them. Previously, every run trained with sdpa and no Liger kernel unless it set them. See Default kernels by model type.

  • A supervised run on the verl engine whose packing or reference start check measures a value over its bound but at most 5 times the bound trains, and the check passes with a warning. akka training runs get shows the value, its bound and the limit, and the job’s log names them. A value more than 5 times its bound still fails the run, and a head or isolation value over its bound fails it as before. Previously, any value over its bound failed the run.

  • Continue a run with its optimizer. akka training runs branch and akka training runs sweep default to --restore auto, which keeps the snapshot’s optimizer state, random-number generators and data position wherever a trainingState branch would be accepted, and restores only the weights otherwise. The dry run and the Restore line of training runs get name the mode chosen and why, so a branch says when it starts a fresh optimizer. A sweep chooses for each point on its own. See Branches.

  • A resumed run shows on its Resumed line which save it restored, with its optimizer state, or that it restored none and starts from the base model. Under verl, a resumed attempt whose optimizer state does not load fails before its first update. The first update of a trainingState branch under verl follows the child’s schedule, warmup included. Previously, it ran at the child’s full learning rate.

  • akka training runs list and akka training endpoints list take --project NAME to list one training project’s runs or endpoints. akka registry models list --project NAME lists the project’s models by the project’s name, the same as --namespace NAME.

  • Archive a registry namespace. akka registry namespaces archive NAMESPACE takes a namespace whose work is finished out of akka registry namespaces list and out of akka registry models list, akka registry datasets list and akka registry bundles list. Add --archived to include it. A list narrowed to it with --namespace, and akka registry namespaces get, still show it. An archived namespace and its models, datasets and bundles are marked as archived. A reference into an archived namespace still resolves, so a run or an evaluation that names one of its versions is not affected, and its aliases still move. Optimize refuses to register a new version in an archived namespace, and the refusal names the namespace and the command that unarchives it. akka registry namespaces unarchive NAMESPACE restores it. The API routes are POST /v1/registry/namespaces/{ns}/archive and POST /v1/registry/namespaces/{ns}/unarchive, and the list routes take ?archived=true.

  • Archive a training project. akka training projects archive NAME leaves the project, and its runs, evaluations, distillations and endpoints, out of their lists, and refuses new work for it, including registering a candidate, naming akka training projects unarchive NAME. Archiving is refused while the project has work in progress, and the refusal names each item. get still reads an archived project, and its models can still be referenced. Each list takes --archived to include archived projects, and --project naming an archived project lists its rows. A list marks a row of an archived project (archived). akka training evaluations list and akka training distillations list show each row’s training project. Archiving a training project does not archive its registry namespace, and training projects archive says where the namespace is still open. A run, a pipeline train stage or a branch that would register its model into an archived registry namespace is refused when it is submitted. See Archive a training project.

Breaking changes

  • Omitted klBeta. A reinforcement run that sets rlHyperparams but omits klBeta now trains with a KL penalty of 0.04. On more than one GPU, Optimize refuses a KL penalty on a run that trains from an inherited adapter, so a plan that omits klBeta, inherits an adapter and trains on more than one GPU is now refused with Set klBeta to 0, or train without inheriting a policy. To keep the previous behaviour, set klBeta: 0 in rlHyperparams. To keep greedy sampling, set temperature: 0.

  • akka training runs pause refuses a run that is already paused, and POST /v1/training/runs/{id}/pause answers 400 with the run’s phase. Resume the run to train it again. Previously, Optimize answered 202 with the earlier pause, as if a new pause had been recorded.

  • Explicit loss masks. loss.explicitLossMaskColumn applies explicit masks to text chat datasets. Store each mask under the named key as a non-empty list of integer 0 and 1 values, with one entry per token that the run’s tokenizer and chat template produce. An example with a missing or null mask uses the other loss settings. Optimize refuses a malformed mask, a mask of the wrong length, and a mask that selects the first token or no token. Each training and validation dataset must hold at least one non-null mask. Correct the masks, or remove loss.explicitLossMaskColumn to use the other loss settings. See Loss.

  • right truncation. Optimize refuses data.truncation: right at submission unless the run sets loss.explicitLossMaskColumn. Without an explicit mask, the final assistant answer is selected for training, and cutting tokens from its end would shorten the answer. Set data.truncation to error. To keep right, set loss.explicitLossMaskColumn and provide masks that exclude every token past maxSeqLength. See Data.

  • Long single-turn rows. Under data.truncation: error, Optimize refuses a run with a row longer than maxSeqLength. This now applies to single-turn rows under the default loss policy, and to every row of a dataset with images. Such rows were cut from the end before. In a dataset with images, a row’s length is what the model’s processor counts, image tokens included. Raise maxSeqLength, shorten the rows, or set data.truncation: drop to leave them out.

  • Tools in reinforcement datasets and on pages. A reinforcement run fails when its dataset has a row that offers tools, and the failure names the line. Neither reinforcement engine renders a row’s tools into the prompt it rolls out. Previously, the run trained on prompts rendered without the tools. Remove tools from the rows of a reinforcement dataset. A supervised run whose training dataset has pages fails in the same way when a row of its training or validation dataset offers tools, whether or not that row has pages. Such a run renders every row without its tools, on every model. Previously, the run trained on those rows without their tools. Remove tools from every row, or train the rows with pages in a run of their own.

  • dataFit.targetsCut. A run no longer reports dataFit.targetsCut. Training dashboards no longer show the count of rows whose target was likely cut. For text datasets, Optimize refuses truncation that would remove a token selected for training. Update scripts and API clients to stop reading dataFit.targetsCut, and remove dashboard queries that use the count.

  • Prepared rows of Gemma 4. Optimize refuses a supervised run over prepared token rows whose chatTemplateSha256 is not the digest of the template the run renders under. Optimize trains Gemma 4 E2B, E4B and 12B at their catalog commits under corrected chat templates, so rows prepared for them under the template the repository ships are now refused before a GPU is claimed. The refusal names the dataset and both digests. Render the rows again under the corrected template, describe them with describe_prepared.py --chat-template, and register the new version. See Prepared token rows.

  • Branch restore default. akka training runs branch and akka training runs sweep default to --restore auto rather than weights, so a branch that can keep its optimizer state does. To start every branch with a fresh optimizer, pass --restore weights. A branch request through the API with no restoreMode is auto, where it was refused before.