File size: 9,526 Bytes
c60fef9
19e82b3
 
 
c60fef9
19e82b3
 
 
 
 
 
 
c60fef9
 
19e82b3
c60fef9
19e82b3
 
 
c60fef9
19e82b3
c60fef9
 
 
19e82b3
 
 
 
 
 
 
 
c60fef9
19e82b3
 
c60fef9
19e82b3
c60fef9
 
19e82b3
c60fef9
 
19e82b3
 
 
 
 
 
 
 
 
c60fef9
 
c7d4f85
 
 
 
 
 
 
c60fef9
19e82b3
 
c60fef9
8a1f265
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d6751af
 
 
 
 
 
 
 
8432c6c
d6751af
 
 
8432c6c
d6751af
 
 
 
 
 
19e82b3
c60fef9
d6751af
 
c60fef9
19e82b3
 
 
 
 
 
 
 
 
 
 
 
 
 
c60fef9
19e82b3
c60fef9
19e82b3
 
 
 
c60fef9
19e82b3
 
 
c60fef9
19e82b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8a1f265
 
19e82b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c60fef9
19e82b3
 
8432c6c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
---
language:
- ro
- en
license: cc-by-nc-4.0
library_name: transformers
pipeline_tag: text-generation
tags:
- romanian
- bilingual
- nanochat
- text-generation
---

# rostlabs/rost-1b-instruct

rost is a bilingual Romanian/English language model trained from scratch, with a
purpose-built Romanian tokenizer rather than one inherited from an English model.
This repository holds the instruction-tuned chat model.

## Model overview

