teaching a small model to write and think in real romanian
it isn't good enough. a model can be fluent-ish and still invent word-forms that don't exist, slip into english mid-sentence, and drop diacritics like they're optional. if you actually read romanian, you notice immediately.
so we spent a training run fixing exactly that. today we're releasing surogate 3.5, two romanian-first bilingual (RO/EN) models, 2B and 4B, both apache 2.0.
what they are
surogate 3.5 is a dual-mode reasoner built on the qwen3.5 family:
- thinking on: it reasons step by step in the language of the prompt. romanian prompt, romanian chain-of-thought, math included. english prompt, english chain-of-thought.
- thinking off: it answers directly, no reasoning trace.
the models were trained with our open-source surogate training framework.
the thing we actually cared about
the goal was never a leaderboard number. it was romanian text that a native speaker wouldn't flinch at. three failure modes, measured on a 13,963-prompt romanian generation benchmark scored against a dexonline-authoritative dictionary:
invented word-forms (made-up words that don't exist), per 1k tokens, lower is better:
| invented word-forms / 1k ↓ | |
|---|---|
| qwen3.5-4B (base) | 4.07 |
| surogate 3.5-2B | 1.49 |
| surogate 3.5-4B | 1.56 |
that's the headline: roughly a 2.6x cut in made-up words, and the 2B holds it just as well as the 4B.
english leakage (english creeping into romanian output), per 1k, lower is better:
| english-leak / 1k ↓ | |
|---|---|
| qwen3.5-4B | 1.38 |
| surogate 3.5-2B | 0.88 |
| surogate 3.5-4B | 1.00 |
reasoning language match: when the chain-of-thought is on, does it actually think in the prompt's language, or quietly switch to english to do the real work?
| RO prompts | EN prompts | <think> leak (no-think mode) |
|
|---|---|---|---|
| surogate 3.5-2B | 100% | 100% | 0% (1/1392) |
| surogate 3.5-4B | 100% | 100% | 0% (1/1392) |
a reasoning model that switches to english to think isn't reasoning in your language, it's translating. keeping the chain-of-thought in the prompt language is the harder version, and the honest one.
the full table
greedy decoding unless noted. IFEval is strict metrics. translation is chrF2 on a held-out RO↔EN set.
| benchmark | qwen3.5-4B | surogate 3.5-2B | surogate 3.5-4B |
|---|---|---|---|
| RO invented word-forms / 1k ↓ | 4.07 | 1.49 | 1.56 |
| RO english-leak / 1k ↓ | 1.38 | 0.88 | 1.00 |
| RO missing diacritics / 1k ↓ | 0.68 | 1.93 | 0.30 |
| RO IFEval (prompt / instr strict) ↑ | 0.272 / 0.541 | 0.116 / 0.350 | 0.294 / 0.545 |
| RO GSM8K (strict) ↑ | 0.706 | 0.459 | 0.722 |
| EN IFEval (prompt strict) ↑ | 0.823 | 0.522 | 0.691 |
| EN GSM8K (strict) ↑ | 0.890 | 0.665 | 0.882 |
| translation EN→RO (chrF2) ↑ | 54.8 | 46.9 | 53.9 |
| translation RO→EN (chrF2) ↑ | 62.5 | 53.1 | 63.0 |
the 4B beats base qwen3.5-4B on romanian orthography, romanian ifeval, romanian gsm8k, and ro→en translation, while cutting invented words by more than half. it also has the best diacritics in the table by a wide margin (0.30 vs 0.68).
where it still trails (we're not hiding it)
- english ifeval and english gsm8k are behind base qwen. the romanian-first training costs some english instruction-following.
- en→ro translation trails base qwen slightly on the 4B.
- the 2B trades diacritic accuracy (1.93 vs base 1.05) and instruction-following for its low invented-word rate. it's a specialist: reach for the 4B if you need diacritics and ifeval.
we left the whole table up on purpose. judge it yourself.
which one to use
- surogate 3.5-2B: one job, done well. romanian text that doesn't make up words, on hardware you already own. a specialist for generation quality at small scale.
- surogate 3.5-4B: the all-rounder. best romanian orthography in the set, strong reasoning, keeps the low invented-word rate.
usage
vLLM, 4B:
vllm serve surogate/Surogate-3.5-4B --reasoning-parser qwen3 \
--enable-auto-tool-choice --tool-call-parser hermes
vLLM, 2B:
vllm serve surogate/Surogate-3.5-2B --reasoning-parser qwen3
thinking control via the chat template:
tok.apply_chat_template(
messages,
add_generation_prompt=True,
enable_thinking=True, # step-by-step reasoning in the prompt's language
# enable_thinking=False -> direct answer
)
one sampling note: the repo ships a generation_config.json (temperature 0.6, top_p 0.95, top_k 20). don't sample with top_p=1.0, the unfiltered tail degrades output. for orthography-critical work, prefer greedy (temperature=0).
links
- collection: RO-EN Surogate Models
- surogate/Surogate-3.5-2B
- surogate/Surogate-3.5-4B
- training framework: github.com/invergent-ai/surogate
built by the team at invergent in bucharest. apache 2.0.
intelligence should speak your language too.