A bidirectional Karachay-Balkar ↔ Russian translation model. It is a DoRA adapter on
top of facebook/nllb-200-distilled-600M, trained on ~730k Karachay-Balkar sentence,
phrase and word pairs.
Karachay-Balkar (krc, къарачай-малкъар тил) is a Kipchak Turkic language of the North
Caucasus with roughly 300k speakers. It is not one of the 200 languages in NLLB.
chrF (sentences, KB↔RU, held-out)
56.41
Base model
facebook/nllb-200-distilled-600M
Adaptation
DoRA, r=64, α=64, dropout 0.2
Adapter size
133 MB
Training pairs
729,650 (1,445,188 direction-doubled rows)
Directions
krc→rus and rus→krc in one model
⚠️ Read this before running it
Two things about this model are non-obvious, and it will produce poor output if you skip them.
1. Karachay-Balkar rides the Bashkir language slot. NLLB has no krc token, so KB was
trained into bak_Cyrl. Bashkir is the closest Kipchak relative available in the tokenizer,
which is a large part of why 730k pairs are enough to get useful quality. Set
src_lang / forced_bos_token_id to bak_Cyrl when you mean Karachay-Balkar.
2. Every source string must carry a direction tag prefix. Training used a literal text
prefix on the source side. Reproduce it exactly, including the trailing space:
Evaluation used 2 for speed; 4–5 is better for real use
max_length
384
Training used 128 (96.8% of pairs are ≤64 tokens), but a 128-token inference cap silently truncates long inputs
no_repeat_ngram_size
3
Suppresses the usual seq2seq loop on long inputs
The model saw very few targets longer than 128 tokens, so very long outputs may still be
weak — but with max_length=384 they will at least not be cut off.
Detecting the direction automatically
If you need to auto-detect which language you were handed, the reliable signal is the
presence of the digraphs къ or гъ — these do not occur in Russian orthography.
Do not use дж as a signal: Russian has it in loanwords (джентльмен, бюджет, Джордж),
and using it as a KB marker routes Russian input into KB→RU, which silently returns a
paraphrase of the input rather than a translation.
Orthography and dialect
Written Karachay and Balkar differ essentially in one thing: the phoneme /dʒ/ is spelled
дж in Karachay and ж in Balkar. The training corpus was normalised to the ж
form, with one guard: дж → ж was applied only when дж was absent from the Russian side
of the pair, so Russian loanwords keeping дж were not corrupted.
The dative pronouns манга / санга / анга are normative for both varieties and are what
the model produces. меннге / сеннге is a tolerated Karachay dialect form (~1% of Balkar
literature, 30–40% of Karachay) and was normalised to манга / санга with word-boundary
anchoring — an unanchored regex corrupts ordinary datives such as тирменнге (to the mill)
or экзаменнге (to the exam). анга is never rewritten: its stem has no final -н, so
аннге cannot exist.
The tsokayushchiy (ц/дз/з, Cherek) variety is spoken but written as standard, so it is
effectively absent from text and from this model.
Training data
729,650 pairs:
Tier
Pairs
Share of training rows
Sentences
480,858
66.1%
Words
136,645
18.6%
Phrases
112,147
15.2%
Sources: digitised Karachay-Balkar books and literature, a merged lexicon built from 12
dictionaries, and 171 issues (one year, 2007) of the newspaper Заман.
Provenance disclosure. The Karachay-Balkar side of every pair is human-authored — this
was a hard project rule, and no synthetic KB was ever admitted into training. A substantial
share of the Russian side of the sentence tier is machine-generated (LLM translation of
the KB source) rather than a published human translation. Treat Russian output fluency as
better attested than Russian output fidelity on rare or literary material.
Gates applied to every batch of data before it entered training: orthographic normalisation
on both sides, exact deduplication, and a hard benchmark-leak check. Rejected rows were
parked, never deleted.
Training recipe
base facebook/nllb-200-distilled-600M
method DoRA (PEFT), r=64, alpha=64, dropout=0.2
targets q_proj k_proj v_proj out_proj fc1 fc2
epochs 4 (of 5 run — epoch 5 overfits, see below)
batch 32
lr 2e-4
max_length 128
seed 42
hardware 2x H100 SXM, ~11 h
final loss 0.90
The published checkpoint is step 180652 = epoch 4.
Held-out split: 2,981 sentence keys / 1,461 phrase keys / 684 word keys held out by Russian
headword, with zero train↔test headword overlap. Reported chrF is sentence-only, both
directions, on a 2,000-row subset of that holdout.
How the score got to ~56
The two score columns below come from different holdouts and are not comparable to each
other: an early all-tier score (which mixes in single words, where chrF is inherently low)
and the later sentence-only score. Compare within a column, not across.
Stage
Corpus
all-tier chrF
sentence chrF
v1 — first attempt
5,849 sentences
—
unusable
v10 — full fine-tune baseline
small
43.98
—
KB2 — corpus rebuild + DoRA
690,652 pairs
49.05
54.67
This model — + Заман 2007
729,650 pairs
—
56.41
What actually moved the number:
Corpus size. Going from 5,849 to 441,860 KB sentences was the whole ballgame. At v1
scale the model was not usable at any hyperparameter setting. The bottleneck was data,
not capacity — 600M was nowhere near saturated.
DoRA over OFT. Head-to-head at this data scale, DoRA beat OFT by 3.2 chrF. OFT was
theoretically attractive (it better preserves the pretrained Turkic manifold) but lost on
effective capacity.
Domain diversity, not just volume. Adding one year of newspapers — 38,998 sentences,
an 8.8% increase — bought +1.74 chrF. The model's remaining failures were concentrated
exactly where books have no coverage: news register, place names, modern vocabulary.
This was the single best return on effort in the project.
Four epochs, not five. Both training arms peaked at epoch 4 and regressed at epoch 5.
What was tried and did not help
Generated morphological forms as bulk training data. A validated KB morphological
generator (checked cell-by-cell against the apertium-krc FST, 99.17% agreement on 26,396
cells) produced 674k inflected KB/RU word pairs, aligned by shared case. Adding them
nearly doubled the corpus and changed sentence chrF by −0.05 — noise. This was run as
a controlled A/B against the present model on an identical held-out set. This release is
the arm without them. The generator remains useful as an independent output validator;
it is not useful as training data.
Raising training max_length from 128 to 256. 0.1% of pairs exceed 128 tokens.
Turkish-pretrained models as a base. Turkish is Oghuz, Karachay-Balkar is Kipchak; the
documented failure mode is Turkish interference and hallucination.
Adding English to the main training mix. Dilution. For English, pivot at inference
through Russian with a separate model instead.
A methodological note
chrF misled this project three times: a 47.29 that corresponded to poor output; an
evaluation bug that split sentence references on commas and scored against the
best-matching fragment, systematically penalising the more complete model; and a 256-row
smoke checkpoint that scored garbage and was mislabelled as epoch 1. Every headline number
here was re-derived after those fixes, and every model decision was confirmed by reading
actual output. If you evaluate this model, read the output.
Limitations
Not comparable to a high-resource MT system. ~56 chrF on a low-resource pair is a
usable draft, not a publication-grade translation.
Weakest on the word tier (isolated lexicon lookups) and on very long inputs.
Trained overwhelmingly on literary and news prose. Conversational, technical, medical
and legal registers are out of distribution.
Russian-side fidelity is limited by the partly machine-generated Russian in the corpus
(see Training data).
The tsokayushchiy (Cherek) spoken variety is not represented.
No safety or toxicity filtering beyond what facebook/nllb-200-distilled-600M carries.
License
CC-BY-NC-4.0, inherited from facebook/nllb-200-distilled-600M. Non-commercial use only.
An adapter cannot be more permissive than its base.
Citation
bibtex
1@misc{zamaev2026krcru,
2 title = {Karachay-Balkar to Russian machine translation with NLLB-200 and DoRA},
3 author = {Zamaev, Aslan},
4 year = {2026},
5 howpublished = {\url{https://huggingface.co/AslanZamaev/tau-krc-mt-v1}},
6 note = {DoRA adapter on facebook/nllb-200-distilled-600M, 729,650 KB-RU pairs}
7}
Contact
Corrections from Karachay-Balkar speakers are the most useful feedback this model can get —
especially cases where the output is fluent but wrong. Open a discussion on this repo, or
reach Aslan Zamaev through the links on his profile.
The training corpus, the extraction pipeline and the morphological generator are not
published. Only the model weights are released here.
Built on NLLB-200 (NLLB Team et al., 2022). Morphological
validation used apertium-krc.