$ show quadrismegistus/prosodic
Prosodic is a Python library and web application for metrical-phonological analysis of poetry, supporting English, Finnish, and German with flexible language extension. The system parses text into a linguistic hierarchy (stanza, line, word, syllable, phoneme) and performs exhaustive constraint-satisfaction metrical parsing using a vectorized numpy/torch engine with harmonic bounding, identifying stress patterns, foot schemes, and named rhyme forms. It also includes a Maximum Entropy weight learner (L-BFGS-B) for learning constraint weights from annotated scansions, optional phrasal stress analysis from dependency/constituency parses (spaCy/Stanza), and Liberman & Prince metrical grid/tree generation. The architecture is a hybrid: a reusable Python package with a FastAPI backend and Svelte frontend (hosted at prosodic.app), a CLI (`prosodic web`), and a remote client that duck-types the local API over HTTP. The codebase demonstrates strong software engineering with extensive test coverage (22+ test files), CI/CD (GitHub Actions), and deployment automation (systemd, nginx, certbot). Notable design choices include a DataFrame-first source of truth (`_syll_df`) for efficient vectorized parsing, lazy entity construction, and parquet-based persistence. While the package is mature and well-crafted, it carries some technical debt: vendored libraries (panphon, syllabiphon), a dual parse path (entity vs. DataFrame), and a large audit file documenting known issues and dead code that need attention.
The LLM identified 5 files worth highlighting for reuse:
Core parsing engine that evaluates all possible scansions via numpy/torch tensors. Uses an elite pre-screen with transitivity-verified harmonic bounding, then exact pairwise comparison on survivors. Supports GPU (torch) with byte-identical results to CPU. LazyParseList defers Parse object construction, storing only numpy violation arrays. This pattern is self-contained, highly optimized, and reusable for any constraint-satisfaction problem over discrete positions.
Defines all metrical constraints (w_stress, s_unstress, w_peak, foot_size, etc.) via a `@constraint` decorator that attaches a `vectorized` lambda operating on broadcast numpy arrays. Adding a new constraint requires only one function in this file; no changes to the parser vectorized dispatch. This clean separation of concerns makes the constraint set easily extensible and reusable for other linguistic or optimization problems.
Maximum Entropy weight learner for metrical constraints. Loads annotations from CSV/TSV or DataFrames, normalizes column names, handles ragged lines, and splits violation counts into positional zones (e.g., line-initial, medial, final) for zone-aware weights. Uses scipy's L-BFGS-B optimizer with L2 regularization. The `apply_to_meter()` method transfers learned weights back to a Meter object. This pattern is a reusable framework for learning constraint weights from annotated data, applicable beyond poetry to any OT/HG grammar.
Foot parser that segments a scansion string into metrical feet using dynamic programming. Minimizes a cost function based on foot size, period, and extrametricality at edges. Handles catalexis (missing final syllable) and hypermetrical syllables. Validated at 97.5% exact match against hand-tagged gold. The DP formulation is clean, self-contained, and reusable for any segmentation problem with period-based costs.
Rhyme detection using feature-weighted edit distance on IPA rime sequences. Decomposes rime into nucleus and coda, computes phonetic feature edit distance (via vendored panphon), and classifies as perfect, slant, or assonance based on 2-D bands calibrated against Walker's 1775 rhyming dictionary. The `rime_type` property and `rime_distance` method are reusable for any IPA-based rhyme analysis, and the band classification could be adapted to other similarity thresholds.