How to use from
Docker Model Runner
docker model run hf.co/ToetsChecker-Research/boterham
Quick Links

Boterham 0.5B

A Dutch language model of half a billion parameters, trained from scratch on open data only, for about € 120 of rented compute. It reads a text you give it, answers questions about that text, and says "Ik weet dit niet." when the answer is not there.

Nederlands · English

Scoreboard: Boterham 0.5B round 4 next to GPT-NL 26B on seven Dutch EuroEval tasks

English

At a glance

Parameters 488.3M total; 447.4M excluding tied token embeddings
Architecture Decoder-only Transformer, RMSNorm, GQA, RoPE, SwiGLU, QK-norm
Layers / hidden size 26 / 1,280
Attention heads 20 query heads, 4 key/value heads
Context length 2,048 tokens
Vocabulary 32,002-token byte-level BPE, trained on the corpus itself
Pretraining 8.0 billion tokens on one NVIDIA H100
Instruction tuning four rounds on one to four NVIDIA L4 GPUs
Training data ToetsChecker-Research/beleg, public domain and open licences only
Compute cost € 121.60 at Scaleway, of which € 100 was a free credit
Languages Primarily Dutch; some English
License Apache 2.0

This repository holds round 4 of the instruction tuning (November 2026). The September release (round 1) is still available under the git tag ronde-1: from_pretrained(model_id, revision="ronde-1").

The Hugging Face export uses the Qwen3ForCausalLM implementation because the architectures are identical. Boterham does not use Qwen weights and is not a fine-tune of Qwen; tokenizer and weights were trained from scratch.

The figures on this page have Dutch labels. Each one is described in the text next to it.

Results

EuroEval 18.0.0, ten iterations per task, with the 95% interval over the iterations. WikiLingua-nl ran on EuroEval 15.16.0 because that version still reports BERTScore, the metric behind the GPT-NL figure.

The fair opponent is GPT-NL after instruction tuning (epoch 2, "our data (IT)" in figure 21 of TNO report GPTNL-DEL-4002), because Boterham is instruction-tuned as well. GPT-NL has 26B parameters, about fifty times as many. Its base model is listed for reference.

Task Metric Boterham 0.5B r4 GPT-NL IT GPT-NL base
ScaLA-nl (grammar) MCC 29.50 ± 3.00 1.18 19
SQuAD-nl (reading) EM 36.62 ± 0.97 34.37 51
CoNLL-nl (names) micro-F1 w/o MISC 49.46 ± 2.76 47.82 ~36
DBRD (sentiment) MCC 40.15 ± 4.15 85.36 ~90
WikiLingua-nl (summaries) BERTScore 56.80 61.97 61
HellaSwag-nl (common sense) MCC 1.15 ± 0.75 3.71 -2
MMLU-nl (knowledge) MCC -2.13 ± 0.86 2.28 2

Boterham is ahead of the instruction-tuned GPT-NL on grammar, reading and names, and behind it on sentiment, summarization, common sense and knowledge. On MMLU-nl and HellaSwag-nl both models are at chance level (MCC 0 is guessing), so the difference there says nothing.

The chart below shows every round of Boterham on the same seven tasks. Each round of instruction data targeted what the previous round could not do. Round 3 added grammar judgements, which lifted ScaLA-nl above zero. Round 4 added name recognition in the CoNLL-nl format and sentiment, which is where those two tasks jump.

EuroEval per task for every round of Boterham, with GPT-NL as dashed lines

What it is good at, and what not

Good: a short answer to a question about a text you supply, and refusing with "Ik weet dit niet." when the text does not contain the answer.

Weak: summaries are short and mostly take the opening sentence of the text. Facts without a text in the prompt, open conversation, creative writing, code and anything after its training data are unreliable. Even on its strong tasks it gives plausible but wrong answers on free-form input. In our own test with eight questions on two Rijksoverheid.nl pages it answered two of the six answerable questions correctly, refused two it could have answered, gave two wrong answers, and refused both questions whose answer was not in the text. Check every answer against the text.

How to prompt it

The model was trained and measured on fixed instructions. It does best when you use them literally.

Reading question:

Beantwoord de vraag uitsluitend op basis van de tekst. Staat het antwoord er niet in, antwoord dan precies: Ik weet dit niet.

Tekst: {text on one line}

Vraag: {question}

Summary:

Document: {text on one line}

Schrijf een samenvatting van het bovenstaande document.