| | |
|---|---|
| parameters | 1.384B total (24 layers, 1,536 hidden, 12 heads) |
| context length | **4,096 tokens** |
| vocabulary | 32,768, bilingual -- [rostlabs/rost-tok-bilingual](https://huggingface.co/rostlabs/rost-tok-bilingual) |
| position encoding | RoPE, theta 100,000 |
| attention | sliding-window pattern SSSL; 18 of 24 layers see a quarter context |
| precision on disk | float32 safetensors. Load as bfloat16 -- that is what it trained in |
| stage | sft, checkpoint step 000387 |
| languages | Romanian (primary), English |

Not a Llama or Mistral derivative: the architecture is its own, so the modelling
code ships in this repository and `trust_remote_code=True` is required.

## Usage

```python
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained(
    "rostlabs/rost-1b-instruct", trust_remote_code=True, dtype=torch.bfloat16).to("cuda").eval()
tokenizer = AutoTokenizer.from_pretrained("rostlabs/rost-1b-instruct")

messages = [{"role": "user", "content": "Care este capitala Romaniei?"}]
inputs = tokenizer.apply_chat_template(
    messages, add_generation_prompt=True, return_tensors="pt", return_dict=True)
out = model.generate(inputs["input_ids"].to("cuda"), max_new_tokens=128)
print(tokenizer.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
```

The weights are stored in bfloat16, the precision the model was trained in and the
precision the forward pass casts to regardless. They were published as float32 at first,
because release verification compares logits exactly and that is only meaningful in float32 —
but that made the files twice the size for no information: 47% of the parameters were already
bfloat16-exact, and under bfloat16 the two files produce bitwise identical logits. Loading in
float32 is still possible and shifts the top-8 probabilities by up to 1.7e-03, a mode the
model was never trained in.

Measured on a single RTX 5070 (12 GB, SDPA path): **~91 tokens/second**, ~3.3 GB
resident.

### Recommended sampling parameters

`generation_config.json` carries these, so `model.generate()` uses them without being
asked:

```json
{
  "do_sample": true,
  "temperature": 0.6,
  "top_k": 50,
  "repetition_penalty": 1.1,
  "eos_token_id": [32763, 32759]
}
```

The repetition penalty is not decoration. Measured over 198 generations of 400 tokens,
on prompts chosen to provoke the failure:

| decoding | replies that looped | worst repeated 6-gram |
|---|---:|---:|
| greedy | 50% | 44x |
| temperature 0.2, no penalty | 44% | 44x |
| temperature 0.6, no penalty | 22% | 10x |
| **temperature 0.6, penalty 1.1** | **0%** | **2x** |

A penalty of 1.1 also raises the share of replies that end by emitting their stop token,
rather than running out of budget, from 50% to 83%. Stronger settings suppress repetition
further and cost accuracy: at 1.3 the model stopped looping and began inventing
etymologies, so 1.1 is the mildest setting that works and that is why it is the default.

Before this revision the repository set no `eos_token_id` in any file, so `generate()`
had no stop condition and ran to `max_new_tokens` on every call.

### Running it with llama.cpp

Quantisations are published at
[rostlabs/rost-1b-instruct-GGUF](https://huggingface.co/rostlabs/rost-1b-instruct-GGUF):
Q4_K_M at 791 MiB through to BF16 at 2.6 GiB.

They need a llama.cpp that has this architecture compiled in, because llama.cpp compiles
architectures in rather than loading them dynamically. A fork with it applied is at
[rostlabs/llama.cpp](https://github.com/rostlabs/llama.cpp), whose `master` is upstream
master plus one commit:

```bash
git clone -b master https://github.com/rostlabs/llama.cpp && cd llama.cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build -j
./build/bin/llama-cli -m rost-1b-instruct-Q4_K_M.gguf --repeat-penalty 1.1 -p "Salut!"
```

Measured: 60.6 tok/s on twelve CPU threads, 489.7 on an RTX 5070, 77 on an M3.

### Not available

**Ollama and LM Studio.** Both bundle their own llama.cpp, so neither will read those files
until this architecture is merged upstream. That is prepared but not submitted.

**Tool and function calling.** The instruct checkpoint has had conversational
fine-tuning only. No agent fine-tuning has been applied, so the tool tokens are
not reachable under any prompt framing. Do not build an agent on this checkpoint
yet.

## Training

| | |
|---|---|
| tokens | 11.68B, single pass -- no data was repeated |
| optimizer steps | 11,136 at a 1,048,576-token batch |
| hardware | 8x H100 80GB, ~3.6 hours |
| schedule | warmup-stable-decay, decay over the final 30% |
| precision | bfloat16 with FP8 matmuls |

Trained in two phases, which is the substance of the recipe rather than a detail:

| | Romanian | English (ClimbMix) | DQA | code |
|---|---:|---:|---:|---:|
| phase 1, steps 0-7,795 | 30% | 60% | 5% | 5% |
| phase 2, steps 7,795-11,136 | **55%** | 35% | 10% | -- |

The second phase raises Romanian while the learning rate decays, so the model
finishes on a Romanian-heavy diet. A d6 rehearsal measured Romanian improving
roughly 8x faster than English across that phase.

### Data

| source | licence |
|---|---|
| Romanian: FineWeb2-ro, educational score >= 3, diacritic-normalised | ODC-BY |
| English: Nemotron ClimbMix | CC-BY-NC-4.0 |
| High-quality QA: Nemotron-CC-v2.1 HQ-DQA | gated |
| Code: Nemotron-CC-Code-v1 (phase 1 only) | gated |
| Chat fine-tuning: OpenLLM-Ro sets | CC-BY-NC-4.0 |

## Evaluation

**OpenLLM-Ro suite**, base checkpoint, 400 rows per task, **zero-shot**, scored by
likelihood over the options:

| task | accuracy | normalised | chance |
|---|---:|---:|---:|
| ro_hellaswag | 31.25 | **38.50** | 25.0 |
| ro_truthfulqa (MC1) | 21.25 | **34.00** | 14.3 |
| ro_arc_challenge | 24.50 | 30.25 | 28.6 |
| ro_mmlu | 28.50 | 29.75 | 25.0 |
| ro_winogrande | 52.25 | 52.25 | 50.0 |
| **mean (normalised)** | | **36.95** | 28.6 |

**Read these against the chance column, not on their own.** The model is clearly
above chance on sentence completion and truthfulness, and close to chance on
`ro_arc_challenge` and `ro_winogrande`. At 400 rows a task, differences under about
5 points are inside the noise.

**These are not comparable to the OpenLLM-Ro leaderboard.** Published figures there
average each task over several few-shot settings; these are zero-shot, which
understates them. For scale rather than ranking: RoLlama2-7b-Base reports a 42.05
four-task accuracy average against this model's 34.12 -- from a model 5x larger
trained on far more data.

Also measured: CORE metric 0.2450 on the base model (0.1608 at step 2,000), and
0.3021 validation bits-per-byte for the instruct checkpoint against 0.5113 for the
base model it started from.

## Intended use

Research on Romanian language modelling, Romanian text generation and completion,
and as a base for further fine-tuning. It is small enough to run on a consumer GPU,
which is the point.

**Out of scope:** anything requiring factual reliability, agent or tool use,
long-context work beyond 4,096 tokens, commercial deployment (see the licence),
and any decision affecting a person's rights, health, safety or finances.

## Limitations

- **It confabulates confidently.** Asked about Bucharest it correctly names the
  capital and then places it in the wrong county. Specifics need checking.
- **It repeats.** Restating a sentence with the clauses swapped is a common
  failure, inherited from the base model and only partly removed by fine-tuning.
  Decode with the shipped `repetition_penalty` of 1.1; with penalties off and a low
  temperature it will repeat one sentence until it runs out of tokens.
- **Reasoning is near chance.** See `ro_arc_challenge` and `ro_winogrande` above.
- **4,096 tokens** of context, well short of contemporary models.
- **Domain skew.** The Romanian pretraining data is roughly one third health
  content by character count, with history, geography, finance and education each
  near 10%, and entertainment, gaming and software each under 1%. Fluency is uneven
  accordingly.
- **The Romanian corpus is internally duplicated**, which inflates absolute
  Romanian bits-per-byte by around 0.09. Comparisons on fixed sets are unaffected.
- **No safety tuning of any kind** has been applied.

## Licence

**CC-BY-NC-4.0, non-commercial.** Both halves of the training data carry
non-commercial terms -- ClimbMix is CC-BY-NC-4.0 ("for research and development
only") and the OpenLLM-Ro fine-tuning sets are CC-BY-NC-4.0 -- and the model
inherits them. The ClimbMix mirror used is tagged MIT, which does not override the
upstream terms. The Romanian data is ODC-BY and requires attribution to FineWeb2.

## Citation

```bibtex
@misc{rost2026,
  title  = {rost: a bilingual Romanian-English language model trained from scratch},
  author = {Iancu, Stefan},
  year   = {2026},
  url    = {https://huggingface.co/rostlabs/rost-1b-instruct}
}
```

The original training checkpoint (`model_*.pt`, `meta_*.json`) ships alongside the
safetensors, for use with the training code.