# Amharic Text-to-Speech — Namu Internship Project **Goal:** every intern fine-tunes a text-to-speech model that speaks Amharic (አማርኛ), listens to the result, and measures honestly whether it got better. **Team:** 6 interns, one model each · **Duration:** 2 weeks (10 working days) · **Level:** beginner (no prior speech-ML experience assumed) This is **not** an attempt at state of the art, and it never will be. It is an introduction with three aims: see how fine-tuning actually works, hear the result of your own work, and experiment with a real TTS model. --- ## Read in this order | # | Document | What it gives you | |---|---|---| | 0 | [Project brief](docs/00_PROJECT_BRIEF.md) | Why this project, what "done" means, what is deliberately not the goal | | 1 | [Background](docs/01_BACKGROUND.md) | Amharic + TTS primer, what to read on which day | | 2 | [Datasets](docs/02_DATASETS.md) | Every candidate corpus, measured, and which one was pre-picked for you | | 3 | [Team & tasks](docs/03_TEAM_AND_TASKS.md) | Six individual owners, three cross-cutting duties, review buddies | | 4 | [Timeline](docs/04_TIMELINE.md) | Day 0 pre-bake plus 10 days, with the gate at the end of each | | 5 | [Evaluation](docs/05_EVALUATION.md) | Noise floor, ASR floor, CER harness, MOS-lite blind A/B | | 6 | [Setup](docs/06_SETUP.md) | Colab-only environment, exact commands | | 7 | **[Gotchas](docs/07_GOTCHAS.md)** | **The traps that will eat your week. Read before you touch anything.** | | 8 | [Assessment rubric](docs/08_RUBRIC.md) | How the work is assessed | | 9 | [Experiments](docs/09_EXPERIMENTS.md) | The six axes: hypothesis, method, expected result, cost | --- ## The 60-second version We fine-tune [`facebook/mms-tts-amh`](https://huggingface.co/facebook/mms-tts-amh) — an 83M-parameter VITS model that already speaks Amharic, badly — on a cleaned single-speaker Amharic corpus, using [`ylacombe/finetune-hf-vits`](https://github.com/ylacombe/finetune-hf-vits). One run is about 20–25 minutes on a free-tier T4, and the upstream repo reports usable results from as few as 80–150 samples. That is why you get many cycles instead of one. The hard part is **not** the training. It is the data and the text pipeline. Three facts we measured while writing this: 1. **`mms-tts-amh` cannot read Amharic script.** Its vocabulary is 28 tokens — the Latin letters `a–z` minus `v`, plus space, apostrophe, underscore. Ge'ez characters: zero. Its `tokenizer_config` sets `is_uroman: true`, so every input must be romanized with `uroman` before it is tokenized. 2. **Digits are silently deleted.** `"በ2016 ዓ.ም. 25% አድጓል"` reaches the model as `"ba aame adegwaale"`. The year and the percentage are simply gone — no error, no warning, because there are no digits in the vocabulary. Normalize first and the same sentence becomes `"bahulate shihe aseraa sedesete aamata meherate haayaa amesete bamato adegwaale"`, and you can hear the numbers come back. 3. **Amharic homophones romanize inconsistently.** `ሐኪም → "hhakime"` but `ሀኪም → "hakime"`; `ጸሐይ → "tsahhaye"` but `ፀሐይ → "tzahhaye"`. Same sound, different token sequences. Normalization makes them agree. All three are handled by [`src/amharic_normalize.py`](src/amharic_normalize.py), which is written and tested for you. Understanding *why* it exists is most of the learning in this project. You hear all three on Day 1, before lunch. --- ## Before Day 1: the supervisor pre-bake Day 1 ends with every intern listening to their own fine-tuned model. That is only possible because a supervisor did the Day-0 work first. If Day 0 is skipped, Day 1 fails and no amount of intern effort recovers it — see [Day 0 in the timeline](docs/04_TIMELINE.md). What is already built when you arrive: | Artifact | What it is | Why it is not yours to build | |---|---|---| | `Namuorg/mms-tts-amh-train` | `mms-tts-amh` with its GAN discriminator restored | No `amh` `*-train` checkpoint exists on the Hub. `ylacombe` published `*-train` only for eng, spa, tam, guj, mar, kor, fra and acd. Without the discriminator, fine-tuning is impossible. It is a 30-minute job for someone who has done it before, and a two-day job for a beginner. | | `Namuorg/finetune-hf-vits` | Fork of the trainer, dependencies pinned to an exact SHA, romanizer patched to use the `uroman` pip package | Upstream pins nothing, and its Perl romanization path can fail while still exiting 0 — every transcript becomes an empty string, training completes with a falling loss, and the model learns to say nothing. **Never install upstream's `requirements.txt`.** | | Eight `Namuorg/amharic-tts-*` datasets | Pre-built, pre-filtered, pre-normalized training sets at 2 / 10 / 30 / 60 minutes, plus multi-speaker, un-normalized, FLEURS and unfiltered variants | The source corpus is 6.1 GB. Pre-baking turns every experiment axis into a one-line JSON edit instead of a data-engineering project. | | `Namuorg/fleurs-am-floor-50` | The 50 FLEURS test clips the ASR floor needs | Otherwise every intern downloads gigabytes to compute one number that is the same for everyone. | | One pinned Colab notebook | The whole environment for all ten days | It was run top to bottom on a real T4 before you arrived. A notebook that was written but never executed is worth nothing. | | `configs/finetune_amharic.json` | The frozen, validated training config | It already contains `uroman_path`, without which the run raises a `ValueError` the moment preprocessing starts. | | `tools/validate_config.py` | Config checker | The trainer rejects **any** unknown JSON key and gives you an unhelpful error. This one names the offending key in plain English before you burn GPU time. | | `Namuorg/amharic-tts-demo` | Gradio Space template | Duplicate it, change `MODEL_ID`, done in five minutes. | Interns build models, datasets, experiments and findings. Interns do not build infrastructure. --- ## What ships at the end Each intern personally: - a public fine-tuned model on the Hub, under your own username, with a real model card - a dataset repo you built yourself, with filtering choices you chose and can defend - a live Gradio Space pointing at your model - one experiment axis, one finding stated in one sentence, one row in the shared comparison table - a 5-minute talk on Day 10: your before clip, your after clip, your finding, one thing that surprised you The cohort together: - one comparison table with six rows, including each owner's own measured noise floor - one run log covering every run anyone launched across all ten days - one before/after audio wall - one measured ASR floor number, one MOS-lite blind A/B result from 3–5 external native Amharic speakers - one digit-trap demo recording, one written retrospective, one index page There is no slide deck. Six short talks and a live demo instead. --- ## Quickstart (Day 1) Everything runs in Colab. There is no local setup path, and that is deliberate — see [setup](docs/06_SETUP.md) for why. Open the pinned notebook, then clone this repo inside it: ```bash git clone && cd amharic-tts-internship ``` ```bash pip install -r requirements-day1.txt ``` Verify the text pipeline. These are self-testing and need no GPU: ```bash python src/amharic_numbers.py ``` ```bash python src/amharic_normalize.py ``` Then generate your baseline audio and **listen to it**: ```bash python src/baseline_tts.py --out baseline_wavs/ --demo-trap ``` The `--demo-trap` flag renders each sentence twice, with and without normalization. Listen to the pair containing the year and the percentage. You will hear the numbers disappear. That is the project in one listen. Before you train anything, the notebook makes you run the **romanization canary**. If it prints blanks for you, stop and get a supervisor. A model trained on blank transcripts trains happily, shows a falling loss, and says nothing. --- ## Ground rules - **Everything goes on the Hub or in git.** No models or datasets living on someone's laptop. - **Listen first, then look at the number.** Write the ear verdict in the run log before you read the CER. If you see the number first, you will hear the number. - **Measure your noise before you claim your signal.** Every intern reruns one config with only the seed changed. That gap is your noise floor, and you may not claim a difference smaller than it. - **A run that is not in the run log did not happen.** One log, one keeper, no private spreadsheets. - **Nothing gets pushed to the Hub until your review buddy has listened to it** and initialled the run-log row. Buddies rotate every two days. - **Native speakers decide language questions.** Not the loss curve, and not Claude. The Day-8 listening panel must be native speakers who are not you. - **Write down what you tried, including failures.** A null result you measured honestly is a finding and it goes in the table. - **Ask after 30 minutes stuck.** Not after two days. Being stuck silently is the only real failure mode in a ten-day project. --- ## Licensing — read before anything is published `facebook/mms-tts-amh` is **CC-BY-NC 4.0: non-commercial**. Anything fine-tuned from it inherits that. Everything this cohort produces is a learning artifact and a public research artifact, and **cannot ship in a Namu commercial product**. This is decided, not open. It is briefed on Day 1 morning as a real-world constraint you will meet again in your career. Tag every model you push `cc-by-nc-4.0`, and state in your model card what it derives from. See [the brief](docs/00_PROJECT_BRIEF.md#licensing).