Tag: Diacnet

  • diacnet-2.0: how we fixed Yorùbá, added Arabic, and removed 90% of our Hausa errors with one function

    diacnet-2.0: how we fixed Yorùbá, added Arabic, and removed 90% of our Hausa errors with one function

    diacnet restores diacritics by rewriting text: a byte-level
    ByT5 model reads <yor> se eranko naa si gbo o? and writes ṣé ẹranko náà sì gbọ́ ọ?. Today we are releasing
    diacnet-2.0 (582M) and
    diacnet-mini-2.0 (300M): 11 languages including Arabic,
    Yorùbá error cut by 60%, and, with one small post-processing step, lower error than our character tagger
    diactag-2.0 on 8 of 10 languages.

    This post is mostly about the three things that went wrong on the way, because each one taught us something.

    1. More data made Yorùbá worse

    diacnet-1.1 was trained on far more Yorùbá text than 1.0, and it got worse at Yorùbá: its diacritic error rate
    rose from 0.155 to 0.201. The cause was measurable. Yorùbá is written with tone marks on almost every syllable,
    but most Yorùbá on the web leaves them out. 1.0 had trained on about 2,000 carefully marked passages
    (average mark density 0.565); 1.1’s much larger web corpus averaged 0.223. The model learned what it saw:
    leave the tones off.

    For 2.0 we attacked the data, not the model:

    •Filter the weak rows. Yorùbá training pairs were kept only if their mark density was at least 0.6× that of well-marked text.

    •Teacher-marked text. We took real Yorùbá, Igbo, Hausa and Arabic news and web text and had a large language model, DeepSeek-V4-Pro, re-mark it in full. A sentence was kept only if the teacher changed marks and nothing else. Where it lightly normalised a sentence (splitting a contraction, say), its version became the target and the input was rebuilt from it, so input and target always match letter for letter.

    •Meaning-dependent words. We generated sentences built around words whose marks depend on meaning (Vietnamese ranh: rảnh “free”, rành “skilled”; Yorùbá ogun: ogun “war”, ogún “twenty”), with an English gloss for each sense.

    The synthetic set came to about 37k pairs. Before choosing the teacher we
    compared several on the same sentences; the gap between two strong teachers was itself informative, at 7.4% of
    Yorùbá letters, 3.4% Igbo and 1.0% Hausa, a useful reminder that even the references a model learns from are
    not perfectly agreed upon.

    2. Our first base model barely learned anything new

    We trained the small model first, from google/byt5-small, and it worked. For the larger model we tried to save
    compute by continuing from diacnet-1.1 with a low learning rate (5e-5). It improved Yorùbá a little and
    learned almost no Arabic: a 0.34 error rate, three times worse than the small model.

    The fix was to stop being clever: we retrained base from google/byt5-base with the small model’s recipe
    (learning rate 2e-4, 2.5M real pairs plus the teacher set, one epoch). The retrained base is now the best model
    in the family on almost every language. Continued training at a cautious learning rate can preserve a model
    so well that it cannot learn a new script.

    3. The model was “wrong” because it was fixing typos

    When we scored diacnet the same strict way we score diactag, Igbo and Hausa looked terrible: about 0.09 and
    0.05 error rate against diactag’s 0.016 and 0.004. Reading the outputs showed why. Most errors were not wrong
    marks. In 4-7% of sentences diacnet had changed a letter, and strict scoring counts every markable letter in
    such a sentence as wrong.

    This was a feature misfiring. diacnet’s training inputs include deliberate typos (7% character noise), so it
    learned to fix spelling as well as add marks. On a benchmark, and in many real pipelines, that is unwanted.

    The fix is a tiny function that runs after generation: line the output up with the input, keep the model’s
    marks on every letter it left unchanged, and fall back to the input letter anywhere it changed, dropped or
    added one. The result is guaranteed to be your text with marks added.

    import difflib, unicodedata as ud
    
    _FOLD = str.maketrans("ɓɗƙƴđıłƁƊƘƳĐŁ", "bdkydilBDKYDL")   # letters with no combining form
    _LETTER = {"ٓ", "ٔ", "ٕ"}                  # Arabic madda / hamza are spelling
    
    def _units(text):
        units = []
        for c in ud.normalize("NFD", text):
            if units and ud.combining(c):
                if c in _LETTER:
                    units[-1][0] += c
                units[-1][1] += c
            else:
                units.append([c, c])
        return [(ud.normalize("NFC", b).translate(_FOLD), ud.normalize("NFC", f)) for b, f in units]
    
    def align(source, output):
        src, out = _units(source), _units(output)
        res = [f for _, f in src]
        sm = difflib.SequenceMatcher(None, [b for b, _ in src], [b for b, _ in out], autojunk=False)
        for a, b, n in sm.get_matching_blocks():
            res[a:a + n] = [f for _, f in out[b:b + n]]
        return "".join(res)
    diacnet-2.0: raw output vs aligned output
    diacnet-2.0RawAligned
    Igbo0.0930.018
    Hausa0.0480.004
    Yorùbá0.0780.070
    Arabic news (WikiNews)0.3440.154

    Hausa error falls by 90%, Igbo by 80%, and Arabic news by more than half, at no training cost. Users who do want
    typo correction can still ask for the raw output.

    Results

    Scored with exactly the code and letter definitions used for diactag-2.0, on 1,000 sentences per language
    from diacbench:

    diacbench: diacnet and diactag
    diacnet-1.1diacnet-mini-2.0diacnet-2.0diactag-2.0
    Yorùbá0.17430.08150.06980.0787
    Igbo0.02190.02020.01850.0162
    Hausa0.00630.00440.00410.0044
    Vietnamese0.03160.02070.01430.0141
    Polish0.00550.00240.00140.0035
    Spanish0.00640.00310.00270.0038
    French0.00280.00130.00120.0017
    Mean, 10 languages0.02610.01410.01170.0130

    (Aligned output, diacbench v1 references; full tables with Turkish, Portuguese and Italian on the model cards.)

    The two approaches now complement each other. diacnet-2.0 leads on Yorùbá and the European languages and
    offers meaning hints and typo correction; diactag-2.0 leads on Igbo, Vietnamese and modern standard Arabic, is
    15 times smaller, and runs in milliseconds on a CPU.

    Arabic is the newest and weakest language for diacnet: error 0.096 on Classical Arabic and 0.154 on modern
    news, behind diactag-2.0. Unlike most open Arabic diacritizers, diacnet was not trained on the Tashkeela
    corpus that the Classical test sets come from, and it offers the same two modes: full, and without
    grammatical case endings.

    Meaning hints: a nudge, not a switch

    You can tell diacnet what an ambiguous word means:

    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)"})
    # 'Chị ấy chỉ thật sự rảnh vào những buổi tối sau khi đã cho con ngủ say.'
    # without the hint: '... rành ...' ("skilled")

    We tested this properly on 580 held-out sentences whose ambiguous spellings never appeared in training. Hints
    lift Vietnamese accuracy on the ambiguous word from 0.63 to 0.90 and Turkish from 0.75 to 0.84. We also tried
    the opposite: give the hint for the word’s other meaning and see whether the output follows it. Usually it
    does not: diacnet switches between a quarter and a half of the time and otherwise trusts the sentence. Hints help when the
    sentence leaves the meaning open; they will not override a sentence that makes it clear. We think that is the
    right behaviour, but it is worth knowing.

    Also in 2.0

    •<auto>: leave the language out and the model infers it, at a cost of at most 0.0005 in error rate.

    •Partial input: marks already in the text are kept (99.9-100% in our tests) and the rest are filled in, so Yorùbá typed with underdots but no tones comes back fully marked.

    •Two sizes: diacnet-2.0 is more accurate everywhere (17% lower mean error); diacnet-mini-2.0 is half the size and within a hair of it on Igbo, Hausa, French, Spanish and Italian.

    Try it

    pip install "olaverse[deeplearning]"
    from olaverse.nlp import Diacritizer
    
    d = Diacritizer(model="diacnet-2.0", lang="yor", device="cuda")   # or "cpu" / "mps"
    d.restore("O so fun ara re pe oun ko ni isoro kankan.")
    # 'Ó sọ fún ara rẹ̀ pé òun kò ní ìṣòro kankan.'
    
    d.restore("وهذا قول مرغوب عنه .", lang="ara", case_endings=False)
    # 'وَهَذَا قَوْل مَرْغُوب عَنْه .'

    The library aligns the output by default (aligned=False returns the raw text) and handles chunking and
    batching. The model cards also show plain transformers usage with the alignment function.

    •Models: olaverse/diacnet-2.0, olaverse/diacnet-mini-2.0

    •Character tagger: olaverse/diactag-2.0

    •Benchmark: olaverse/diacbench

    •Library: olaverse

  • Introducing DiacNet-1.1: Multilingual Diacritic Restoration for 10 Languages

    Introducing DiacNet-1.1: Multilingual Diacritic Restoration for 10 Languages


    Overview

    Diacritics—such as accents, tone marks, and special characters—are essential for clarity, pronunciation, and meaning in many languages. Yet, they are often stripped away in digital text due to technical limitations, user input habits, or data processing errors. This loss can lead to ambiguity, mispronunciation, and even miscommunication.

    Today, we’re excited to introduce DiacNet-1.1, a state-of-the-art model designed to restore diacritics to text across 10 languages in a single, unified system. Developed by olaverse, DiacNet-1.1 is fine-tuned from Google’s ByT5-base (580M parameters) and trained on 7 million sentences of commercially licensed text. Whether you’re working with Yorùbá, Vietnamese, Polish, or Spanish, DiacNet-1.1 can help you recover the nuances of written language with remarkable accuracy.


    Supported Languages

    DiacNet-1.1 supports the following 10 languages:

    • Yorùbá (<yor>)
    • Igbo (<ibo>)
    • Hausa (<hau>)
    • Vietnamese (<vie>)
    • Polish (<pol>)
    • Turkish (<tur>)
    • Portuguese (<por>)
    • Spanish (<spa>)
    • French (<fra>)
    • Italian (<ita>)

    You can also use the <auto> tag to let the model infer the language automatically, with minimal impact on accuracy.


    How It Works

    DiacNet-1.1 is a sequence-to-sequence model that takes stripped text (text without diacritics) and predicts the fully diacritized version. The model is trained on a diverse corpus of web and encyclopedic text, ensuring robustness across different domains.

    Example Usage

    Here’s how you can use DiacNet-1.1 in just a few lines of Python:

    from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
    
    # Load the model and tokenizer
    tok = AutoTokenizer.from_pretrained("olaverse/diacnet-1.1")
    model = AutoModelForSeq2SeqLM.from_pretrained("olaverse/diacnet-1.1")
    
    # Restore diacritics to Yorùbá text
    text = "<yor> se eranko naa si gbo o?"
    inputs = tok(text, return_tensors="pt")
    out = model.generate(**inputs, max_new_tokens=512)
    print(tok.decode(out[0], skip_special_tokens=True))
    # Output: ṣé ẹranko náà sì gbọ́ ọ?

    Language Tagging

    Prefix your input text with the appropriate language tag to guide the model:

    # Vietnamese
    text = "<vie> Toi khong biet tieng Viet"
    # Output: Tôi không biết tiếng Việt
    
    # Polish
    text = "<pol> Lodz jest piekna"
    # Output: Łódź jest piękna
    
    # Auto-detect language
    text = "<auto> El nino esta en la casa"
    # Output: El niño está en la casa

    Performance

    DiacNet-1.1 was evaluated on diacbench, a benchmark of 1,000 held-out sentences per language, sourced independently from the training corpus. The model was tested using the following metrics:

    • DER (Diacritic Error Rate): Errors restricted to diacritic-eligible characters.
    • WER (Word Error Rate): Measures errors at the word level.
    • CER (Character Error Rate): Measures errors at the character level.
    • Exact Match: Percentage of sentences restored perfectly.

    Benchmark Results

    LanguageDERWERCERExact Match
    Italian0.00020.10%0.04%99.3%
    Portuguese0.00311.39%0.23%88.0%
    French0.00530.77%0.18%94.7%
    Polish0.00582.65%0.33%85.3%
    Turkish0.00681.50%0.35%91.7%
    Spanish0.00812.06%0.35%83.0%
    Vietnamese0.046011.98%3.06%36.0%
    Igbo0.05084.78%1.29%41.0%
    Hausa0.05932.53%0.51%59.7%
    Yorùbá0.200642.18%14.50%0.3%

    Note: The lower exact-match scores for Vietnamese and Yorùbá reflect the high density of diacritic marks in these languages. Even a single error can cause the entire sentence to fail the exact-match metric. DER is the most meaningful metric for these languages.


    Improvements Over DiacNet-1.0

    DiacNet-1.1 represents a significant leap forward from its predecessor, DiacNet-1.0, with improvements across multiple languages:

    LanguageDER (1.0 → 1.1)WER (1.0 → 1.1)Verdict
    Vietnamese0.1264 → 0.046021.98% → 11.98%1.1 — 2.7× better
    Turkish0.0447 → 0.006819.20% → 1.50%1.1 — 6.6× better
    Polish0.0357 → 0.005815.12% → 2.65%1.1 — 6.2× better
    Italian0.0015 → 0.00020.66% → 0.10%1.1 — 7.5× better
    Portuguese0.0072 → 0.00311.80% → 1.39%1.1 better
    Spanish0.0084 → 0.00812.19% → 2.06%~equal
    French0.0038 → 0.00531.46% → 0.77%Mixed
    Igbo0.0359 → 0.05088.34% → 4.78%Mixed
    Hausa0.0383 → 0.05938.58% → 2.53%Mixed
    Yorùbá0.1554 → 0.200627.69% → 42.18%1.0 better

    Key Observations

    1. Major Gains: DiacNet-1.1 achieves 2.7× to 7.5× better performance on Vietnamese, Turkish, Polish, and Italian.
    2. Mixed Results: For French, Igbo, and Hausa, the model shows trade-offs between DER and WER. For example, while DER increased slightly for Hausa, WER improved dramatically (8.58% → 2.53%), and exact-match scores jumped from 0% to 59.7%.
    3. Yorùbá Challenge: The model’s performance on Yorùbá regressed due to the lower quality of diacritic annotations in the larger training corpus. DiacNet-1.0 was trained on ~2,000 high-quality Yorùbá passages, while DiacNet-1.1’s corpus, though much larger, had a lower diacritic density. This highlights a critical trade-off: more data isn’t always better if annotation quality suffers.

    Priority for Next Release: Improving Yorùbá, Igbo, and Hausa performance by incorporating higher-quality annotated data.


    Comparison with General-Purpose LLMs

    We benchmarked DiacNet-1.1 against Claude Sonnet 4.5 and GPT-4o-mini on the same diacbench dataset. The results reveal interesting trade-offs between accuracy and reliability:

    Diacritic Error Rate (DER)

    SystemYorùbáIgboHausaVietnamesePolishTurkishPortugueseSpanishFrenchItalian
    Copy-Input (Floor)0.43580.11710.02360.30620.09150.11130.04760.04260.04710.0333
    DiacNet-1.00.15540.03590.03830.12640.03570.04470.00720.00840.00380.0015
    DiacNet-1.10.20060.05080.05930.04600.00580.00680.00310.00810.00530.0002
    Claude 4.5 (Strict)0.33530.22610.35090.02780.03430.02410.01720.02150.11710.0005
    Claude 4.5 (Fallback)0.19130.04270.01780.01070.00350.00190.00110.00400.00520.0005
    GPT-4o-mini (Strict)0.46070.50350.63680.08470.04300.02610.02800.05550.03410.0085
    GPT-4o-mini (Fallback)0.28110.12770.14320.03990.00700.00380.00240.00890.00230.0052

    Key Takeaways

    1. Strict vs. Fallback Scoring:
    • Strict scoring counts all errors, including cases where the LLM rewrites or translates the input.
    • Fallback scoring assumes a pipeline that detects and skips rewritten outputs, focusing only on diacritic restoration.
    1. DiacNet-1.1 vs. Claude (Strict): DiacNet-1.1 outperforms Claude on 8 out of 10 languages when scored strictly.
    2. DiacNet-1.1 vs. Claude (Fallback): With fallback scoring, Claude outperforms DiacNet-1.1 on 9 out of 10 languages. This highlights that while LLMs can achieve higher accuracy on compliant outputs, they fail to return usable text on 20-35% of inputs (e.g., 34% of Hausa, 26% of Yorùbá, 21% of Igbo).
    3. Reliability: DiacNet-1.1 never rewrites or alters base characters in 94.7–100% of cases, depending on the language. In contrast, LLMs alter 20–50% of inputs, making them unreliable for large-scale processing.

    Output Compliance

    SystemYorùbáIgboHausaVietnamesePolishTurkishPortugueseSpanishFrenchItalian
    DiacNet-1.1100%96.3%94.7%99.3%100%99.7%100%99.7%99.7%100%
    DiacNet-1.098.0%99.0%98.3%96.3%99.3%100%99.7%99.7%100%100%
    Claude 4.574.3%79.3%65.7%97.7%96.7%98.0%97.7%98.3%88.3%100%
    GPT-4o-mini68.0%57.3%49.3%93.7%96.0%94.7%97.7%97.3%96.7%99.7%

    Conclusion: If you need maximum accuracy on a few sentences and can tolerate retries, a frontier LLM like Claude may be the best choice. However, if you need to process millions of sentences reliably, deterministically, and offline, DiacNet-1.1 is the tool for the job.


    Training Details

    AspectDescription
    Base Modelgoogle/byt5-base (580M parameters, byte-level)
    Data7.02M sentences from FineWeb-2 (ODC-By) and Wikipedia (CC BY-SA), filtered for diacritic density, NFC-normalized, and deduplicated.
    ObjectiveSequence-to-sequence: <lang> stripped text → fully diacritized text.
    AugmentationPartial stripping (30%), character noise (7%), <auto> tag (12%), optional gloss conditioning (~6%).
    PrecisionBF16, max 512 bytes.
    Correction PassContinued training on high-density Yorùbá with 35% replay of other languages, learning rate 2e-5.

    Note: All training data is commercially licensed. No non-commercial sources (e.g., MENYO-20k, JW300) were used.


    Limitations

    While DiacNet-1.1 is a powerful tool, it has some limitations:

    1. Yorùbá Tone Marks: The model under-marks tones in Yorùbá due to under-annotated training data. Output should not be treated as publication-ready without review.
    2. Irreducible Errors: Stripping diacritics is lossy. For example, in Italian, both Viaggiò (3rd-person past) and Viaggio (1st-person present) reduce to Viaggio—no model (or human) can recover the original distinction.
    3. Proper Nouns: Names and places (e.g., Àlàmú vs. Àlámù) are unreliable due to insufficient context. Foreign names may also be over-nativized (e.g., Vietnamese Tom → Tôm).
    4. Gloss Conditioning: The model supports optional [g: word=meaning] hints, but their effect on diacbench was neutral to slightly negative. This feature is documented but not recommended for general use.
    5. Structural Guarantees: As a seq2seq model, DiacNet-1.1 can alter base characters. However, measured compliance on diacbench is 94.7–100%, so constrained decoding is advisable for high-stakes pipelines.
    6. Register Bias: The model was trained on web and encyclopedic text. Performance on conversational, poetic, or code-switched text is untested.
    7. Benchmark Limitations: The diacbench dataset contains a small number of defective reference sentences (~1%), which slightly caps measured scores.

    Intended Use Cases

    DiacNet-1.1 is ideal for:

    ✅ Restoring diacritics in scraped or user-typed text.
    ✅ Cleaning corpora for downstream NLP tasks.
    ✅ Assisting typing in languages where diacritics are commonly omitted.

    DiacNet-1.1 is not designed for:

    ❌ Text generation.
    ❌ Translation.
    ❌ Spelling correction.
    ❌ General-purpose language modeling.

    Best Practice: Use DiacNet-1.1 with human review for Yorùbá and any application where a wrong tone mark could change meaning.


    Citation

    If you use DiacNet-1.1 in your research or applications, please cite it as follows:

    @misc{diacnet11,
      author = {olaverse},
      title  = {diacnet-1.1: multilingual diacritic restoration},
      year   = {2026},
      url    = {https://huggingface.co/olaverse/diacnet-1.1}
    }

    DiacNet-1.1 is built on ByT5 (Xue et al.), FineWeb-2, and Wikipedia. Please attribute these sources per their respective licenses.


    Try It Yourself

    Ready to restore diacritics to your text? Head over to the DiacNet-1.1 Hugging Face page to explore the model, download it, and start using it in your projects!


    Questions or feedback? Open an issue on the Hugging Face repository or reach out to the olaverse team.

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

    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.