Downloads · 30 days
0
InfinimindCreations/laya-rlcd-training
laya-rlcd-training is a machine learning model from InfinimindCreations. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
A training loop for Laya, the open-weights System One model.
Downloads · 30 days
0
Access
Public
Updated Sep 22, 2026
Repo size
—
Likes
1
Trending 1
Click a slice to open those files.
.py24.6 KB · 67%
From the Hugging Face model README
A training loop for Laya, the open-weights System One model.
Laya ships the building blocks but no training loop. Its README describes the
method (RLCD, Gaussian noise on the logits, a strictly proper scoring rule,
REINFORCE with a group-mean baseline), and the repository contains no backward
call and no optimizer (checked 2026-09-20). This is that loop, written from the
description and tested on a real corpus rather than a toy set.
Everything public about System One models right now rebuilds the inference path: score the allowed answers instead of generating text. That part is well covered. The part everyone leaves out is how you make the model good at your questions. That is what this is for.
Takes labelled text, trains the encoder to answer several typed questions in one forward pass, and reports accuracy per question against a held-out gold set.
Three question types, matching Laya's own:
| type | label in your data | example |
|---|---|---|
choice | one of the criteria keys | which section does this belong to |
score | integer index into an ordinal scale | how severe is this, 0–4 |
bool | true / false | does this describe violence |
pip install torch transformers safetensors huggingface_hub datasets
python example/build_example.py --train 4000 --gold 400
python train.py \
--data example/train.jsonl \
--gold example/gold.jsonl \
--questions example/questions.json \
--batch 16 --stage 200 --save out/
The base model is fetched on first use. Set LAYA_SNAP to a local directory to
use a copy you already have, or to continue from your own checkpoint.
The example is built from AG News, so it runs without any private data. It prints the majority-class baseline before training starts: the number your result has to beat before it means anything.
One JSON object per line:
{"id": "a1", "text": "...", "topic": "business", "severity": 2, "violent": false}
A field missing from a line is skipped for that record. Questions do not all have to be labelled on the same texts, which lets you combine a large cheaply labelled set for one question with a small carefully labelled set for another.
Question definitions live in a JSON file; see example/questions.json and the
docstring in data.py.
The four-question model this loop produced on our news corpus is public: InfinimindCreations/laya-news-decisions.
Six questions over 92k news articles, labelled by a larger model, evaluated against gold judgements from three independent LLM annotators (majority vote). Two runs, same loop, same questions, same gold set. The only change is the amount of training data.
A note on the gold set, because it decides what any of these numbers mean: it started at 176 judgements and the extremes were nearly empty: four cases on the top impact level, where a single article moved the score by 25 points. We widened it to 230 by sampling by level rather than by topic and having three LLM annotators judge each case independently, keeping only what at least two agreed on. Levels 3 and 4 went from 20 and 4 cases to 48 and 23. Every number below that says 230 uses the widened set.
| question | 19.8k records | 92k records | |
|---|---|---|---|
| topic (choice, 9 classes) | 0.722 | 0.773 | +0.051 |
| impact (score, 5 levels) | 0.585 | 0.648 | +0.063 |
| civilian harm (score) | 0.614 | 0.648 | +0.034 |
| urgency (score, 3 levels) | 0.705 | 0.733 | +0.028 |
| sentiment (score) | 0.619 | 0.642 | +0.023 |
| violence (bool) | 0.943 | 0.966 | +0.023 |
All six improved, none traded against another. On the ordinal questions the within-one-level rate reached 0.97–0.99, i.e. the model rarely misses by more than one step.
Both runs: one A100, full fine-tune, batch 16, G=32, lr 1e-5 with cosine decay.
We then added a title-level question to the same model, trained from the base weights so it would not inherit the collapse described below. Measured against a widened gold set (230 judgements for the ordinal questions, 900 for the new one):
| question | six questions | seven questions | |
|---|---|---|---|
| the new question | 0.333 (collapsed) | 0.769 | +0.436 |
| impact | 0.600 | 0.604 | +0.004 |
| sentiment | 0.642 | 0.642 | 0.000 |
| topic | 0.773 | 0.761 | -0.011 |
| violence | 0.966 | 0.955 | -0.011 |
| civilian harm | 0.625 | 0.594 | -0.031 |
| urgency | 0.733 | 0.648 | -0.085 |
There is no free lunch here and we are not going to pretend otherwise. One model is the specialist, the other the generalist; the seventh question cost about two points on average across the other six, worst on urgency. Both were trained with the same budget, so part of that is simply fewer steps per question.
One detail the accuracy column hides: on impact the seven-question model's rank correlation rose to 0.824 from 0.778. It orders the articles better while hitting the exact level about as often, which for that question is the property that matters.
A long run should survive an interruption. --save writes two different files,
and conflating them costs you a run:
checkpoint.pt: the latest state, written at every evaluation, carrying
the weights, the AdamW moments and the scheduler position. This is what
--resume out/checkpoint.pt reads, so an interruption costs one stage at most.model-best.pt: the best state. This is the one you deploy.Writing the resume file only on improvement looks harmless and is not: a run whose best score falls early would resume hours behind where it stopped.
Weights alone are not enough: without the optimizer moments and the scheduler position the learning rate jumps back to its warmup value and shakes the weights loose. Measured on a 600-step schedule, continuing correctly resumed at lr 4.12e-06, a weights-only warm start would have restarted at 8.82e-06.
Set LAYA_PUSH=org/repo to also push the best checkpoint to the Hub during the
run, throttled by --push-every (uploads run on the accelerator's clock).
A full fine-tune of the 322M-parameter multilingual variant needs roughly 5.2 GB
for parameters, gradients and the two AdamW moments, before activations. On a
12 GB consumer card that OOMs at batch 4; use --freeze 12 to freeze the lower
encoder layers. On an 80 GB accelerator, leave --freeze at 0. In our runs the
unfrozen model passed the frozen one's 5,000-article result after 1,600.
Apache 2.0, following Laya itself. The example data comes from AG News.