Fast, lightweight grapheme-to-phoneme conversion using decision trees
Project description
Phonebox: Grapheme-to-Phoneme Conversion
Fast, lightweight grapheme-to-phoneme (G2P) conversion using decision trees and EM alignment. The package also includes MultigramG2P (n:m joint Viterbi) in the library; 1:1 CLI commands use the decision tree path.
Decision-tree G2P is fast, compact, and interpretable; it trades some accuracy
for those properties, and neural G2P methods will generally score better.
CMUdict / PocketSphinx workflows are the main English use case; measured phone
error rates and IPA locale benchmarks are in
docs/G2P_EVAL.md.
Features
- Measured accuracy: reported phone error rates on CMUdict (see docs/BENCHMARKS.md); neural G2P methods can be more accurate
- Compact Models: < 1MB model size for typical 1:1 trees
- MultigramG2P: n:m joint EM + Viterbi decode (
MultigramG2Pin Python API) - Zero Dependencies: Bundled Python executable works standalone
- CMUdict Support: English pronunciation with PocketSphinx compatibility
Installation
pip install phonebox
Or from source:
git clone https://github.com/lenzo-ka/phonebox.git
cd phonebox
pip install -e .
Quick Start
One Command
# Build G2P from CMUdict, bundle as Python executable
phonebox recipe cmudict pocketsphinx -o g2p.py
# Use it
python g2p.py "Hello, world!"
TTS Preset (keeps stress)
phonebox recipe cmudict tts -o g2p.py
Using Bundled G2P
Command Line
python g2p.py "Hello, world!"
# hello HH AH L OW
# world W ER L D
# Raw mode (no text normalization)
python g2p.py -r "Hello,"
Python Library
from g2p import G2PPredictor
g2p = G2PPredictor.from_embedded()
phones = g2p.pronounce("hello") # ['HH', 'AH', 'L', 'OW']
# Process text (tokenizes automatically)
for word, phones in g2p.pronounce_text("Hello, world!"):
print(f"{word}: {' '.join(phones)}")
CLI Commands
Quick Start:
recipe Build complete G2P from dictionary (one command)
Using Models:
pronounce Get pronunciations for words
normalize Preview text normalization/tokenization
bundle Create standalone executable with embedded model
Building Models:
model Model operations (build, train, convert, benchmark)
dict Dictionary operations (fetch, export-vectors)
Low-Level:
align Align letters to phonemes (EM algorithm)
vectorize Convert alignments to feature vectors
Quality:
check Validate lexicon against phoneset
suggest-joins Discover join candidates (multigram EM)
compare 1:1 vs n:m eval (locale or all IPA locales)
train-multigram Train/export MultigramG2P
G2P evaluation (IPA locales)
phonebox compare all # docs/G2P_COMPARE.md
phonebox compare locale --lexicon … --locale it_IT
phonebox train-multigram --locale it_IT --lexicon it_ipa.tsv -o model.g2p.gz
Repo wrappers: compare_g2p_all.py, compare_g2p_sweep.py, dump_units.py.
See docs/G2P_EVAL.md.
Examples
# Preview text normalization
phonebox normalize "Hello, world!"
# Pronounce with existing model
phonebox pronounce hello world -m model.g2p.gz
# Benchmark model
phonebox model benchmark model.g2p.gz
# Fetch dictionary manually
phonebox dict fetch cmudict
Python API
from phonebox import G2P, MultigramG2P
# 1:1 decision tree (CLI: phonebox pronounce)
g2p = G2P(model="model.g2p.gz")
phones = g2p.pronounce("hello")
print(phones) # ['HH', 'AH', 'L', 'OW']
# n:m multigram (train via CLI or library)
mg = MultigramG2P(max_letter_span=2, max_phone_span=2)
mg.train_from_dict("lexicon.tsv")
# phonebox train-multigram … ; phonebox pronounce -m model.g2p.gz (sidecar auto-detect)
# N-best alternatives
for pron, score in g2p.pronounce_nbest("read", n=3):
print(f"{pron} ({score:.3f})")
Step-by-Step Training
For debugging or custom workflows:
# 1. Fetch dictionary
phonebox dict fetch cmudict
# 2. Align letters to phonemes
phonebox align data/cmudict/cmudict.dict -o alignments.txt --remove-stress
# 3. Vectorize alignments
phonebox vectorize alignments.txt -o vectors.txt
# 4. Train from vectors
phonebox model train en_US --vectors vectors.txt -o model.g2p.gz
# 5. Bundle
phonebox bundle model.g2p.gz -o g2p.py
Standalone Deployment
Bundled files have zero dependencies beyond the Python standard library:
phonebox bundle model.g2p.gz -o g2p.py
python g2p.py "test"
Algorithm
- EM Alignment: Expectation-Maximization aligns letters to phonemes
- Feature Extraction: 7-gram letter windows create feature vectors
- Decision Tree: ID3-style tree trained on aligned data
- Prediction: Tree traversal based on letter context
Based on research from CMU:
License
MIT License - see LICENSE file.
Author
Kevin Lenzo (@lenzo-ka)
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file phonebox-0.1.0.tar.gz.
File metadata
- Download URL: phonebox-0.1.0.tar.gz
- Upload date:
- Size: 132.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ea12b767925d54ab9bd18cbf3a5ab17edde8bf4ddb8889d2524e0f870fbfa6c
|
|
| MD5 |
40636c0aa3070a684208ba94d98666f2
|
|
| BLAKE2b-256 |
e29630ad79eef0b157c8c42467fd35a4e58fd3dcedccd8f4c9786ae1b1584200
|
Provenance
The following attestation bundles were made for phonebox-0.1.0.tar.gz:
Publisher:
publish.yml on lenzo-ka/phonebox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
phonebox-0.1.0.tar.gz -
Subject digest:
7ea12b767925d54ab9bd18cbf3a5ab17edde8bf4ddb8889d2524e0f870fbfa6c - Sigstore transparency entry: 2119604071
- Sigstore integration time:
-
Permalink:
lenzo-ka/phonebox@3d57acfa0a60052e17acc6c4376e2cca0276e777 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/lenzo-ka
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3d57acfa0a60052e17acc6c4376e2cca0276e777 -
Trigger Event:
release
-
Statement type:
File details
Details for the file phonebox-0.1.0-py3-none-any.whl.
File metadata
- Download URL: phonebox-0.1.0-py3-none-any.whl
- Upload date:
- Size: 130.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fee1d762360ab45ccb66298aca34c99bc086040bb5246bbc9eb70d97e76babb4
|
|
| MD5 |
24cc9fd847cc22f61f924de24816b433
|
|
| BLAKE2b-256 |
92128100da0772564643a17acc70ded1d88ac011a9a37ae62f02927134df5be6
|
Provenance
The following attestation bundles were made for phonebox-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on lenzo-ka/phonebox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
phonebox-0.1.0-py3-none-any.whl -
Subject digest:
fee1d762360ab45ccb66298aca34c99bc086040bb5246bbc9eb70d97e76babb4 - Sigstore transparency entry: 2119604150
- Sigstore integration time:
-
Permalink:
lenzo-ka/phonebox@3d57acfa0a60052e17acc6c4376e2cca0276e777 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/lenzo-ka
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3d57acfa0a60052e17acc6c4376e2cca0276e777 -
Trigger Event:
release
-
Statement type: