discharge-simplifier-voice / src /readability.py
rakumar25's picture
Push Discharge Simplifier + Voicemail: real LLM/TTS/translation, faithfulness-check safety net, tests
ec15abf verified
Raw History Blame Contribute Delete
1.43 kB
"""
readability.py — Flesch-Kincaid grade level (no dependencies)
=============================================================
Gives an OBJECTIVE before/after reading grade so the simplification's value is
measurable, not just claimed. That measurable delta is the demo's "wow" and a
useful evaluation metric for the model card.
"""
from __future__ import annotations
import re
_VOWELS = "aeiouy"
def _syllables(word: str) -> int:
word = re.sub(r"[^a-z]", "", word.lower())
if not word:
return 0
count, prev_vowel = 0, False
for ch in word:
is_vowel = ch in _VOWELS
if is_vowel and not prev_vowel:
count += 1
prev_vowel = is_vowel
if word.endswith("e") and count > 1:
count -= 1
return max(1, count)
def _counts(text: str):
sentences = [s for s in re.split(r"[.!?]+", text) if s.strip()]
words = re.findall(r"[A-Za-z]+", text)
n_sent = max(1, len(sentences))
n_word = max(1, len(words))
n_syl = sum(_syllables(w) for w in words)
return n_sent, n_word, n_syl
def flesch_kincaid_grade(text: str) -> float:
n_sent, n_word, n_syl = _counts(text)
grade = 0.39 * (n_word / n_sent) + 11.8 * (n_syl / n_word) - 15.59
return round(max(0.0, grade), 1)
def reading_ease(text: str) -> float:
n_sent, n_word, n_syl = _counts(text)
return round(206.835 - 1.015 * (n_word / n_sent) - 84.6 * (n_syl / n_word), 1)