Put the text on one line (replace blank lines by spaces). With paragraph breaks the model tends to copy a whole paragraph instead of the answer. A cheap safeguard that removes most made-up answers: only accept an answer that appears literally in the text, and treat anything else as "Ik weet dit niet."

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "ToetsChecker-Research/boterham"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, dtype=torch.float32)

tekst = "De vergadering begint vrijdag om 14.00 uur in Utrecht."
vraag = "Hoe laat begint de vergadering?"
messages = [{
    "role": "user",
    "content": (
        "Beantwoord de vraag uitsluitend op basis van de tekst. Staat het "
        "antwoord er niet in, antwoord dan precies: Ik weet dit niet.\n\n"
        f"Tekst: {' '.join(tekst.split())}\n\nVraag: {vraag}"
    ),
}]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(prompt, return_tensors="pt")
with torch.inference_mode():
    output = model.generate(**inputs, max_new_tokens=64, do_sample=False,
                            eos_token_id=tokenizer.eos_token_id,
                            pad_token_id=tokenizer.pad_token_id)
raw = tokenizer.decode(output[0, inputs.input_ids.shape[1]:], skip_special_tokens=False)
antwoord = raw.split("<|einde_denken|>")[-1].split("<|einde|>")[0].strip()
print(antwoord if antwoord.rstrip(".") in tekst else "Ik weet dit niet.")

It runs on a laptop CPU: a question about a page of text takes two to six seconds on two cores.

Training data

The corpus has 10.2 billion tokens from 30 sources: Dutch case law, parliamentary proceedings, legislation, government publications, Wikimedia, EUR-Lex, Europarl, and open English books and articles. Everything is public domain under Dutch or Belgian copyright law, or under an open licence; there is no web crawl and no text generated by another model. Of the corpus 39% is Dutch; the training mix raised that to 68% by weighting.

The corpus per source in billions of tokens, Dutch dark and English light

Per document the dataset records source, licence and retrieval date. It is published separately as ToetsChecker-Research/beleg.

Training

Pretraining. 8.0 billion tokens on one H100, with warmup, a long stable phase and a decaying learning rate at the end. Final validation loss 1.835 (perplexity 6.3) on 49.3M tokens that were never trained on.

Pretraining loss against tokens read, with the learning rate schedule below

Instruction tuning. Four rounds, each continuing from the previous one. Loss counts only answer tokens.

Round Examples Steps Hardware
1 575,211 4,786 (2 epochs) 4x NVIDIA L4
2 315,248 1,006 (1 epoch) 1x NVIDIA L4
3 210,122 1,213 (1 epoch) 1x NVIDIA L4
4 222,316 1,247 (1 epoch) 1x NVIDIA L4

Rounds 2 to 4 used a peak learning rate of 2e-5. All instruction data is derived from the corpus or from human-written open sets (SQuAD-nl, OASST, Aya, Dolly, Tatoeba) and checked afterwards: an extractive answer must appear literally in its context, an abstention example must not contain the answer, and examples that share a 13-gram with a EuroEval test item are removed. Round 4 is published as the instructie-r4 configuration of the dataset.

Cost and footprint

All training ran on rented GPUs at Scaleway in Paris: € 121.60 in total, of which a € 100 credit, so € 21.60 paid. GPT-NL received € 13.5 million in public funding.

Cost per item at Scaleway, and the same amount next to the GPT-NL subsidy

Scaleway reports 2.0 kg CO2e and 1.4 litres of water for all of it, roughly 19 km by car and ten seconds of showering.

CO2e and water use, split into pretraining, fine-tuning and storage

Files in this repository

  • model.safetensors and the tokenizer files: the round 4 model.
  • ronde4/beste.pt, config.json, log.csv: native PyTorch checkpoint and training log of round 4.
  • sft-0.5B/, boterham-0.5B/: round 1 and pretraining checkpoints.
  • figuren/: the figures on this page.

Limitations

A small experimental model with limited world knowledge. It can produce incorrect, made-up or biased text. Do not trust claims about people, dates, numbers, law, medicine or current events without the source in front of you. The context window of 2,048 tokens is short; texts longer than about 6,000 characters do not fit. Formal written Dutch dominates the training data, so casual language is weaker.


Nederlands

In het kort

Boterham 0.5B is een Nederlandstalig taalmodel van een half miljard parameters, vanaf nul getraind op uitsluitend open data, voor ongeveer € 120 aan gehuurde rekenkracht. Het leest een tekst die je meegeeft, beantwoordt vragen over die tekst, en zegt "Ik weet dit niet." als het antwoord er niet in staat.

Dit is ronde 4 van het finetunen (november 2026). De versie van september (ronde 1) staat nog in de repository onder de git-tag ronde-1.

