Spaces:
Running
Running
| # finetune/purity.py | |
| """Bengali script-purity quality gate for teacher labels. | |
| The teacher (Gemma) writes mostly clean Bengali, but occasionally code-switches | |
| (e.g. a stray Latin or Cyrillic word — we saw `зеленая` leak once). Distillation | |
| caps the student at the label quality, so we filter/repair bad labels before | |
| training. This is the gate referenced in the Bengali-quality investigation. | |
| Heuristics only — no model needed. A human Bengali speaker should still spot-check | |
| a sample of what passes. | |
| """ | |
| import re | |
| import unicodedata | |
| # Bengali Unicode block: U+0980–U+09FF. | |
| _BENGALI = re.compile(r"[ঀ-]") | |
| # Letters from other scripts that must NOT appear in a Bengali story body. | |
| _LATIN = re.compile(r"[A-Za-z]") | |
| _CYRILLIC = re.compile(r"[Ѐ-ӿ]") | |
| # Allowed non-letter noise: digits, whitespace, common punctuation, emoji, danda. | |
| _ALLOWED_NONLETTER = re.compile(r"[\s\d\.,!?…\"'“”‘’—\-–—:;()।॥☀-➿\U0001F300-\U0001FAFF]") | |
| def script_stats(text: str) -> dict: | |
| """Counts of Bengali vs foreign letters and the Bengali-letter ratio.""" | |
| text = unicodedata.normalize("NFC", text or "") | |
| bengali = len(_BENGALI.findall(text)) | |
| latin = len(_LATIN.findall(text)) | |
| cyrillic = len(_CYRILLIC.findall(text)) | |
| letters = bengali + latin + cyrillic | |
| ratio = (bengali / letters) if letters else 0.0 | |
| return { | |
| "bengali": bengali, | |
| "latin": latin, | |
| "cyrillic": cyrillic, | |
| "foreign": latin + cyrillic, | |
| "bengali_ratio": round(ratio, 4), | |
| } | |
| def is_clean( | |
| text: str, | |
| min_bengali_ratio: float = 0.98, | |
| max_foreign_letters: int = 0, | |
| min_length: int = 40, | |
| ) -> tuple[bool, dict]: | |
| """Decide whether a teacher label is clean enough to train on. | |
| Defaults are strict: essentially zero foreign-script letters. Loosen | |
| max_foreign_letters to 1–2 if you'd rather repair than drop. | |
| Returns (ok, stats). | |
| """ | |
| stats = script_stats(text) | |
| ok = ( | |
| len((text or "").strip()) >= min_length | |
| and stats["foreign"] <= max_foreign_letters | |
| and stats["bengali_ratio"] >= min_bengali_ratio | |
| ) | |
| return ok, stats | |
| def foreign_words(text: str) -> list[str]: | |
| """Return whitespace tokens that contain any Latin/Cyrillic letter — useful | |
| for eyeballing exactly what leaked (e.g. ['зеленая']).""" | |
| out = [] | |
| for tok in (text or "").split(): | |
| if _LATIN.search(tok) or _CYRILLIC.search(tok): | |
| out.append(tok) | |
| return out | |
| if __name__ == "__main__": | |
| samples = { | |
| "good": "আচ্ছা রূপা, চোখ বুজে নাও। চাঁদমামা হাসছে, পুকুরের ধারে ঘাস দুলছে। শুভরাত্রি।", | |
| "leak": "দেখছো зеленая গোল বলটা? ওটা রূপার প্রিয় খেলনা সবুজ আপেল!", | |
| "english": "Once upon a time there was a small red house under the sun.", | |
| } | |
| for name, s in samples.items(): | |
| ok, stats = is_clean(s) | |
| print(f"{name:8} ok={ok!s:5} {stats} leaks={foreign_words(s)}") | |