Models Jul 14, 2026 4 min read

    Introducing diacnet-1.0: One Model, Ten Languages, and an Honest Look at What It Can (and Can't) Do Yet

    OO
    Olumide Ola
    Olaverse Lab
    Introducing diacnet-1.0: One Model, Ten Languages, and an Honest Look at What It Can (and Can't) Do Yet

    Diacritics carry real meaning. In Yorùbá, the same base letters can spell three different words depending on the tone marks: ogun (war), ògùn (medicine), ogún (twenty). In Vietnamese, Polish, and Turkish, dropping accents doesn’t just look wrong, it can make text ambiguous or outright unreadable. Yet diacritics are exactly what gets lost the moment text is typed on a non-native keyboard, scraped from the web, or transcribed casually.

    diacnet-1.0, built by Olaverse, is a single model that restores diacritics across 10 languages spanning West Africa, Europe, and Southeast Asia, Yorùbá, Vietnamese, Igbo, Hausa, Polish, Turkish, Portuguese, Spanish, French, and Italian, without needing a separate model or vocabulary per language.

    It’s live now on Hugging Face: olaverse/diacnet-1.0

    How it works

    diacnet is fine-tuned from google/byt5-small, a byte-level sequence-to-sequence model. Working at the byte level rather than the word level means the same mechanism handles Yorùbá tone marks, Vietnamese combining diacritics, and Polish or Turkish special characters, no per-language vocabulary needed.

    A language tag prefix (<yor>, <vie>, <pol>, etc.) tells the model which diacritic inventory to apply to a given input, so one joint model covers all 10 languages instead of ten separate ones.

    Training is fully self-supervised: clean, already-diacritized text is the target, and diacritics are deterministically stripped to create the training input. No manual annotation required.

    from transformers import AutoTokenizer, T5ForConditionalGeneration
    
    tok = AutoTokenizer.from_pretrained("olaverse/diacnet-1.0")
    model = T5ForConditionalGeneration.from_pretrained("olaverse/diacnet-1.0")
    
    text = "<yor> se eranko naa si gbo o?"
    inputs = tok(text, return_tensors="pt")
    output_ids = model.generate(**inputs, max_new_tokens=256)
    print(tok.decode(output_ids[0], skip_special_tokens=True))
    # ṣé ẹranko náà sì gbọ́ ọ?
    

    The benchmarks, tested on real external data

    Early validation numbers looked great: a median character error rate (CER) of about 0.02 across most languages. But that number came from a held-out slice of the same training distribution, machine-generated text, not the messy real-world input diacnet would actually see in the wild.

    So I re-ran evaluation on genuinely external test sets: Tatoeba for Spanish, French, Italian, Portuguese, Polish, Turkish, and Vietnamese; MasakhaNEWS for Igbo and Hausa; and the MENYO-20k test split for Yorùbá, roughly 1,000 diacritic-bearing sentences per language, stripped of diacritics as input, with the original text as ground truth.

    Word error rate (%, lower is better), diacnet-1.0 vs. doing nothing:

    LanguageCopy-input (floor)diacnet-1.0
    Italian14.160.62
    French18.191.45
    Portuguese19.471.61
    Spanish17.382.07
    Polish40.0113.18
    Turkish42.7619.49
    Vietnamese86.2521.60
    Igbo34.118.00
    Yorùbá87.3129.08
    Hausa7.808.27 ⚠️

    The good

    On 9 of 10 languages, diacnet beats the “do nothing” floor by a wide margin. Vietnamese goes from an unusable 86.3 WER to 21.6. Italian drops from 14.2 to 0.6. These are real, reproducible gains on text the model never saw during training.

    The honest middle: Yorùbá

    At 29.1 WER, Yorùbá is a big improvement over doing nothing (87.3), but it’s still behind a dedicated Yorùbá-only specialist, Davlan/mt5_base_yoruba_adr, which scored 16.4 WER on an earlier run of the same test set, despite being roughly twice diacnet’s size.

    The gap isn’t really about model capacity. It’s about ambiguity: the same base letters in Yorùbá can spell multiple valid words depending on tone, and resolving that often requires semantic context a byte-level model trained mostly on machine-generated text hasn’t seen enough of. Closing this gap means more human-authored Yorùbá training data, not just a bigger model.

    The failure: Hausa

    diacnet-1.0 currently does not work for Hausa. It scores slightly worse than doing nothing at all (8.3 vs. 7.8 WER). With only about 15 Hausa examples in the training set, the model never learned Hausa’s hooked-letter inventory (ɓ, ɗ, ƙ) and mostly just passes text through unchanged.

    Don’t use diacnet-1.0 for Hausa diacritic restoration right now. Fixing this is the top priority for the next version.

    Why publish the bad numbers too

    It would have been easy to keep the old ~0.02 CER figure and call it a day, it’s not technically false, just measured on the wrong distribution. But a model that quietly fails on Hausa while claiming “near-perfect restoration” is worse than useless for anyone building on it in production. Anyone integrating this needs to know exactly where it helps and where it doesn’t.

    The evaluation code and test sets are open too, olaverse/diacbench, so these numbers are reproducible and other models can be compared on the same footing.

    What’s next: diacnet-1.1

    • Hausa, train on adequate Hausa data (Wura, MasakhaNEWS), targeting a clear win over the copy-input floor.
    • Yorùbá, incorporate human-authored training text (e.g. the MENYO-20k train split) to close the gap to the monolingual specialist.
    • Turkish/Vietnamese, remaining errors cluster in lexically ambiguous cases; larger-capacity variants are under evaluation.

    Try it, break it, help improve it

    diacnet-1.0 is released under Apache-2.0: huggingface.co/olaverse/diacnet-1.0

    If you have Hausa diacritic data, human-authored Yorùbá text, or want to stress-test the model on real-world messy input, get in touch, we’re actively looking for collaborators and data partners ahead of diacnet-1.1.

    Enjoyed this? Every model we write about is open weight and free to download.

    🤗 Follow on Hugging Face