De export gebruikt Qwen3ForCausalLM omdat de architectuur gelijk is. Boterham gebruikt geen Qwen-gewichten; tokenizer en gewichten zijn vanaf nul getraind.

Scores

EuroEval 18.0.0, tien iteraties per taak. WikiLingua-nl op EuroEval 15.16.0, omdat die versie nog BERTScore geeft, de maat achter het getal van GPT-NL. De eerlijke tegenstander is GPT-NL na het finetunen (TNO-rapport GPTNL-DEL-4002, figuur 21), een model van 26 miljard parameters. Het scorebord bovenaan en de grafiek per ronde in de Engelse sectie laten dezelfde getallen zien.

Taak Maat Boterham 0.5B r4 GPT-NL IT GPT-NL basis
ScaLA-nl (grammatica) MCC 29,50 ± 3,00 1,18 19
SQuAD-nl (lezen) EM 36,62 ± 0,97 34,37 51
CoNLL-nl (namen) micro-F1 zonder MISC 49,46 ± 2,76 47,82 ~36
DBRD (sentiment) MCC 40,15 ± 4,15 85,36 ~90
WikiLingua-nl (samenvatten) BERTScore 56,80 61,97 61
HellaSwag-nl (gezond verstand) MCC 1,15 ± 0,75 3,71 -2
MMLU-nl (kennis) MCC -2,13 ± 0,86 2,28 2

Boterham staat voor op grammatica, lezen en namen, en achter op sentiment, samenvatten, gezond verstand en kennis. Op MMLU-nl en HellaSwag-nl zitten beide modellen op gokniveau.

Waar het goed in is, en waarin niet

Goed: een kort antwoord op een vraag over een tekst die je zelf meegeeft, en "Ik weet dit niet." als het antwoord er niet in staat.

Zwak: samenvattingen zijn kort en nemen meestal de openingszin over. Feiten zonder tekst erbij, vrij gesprek, creatief schrijven, code en alles van na de trainingsdata zijn onbetrouwbaar. Ook op zijn sterke taken geeft het op vrije invoer soms een fout antwoord dat er aannemelijk uitziet. In een eigen proef met acht vragen over twee pagina's van Rijksoverheid.nl gaf het op twee van de zes beantwoordbare vragen het goede antwoord, weigerde het er twee die wel te beantwoorden waren, gaf het twee foute antwoorden, en weigerde het terecht beide vragen waarvan het antwoord niet in de tekst stond. Controleer elk antwoord tegen de tekst.

Zo vraag je het

Gebruik letterlijk de opdrachten uit de Engelse sectie, met de tekst op één regel: met witregels erin neemt het model vaak een hele alinea over in plaats van het antwoord. Accepteer daarna alleen een antwoord dat letterlijk in de tekst staat; dat haalt de meeste verzonnen antwoorden weg.

Data, training en kosten

Het corpus telt 10,2 miljard tokens uit 30 bronnen: rechtspraak, Handelingen, wetten, overheidspublicaties, Wikimedia, EUR-Lex, Europarl en open Engelse boeken en artikelen. Alles is publiek domein of open gelicentieerd; er zit geen geschraapt web in en geen tekst van een ander taalmodel. Het corpus is voor 39% Nederlands, de trainingsmix voor 68%. Per document staan herkomst, licentie en ophaaldatum in ToetsChecker-Research/beleg; de data van ronde 4 staat daar als configuratie instructie-r4.

Voortrainen: 8,0 miljard tokens op één H100, validatieverlies 1,835 (perplexiteit 6,3). Daarna vier finetunerondes op L4-kaarten (tabel in de Engelse sectie). Alles samen kostte € 121,60 bij Scaleway, waarvan € 100 tegoed, dus € 21,60 zelf betaald, en volgens Scaleway 2,0 kg CO2e en 1,4 liter water. GPT-NL kreeg € 13,5 miljoen overheidssteun.

Beperkingen

Een klein experimenteel model met beperkte wereldkennis. Het kan onjuiste, verzonnen of bevooroordeelde tekst geven. Vertrouw geen uitspraken over personen, datums, getallen, recht, geneeskunde of actualiteit zonder de bron ernaast. Het contextvenster van 2.048 tokens is kort: teksten boven ongeveer 6.000 tekens passen er niet in. Formeel geschreven Nederlands overheerst in de trainingsdata, dus spreektaal gaat minder goed.

Downloads last month
77
Safetensors
Model size
0.5B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Dataset used to train ToetsChecker-Research/boterham