Restore diacritics and tone marks on text that was typed, scraped, or keyed in without them, across 11 languages from Yorùbá and Igbo to Vietnamese, Polish and Arabic.
Almost nobody types diacritics. Phone keyboards make them slow, legacy databases strip them, and OCR of older print drops them entirely. The result is an archive where "ọkọ" (husband), "oko" (farm), and "òkò" (stone) all collapse into the same string.
For a publisher that means unreadable copy. For an archive it means text that no longer says what the author wrote. For any search index built on top, it means queries that silently fail to match.
Restoring the marks by hand is a proofreading job measured in person-months, and it needs speakers of every language involved. Handing it to a general-purpose generative model trades one problem for another: anything that writes the sentence out again can also reword it.
diacnet-2.0 (582M) is the most accurate Olaverse diacritizer on 8 of 10 languages, mean DER 0.0117. diacnet-mini-2.0 (300M) keeps the same features at half the size, mean DER 0.0141. diactag-2.0 (37.9M) tags characters instead of generating text, is strongest on Igbo, Vietnamese and Modern Standard Arabic, and runs on a CPU.
diacnet-2.0Pass one of the eleven language tags, or leave it out. diacnet-2.0 with <auto> stays within 0.0005 DER of the explicit tag; diactag-2.0 has a built-in language-detection head. One model covers every language, so there is nothing to route between.
diacnet-2.0diactag-2.0 copies the base characters, so its output is always your input with marks added: compliance 1.0000 by construction. diacnet-2.0 generates text, so run its output through the alignment helper on the model card (the SDK does it by default). Every input letter is kept and only the marks are taken, which makes compliance 100% too.
diactag-2.0Some words take different marks for different meanings. diacnet-2.0 accepts meaning hints like [g: ranh=free (time)], which lift Vietnamese ambiguous-word accuracy from 0.63 to 0.90. Marks already in the text are kept (99.9–100%) and the rest are filled in, so half-marked input is completed rather than undone.
diacnet-2.0The Olaverse SDK wraps the models with sane defaults. If you would rather not add a dependency, the second tab is the same pipeline in plain transformers.
from olaverse.nlp import Diacritizer
# Most accurate: diacnet-2.0 (output is aligned by default, so only marks change)
d = Diacritizer(model="diacnet-2.0", lang="yor", device="cuda") # "cpu", "mps" or "auto"
d.restore("O so fun ara re pe oun ko ni isoro kankan.")
# → 'Ó sọ fún ara rẹ̀ pé òun kò ní ìṣòro kankan.'
# Meaning hints for words whose marks depend on meaning
d.restore("Chi ay chi that su ranh vao nhung buoi toi sau khi da cho con ngu say.",
lang="vie", hints={"ranh": "free (time)"})
# Mixed languages in one batch; "auto" when you don't know
d.restore_batch(texts, lang=["yor", "ara", "auto"])
# CPU serving: diactag-2.0 never alters letters, int8 ONNX (pip install "olaverse[onnx]")
fast = Diacritizer(model="diactag-2.0", lang="yor", onnx=True)
fast.restore("se eranko naa si gbo o?") # → 'ṣé ẹranko náà sì gbọ́ ọ?'Every language the models in this pipeline were trained on, with the codes you pass and the codes you get back.
All three models cover the same eleven. Scoped deliberately to languages where diacritics are lexically meaningful. Arabic has its own page, since vowel marks work differently there.
Every figure on this page comes from the published model cards. Download the weights and check us.
Restore Arabic tashkīl, with or without case endings, for text-to-speech, teaching material and readable copy, from models that also cover ten other languages.
/ Search & retrievalRestore the marks your documents lost, then match on an accent-folded key, so a user typing "oko" finds "ọkọ" and still sees it written properly.
The weights are open, so you can build it yourself this afternoon. If you would rather we tuned it to your domain, evaluated it properly, and handed it over, tell us what you are working on.