Research
Helix, part 1: training a European language model
We are training our own language model. It is small – 320 million parameters – but it reads all 24 official languages of the European Union, and it trains on graphics cards built for gaming. This first part covers how we got here; the second follows when training is done.

Contents
Why a games studio trains a language model
NETBYTE builds games, apps and websites. Language models increasingly sit inside such products: as characters that talk back, as help that understands a question, as tools that do something. Most open models are English first; Estonian, Irish or Maltese come as an afterthought. We wanted to understand the whole chain ourselves – data, tokenizer, architecture, training – and find out where the money actually goes.
- parameters
- 320 M
- official EU languages
- 24
- training tokens
- 6.5 B
- for the rented GPUs
- ≈ $12
Helix began as a research prototype. Everything below is a decision that shaped it, each backed by a measurement – and the mistakes that cost us the most time.
Four ideas, one survivor
The prototype went after four known weaknesses of today’s text generators. It writes in blocks of 16 tokens instead of one token at a time, it can run a shared core of layers several times, it predicts a compact “plan” for each block, and it mixes cheap local attention with linear attention for long distances.
Block writing worked straight away: a small test model wrote 64 tokens in 13 passes through the network, where a conventional model needs one pass per token – about a fifth of the work. The other three ideas failed a harder test. We built tasks in which the answer sits far outside the local window, so the model has to look back across the whole text.
Show the data
| Variant | Correct |
|---|---|
| Local window only | 23.1% |
| + linear attention, plan and loops | 23.1% |
| + 2 exact global heads | 49.4% |
| Full attention (control) | 49.0% |
| Chance (25 %) | 25.0% |
Only exact attention across the distance solved them. Linear attention, plan and loops stayed at chance level; the optimizer had even turned the linear memory down to a half-life of less than one token. Two exact global heads were enough to match full attention.
The final model therefore keeps eight local heads with a 256-token window in every layer and adds two exact global heads in every second layer; the layers in between keep two gated linear-attention heads. Plan and loops are switched off. They are still in the code and tested, but on real text they did not earn their cost.
- Local, 256-token window
- Exact global attention
- Gated linear attention
Show the data
| Head type | Layers | Heads per layer |
|---|---|---|
| Local, 256-token window | 1–12 | 8 |
| Exact global attention | 1, 3, 5, 7, 9, 11 | 2 |
| Gated linear attention | 2, 4, 6, 8, 10, 12 | 2 |
Measure, don’t assume
We tested every training trick on a 94-million-parameter model with the same budget per run: 29.5 million tokens, the same seed, the same data order. Two runs of the same configuration differ by ±0.03, so anything smaller is noise.
Show the data
| Change | Δ loss (nats) |
|---|---|
| Muon + WSD schedule | -0.587 |
| Muon optimizer | -0.347 |
| Deeper, thinner network | -0.099 |
| WSD schedule | -0.080 |
| Value residual | -0.007 |
| z-loss | +0.029 |
| Grouped-query attention | +0.088 |
The Muon optimizer was the only large lever, and it stacks with a warmup–stable–decay learning-rate schedule. Moving the embedding and the output layer back to AdamW, as the Muon authors recommend, gained another 0.12 and made training 5 % faster. Combinations do not simply add up: a deeper, thinner network helped under AdamW and hurt under Muon. That is why every promising combination got its own run.
24 languages, 6.5 billion tokens
Helix reads web text from FineWeb-Edu for English and FineWeb-2 for the other 23 languages – for the larger ones its quality-filtered top tenth. Code, mathematics and a small synthetic chat stream complete the mix. English gets a third. The other languages are weighted by how much text exists, smoothed so that Irish and Maltese are not drowned out, and no source is repeated more than four times – up to that point repetition is about as good as fresh data.
Show the data
| Source | Share |
|---|---|
| 23 other EU languages | 51.6% |
| English | 33.0% |
| Code and markup | 10.0% |
| Mathematics | 3.0% |
| Synthetic chat and tools | 2.4% |
The chat stream is extractive: answers are copied from real paragraphs, and tool results are computed rather than invented. It teaches format, not knowledge. The tokenizer is a byte-level BPE with 64,000 entries; it packs between 3.3 and 4 bytes of text into one token for every language in Latin script.
Three bugs worth telling
- The model that read the answer. In one code path the global heads ignored the causal mask and could see future tokens. Loss fell from 6.85 to 1.71 in 75 steps, and a 16-hour run was worthless. A suspiciously good loss is a bug report; a regression test now guards exactly this.
- Characters are not bytes. Compression was counted in characters instead of UTF-8 bytes. That invented a “weakness” in Chinese and made Greek and Bulgarian look almost twice as bad as they are.
- Documents broken at every blank line. The encoder split documents at every empty line – and empty lines sit in the middle of almost every source file. Up to 35 % of the code and maths text was lost. We fixed the separator and rebuilt the whole corpus on 31 October; it took 2 hours and 12 minutes.
From the desk to a rented machine
The first 1.66 billion tokens ran on a single AMD Radeon RX 7800 XT. Two things made that usable: an attention kernel flag that is off by default – without it attention was 12 times slower – and compiling every layer with torch.compile. At a median of 11,800 tokens per second, the rest would have taken almost five more days.
So we wrote an autopilot. It rents GPUs on Vast.ai, uploads code, corpus and checkpoint, trains, brings a checkpoint home every three hours and stops before the credit runs out. On 2 November it went through three machines whose hosts never started them, then settled on two RTX 4070 Ti Super in Germany for $0.363 an hour. The 15.4 GiB upload took 40 minutes.
Show the data
| Setup | Tokens/s |
|---|---|
| Local, before optimisation | 8,319 |
| Local, compiled | 11,830 |
| Rented, 2 GPUs | 41,367 |
41,400 tokens per second is 3.5 times the desk. The rented part – 4.8 billion tokens in about 33 hours – costs roughly $12.
Where Helix stands today
- Held-out
- Training
Loss (nats per token)
Billion tokens read
Show the data
| Billion tokens read | Held-out | Training |
|---|---|---|
| 0.06 | 4.571 | 4.261 |
| 0.55 | 3.776 | 3.574 |
| 1.04 | 3.694 | 3.469 |
| 1.54 | 3.596 | 3.421 |
| 2.03 | 3.426 | 3.238 |
| 2.52 | 3.329 | 3.143 |
| 3.01 | 3.291 | 3.113 |
| 3.50 | 3.263 | 3.076 |
| 3.99 | 3.225 | 3.079 |
| 4.49 | 3.244 | 3.076 |
| 4.98 | 3.218 | 3.036 |
| 5.35 | 3.123 | 2.884 |
As of 3 November 2026, Helix has read 5.35 of its 6.5 billion tokens. Since 5.2 billion it is in the cooldown: the learning rate falls and the mix shifts towards maths, code and chat. On held-out text from all streams it is at 3.12 nats per token.
Show the data
| Language | Bits per byte |
|---|---|
| Greek | 0.721 |
| Bulgarian | 0.844 |
| French | 1.065 |
| English | 1.086 |
| Spanish | 1.135 |
| Portuguese | 1.219 |
| German | 1.257 |
| Dutch | 1.268 |
| Italian | 1.277 |
| Polish | 1.355 |
| Danish | 1.364 |
| Hungarian | 1.407 |
| Slovak | 1.412 |
| Maltese | 1.415 |
| Romanian | 1.416 |
| Swedish | 1.418 |
| Irish | 1.422 |
| Slovenian | 1.431 |
| Czech | 1.444 |
| Lithuanian | 1.450 |
| Latvian | 1.451 |
| Croatian | 1.507 |
| Finnish | 1.508 |
| Estonian | 1.727 |
What that means in practice shows best in an unedited sample from a checkpoint at about 4.9 billion tokens. The beginning is ours, the rest is Helix:
Prompt: The history of the printing press begins in the fifteenth century, when Johannes Gutenberg introduced movable type to Europe. Before that, books
Model output: for printing were usually in the form of texts, usually in the format of illustrations. In its introduction to the printing press, Gutenberg uses one line-of-action model to illustrate a series of printed pieces of a book.
Grammar, word choice and topic hold; the facts do not. That is roughly what to expect from 320 million parameters and 6.5 billion tokens: a fluent model that invents things.
What comes next
Pretraining ends in a few hours. After that come a long-context stage with books from Project Gutenberg and EU legal texts from EUR-Lex, fine-tuning for conversation and tool use, and a small draft model that speeds up generation.