Phonetic similarity and homophone detection library for Python — near-homophones, sound-alike collisions, and variant generation.
- Four scoring algorithms (all normalized 0.0–1.0):
- PPC-A — Positional Phoneme Correlation (Absolute)
- PLD — Phoneme Levenshtein Distance at syllable level
- PED — Phoneme edit distance at phoneme level
- LCS — Longest Common Subsequence ratio on phoneme sequences
- Composite scoring with configurable weights
- Exact homophone discovery via CMU Pronouncing Dictionary inversion
- Near-homophone search with threshold-based fuzzy matching
- Variant generation — phonetic substitutions, morphological variants, and separator permutations
- Compound word splitting with homophone permutation recombination
- Fast fallback encoder for words not in the dictionary (brand names, neologisms)
- Batch collision scanning — forward and reverse scanning pipelines
- LLM-powered deep analysis (optional, via Anthropic/OpenAI API or local agents)
- Rich CLI with formatted tables and JSON output
pip install phonemenal
# With LLM support
pip install phonemenal[llm]from phonemenal import similarity, homophones, variants, splitting, fallback, scanning
# Compare two words (all scores 0.0–1.0)
similarity.ppc("crowd", "crown") # PPC-A
similarity.pld("elastic", "fantastic") # PLD
similarity.ped("cat", "bat") # PED
similarity.lcs("packaging", "packages") # LCS
similarity.composite("crowd", "crown") # Weighted average
# Find exact homophones
homophones.find("blue") # → ["blew"]
# Find near-homophones
homophones.find_similar("crowd", min_score=0.7)
# Generate sound-alike variants
variants.generate("flask") # → {"phlask", "flazk", ...}
variants.generate_morphological("packaging") # → {"packaged", "packager", ...}
# Split compound words & generate permutations
splitting.split("bluevoyage") # → ["blue", "voyage"]
splitting.homophone_permutations("bluevoyage") # → all recombinations
# Fallback for non-dictionary words
fallback.phonetic_key("numpy") # → "nAmpY"
fallback.phonetic_key("numpie") # → "nAmpY" (same key)
# Batch collision scanning
matches = scanning.scan(
candidates=["numpie", "phlask"],
known_names=["numpy", "flask"],
)
# Composite tuning for CMU-backed comparisons
matches = scanning.scan(
candidates=["cat"],
known_names=["bat"],
use_composite=True,
edit_mode="length",
)phonemenal similarity crowd crown # compare with all algorithms
phonemenal similarity crowd crown -a ppc # specific algorithm
phonemenal homophones blue # exact homophones
phonemenal variants flask -m # phonetic + morphological variants
phonemenal split bluevoyage -p # split & show permutations
phonemenal compare crowd crown # full comparison report
phonemenal compare crowd crown -j # JSON output
phonemenal analyze numpy --provider anthropic # LLM deep analysis
phonemenal prompt numpy | pbcopy # get raw promptBuilds positional phoneme combinations by traversing forward and reverse directions with padding, then measures set intersection. Captures how much of the positional phoneme structure two words share.
Syllable-level edit distance using the CMU dict's stress markers to split phonemes into syllable groups. Each syllable is an atomic unit, so the distance reflects how many whole syllables differ — matching how sound flows in speech.
Phoneme-level edit distance on stress-stripped CMU pronunciations. This complements PLD for short and monosyllabic words where syllable-level scoring is too coarse.
Ratio of the longest common subsequence length to the total sequence length. Applied to phoneme sequences from CMU dict, or to raw character strings as a fallback.
Weighted average of PPC-A, an adaptive edit channel, and LCS. By default the edit channel uses max(PLD, PED), and callers can switch to a length-based selector for monosyllables vs. longer words. Default weights are (1.0, 2.0, 1.0) to emphasize edit similarity. All bounded 0.0–1.0.
Note: the default composite score changed in 0.2.0, so scores are not directly comparable with 0.1.x.
Simplified Metaphone-inspired encoding for words not in the CMU dict. Applies digraph replacement, vowel normalization, and character collapsing to produce phonetic keys. Sound-alike names produce the same or similar keys — e.g. numpy and numpie both map to nAmpY.
Full documentation is available at brokensound77.github.io/phonemenal.
Apache-2.0
This project stems from previous research on homophonic collisions conducted by Reagan Short and Justin Ibarra. You can check out our TROOPERS 2023 talk: Homophonic Collisions: Hold me closer Tony Danza for more background on the problem space and their approach to phonetic similarity detection.