Teacher in the Loop
Reliable Distillation of Kokoro-82M into 8M-Parameter Single-Voice Students, in English and Italian
Kokoro-82M's voices af_heart, if_sara and im_nicola as 8M-parameter
students: one 9 MB int8 ONNX graph per voice, more than twenty times faster than real time on one CPU thread.
Paper, training code and inference code for "Teacher in the Loop: Reliable Distillation of Kokoro-82M into 8M-Parameter Single-Voice Students, in English and Italian" (Fabio Angela, 2026), a follow-up to Paradee.
- Try it in your browser: the three voices run on your device (ONNX Runtime Web and eSpeak NG compiled to WebAssembly); nothing you type leaves the browser.
- Listen to the paper's samples: the teacher, Paradee's released decoder, the published recipe and ours on the same held-out sentences.
- Download the weights: int8 and float32 graphs and the PyTorch weights of each voice.
The paper is on Zenodo (10.5281/zenodo.23400040); an arXiv version will follow. The training package was checked against the paper's numbers on a GPU run (paper, Appendix G).
Results at a glance
UTMOS of the decoder alone on the teacher's own features, mean over 200 held-out sentences:
| Voice | Kokoro-82M (teacher) | Paradee, released | Published recipe, our run | This paper |
|---|---|---|---|---|
af_heart (English) |
4.52 | 4.37 | 2.89 | 4.47 |
if_sara (Italian) |
4.02 | – | 2.21 | 3.88 |
im_nicola (Italian) |
3.87 | – | 3.53 | 3.70 |
End to end, with the existing text students, the scores do not drop, and int8 export with per-channel scales costs at most 0.01 UTMOS. Paradee released only an English voice.
Speak
pip install teacher-in-the-loop
titl --voice if_sara "Buongiorno a tutti." -o buongiorno.wav
from titl import Voice, write_wav
voice = Voice.from_pretrained("af_heart") # or "if_sara", "im_nicola"; int8 by default
write_wav("hello.wav", voice("Hello there. This voice has eight million parameters.", speed=1.0))
Each voice is one ONNX graph of about 9 MB (int8 weights) that runs more than twenty times faster than real time
on one CPU thread. Text becomes phonemes as in Kokoro: Misaki for English, Misaki's eSpeak NG backend for Italian.
English also needs spaCy's en_core_web_sm model, which Misaki downloads with pip on first use; to work offline
or without pip, install it beforehand (python -m spacy download en_core_web_sm).
Layout
src/titl/ inference: phonemes, the ONNX voice, command line (pip package teacher-in-the-loop)
training/ the paper's recipe: teacher corpus, text side, teacher pool, decoder stages, export
eval/ evaluation behind the paper's tables, held-out sentences, speed benchmark
tests/ tests of the inference package
paper/ the paper (PDF) and data/, the CSVs behind every table and figure with their sources
hf/ model card of the Hugging Face weights repository
space/ the Hugging Face Space: in-browser demo (JavaScript phonemes, ONNX Runtime Web) and audio samples
LICENSE Apache-2.0 (Paradee, from which the training code derives, is Apache-2.0), except the sentence
lists in training/data/ and eval/heldout.json: CC BY-SA 4.0 (training/data/LICENSE.md)
NOTICE attribution for Paradee and Kokoro-82M
THIRD_PARTY_NOTICES.md
third-party models, code, Python packages and data, with their licenses
CITATION.cff how to cite this repository and the paper
Converting text to phonemes loads eSpeak NG and phonemizer-fork (GPL-3.0-or-later) and num2words (LGPL-2.1) at
run time. pip installs them as separate packages; this repository does not include them
(THIRD_PARTY_NOTICES.md, section 3).
Scope
Only the distillation of Kokoro-82M's voices af_heart (English), if_sara and im_nicola (Italian): the
revised decoder recipe described in the paper, the existing Paradee text side, the int8 ONNX export, the
evaluation needed to reproduce the paper's tables, and the inference code that runs the released voices.
The paper
paper/Teacher-in-the-Loop-Angela-2026.pdf, also on Zenodo as
10.5281/zenodo.23400040; the LaTeX source will be on arXiv. Every number
in it is in paper/data/, which the paper calls data/; paper/data/SOURCES.md says where each one comes from.
Citation
@misc{angela2026teacher,
author = {Fabio Angela},
title = {Teacher in the Loop: Reliable Distillation of {Kokoro-82M} into {8M}-Parameter Single-Voice
Students, in {English} and {Italian}},
year = {2026},
publisher = {Zenodo},
doi = {10.5281/zenodo.23400040},
url = {https://doi.org/10.5281/zenodo.23400040}
}
Metadata
Release files for teacher-in-the-loop 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| teacher_in_the_loop-0.1.0.tar.gz | 2.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| teacher_in_the_loop-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.1 MB
Release files / teacher_in_the_loop-0.1.0.tar.gz
| Download URL | teacher_in_the_loop-0.1.0.tar.gz |
|---|---|
| Size | 2.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a36c236d83e11606ecf2650337eb51d7cf09a3bc097802bf5c9f99a2c422f069
|
|
BLAKE2b-256 checksum How to use checksums |
d8e88a46779e2c8120d57f70457aaecdad984b6032a64ba81da8c499bdb9b1d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / teacher_in_the_loop-0.1.0-py3-none-any.whl
| Download URL | teacher_in_the_loop-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cefc64dcfee0122d52d07185eabd02c2cadbea3466414ce35f8a195f53f55586
|
|
BLAKE2b-256 checksum How to use checksums |
99cdb9510886ec250fb5f4ec3111e59daffc06300faf0f2546c02e8d5fa1243b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|