Automatic Speech Recognition
Transformers
Safetensors
Arabic
whisper
arabic
dialectal-arabic
asr
Eval Results (legacy)
Instructions to use oddadmix/whisper-small-arabic-dialectal with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use oddadmix/whisper-small-arabic-dialectal with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("automatic-speech-recognition", model="oddadmix/whisper-small-arabic-dialectal")# Load model directly from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq processor = AutoProcessor.from_pretrained("oddadmix/whisper-small-arabic-dialectal") model = AutoModelForSpeechSeq2Seq.from_pretrained("oddadmix/whisper-small-arabic-dialectal") - Notebooks
- Google Colab
- Kaggle
| """Text cleaning / normalization for Arabic multi-dialect ASR. | |
| Design goals for the `oddadmix/dialectal-arabic-lahgtna-v2-*` data: | |
| * Strip tashkil (harakat), dagger-alef and tatweel -> the target is | |
| undiacritized text. | |
| * Remove non-verbal annotation tags like ``[laughter]``, ``[exhale]``, | |
| ``[inhale]``, ``[mumble]`` etc. (anything in square brackets). | |
| * Collapse whitespace. | |
| Deliberately *kept*, because this is a multi-dialect corpus and these carry | |
| real information: | |
| * Dialectal consonants گ ڨ چ پ ژ ڥ ... (Maghrebi / Iraqi / Gulf spelling). | |
| * Sentence punctuation ، ؟ ! . ... (Whisper can and should predict it). | |
| * Latin letters / digits that appear inside transcripts. | |
| Aggressive letter folding (أإآ->ا, ى->ي, ة->ه) is available via | |
| ``normalize_letters=True`` but is OFF by default — for a general multi-dialect | |
| model it tends to hurt real-world output. If you enable it, enable it for BOTH | |
| training targets and evaluation references so WER stays consistent. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| import unicodedata | |
| # --- Arabic diacritics / marks to remove ----------------------------------- | |
| # Harakat + tanwin + shadda + sukun + maddah + combining hamza (064B-0652), | |
| # extra combining marks (0653-065F), superscript "dagger" alef (0670), | |
| # Arabic small high/low Quranic marks (06D6-06ED), and honorific marks | |
| # (0610-061A). Tatweel/kashida (0640) is elongation-only and also dropped. | |
| _DIACRITICS = ( | |
| "ؐ-ؚ" # Arabic honorific / small high marks | |
| "ً-ٟ" # harakat, tanwin, shadda, sukun, combining hamza, ... | |
| "ٰ" # superscript (dagger) alef | |
| "ۖ-ۜ" # small high Quranic marks | |
| "۟-ۨ" | |
| "۪-ۭ" | |
| ) | |
| _DIACRITICS_RE = re.compile(f"[{_DIACRITICS}]") | |
| _TATWEEL_RE = re.compile("ـ+") | |
| # Bracketed non-verbal tags: [laughter], [exhale], [ mumble ], [noise], ... | |
| _BRACKET_TAG_RE = re.compile(r"\[[^\]]*\]") | |
| # Occasionally annotators use <...> or (( )) style tags; strip those too. | |
| _ANGLE_TAG_RE = re.compile(r"<[^>]*>") | |
| # Zero-width / bidi control characters that sometimes ride along in Arabic text. | |
| _ZERO_WIDTH_RE = re.compile("[---]") | |
| _WS_RE = re.compile(r"\s+") | |
| # --- Optional letter folding (OFF by default) ------------------------------ | |
| _LETTER_FOLD = { | |
| "أ": "ا", "إ": "ا", "آ": "ا", "ٱ": "ا", | |
| "ى": "ي", | |
| "ؤ": "و", | |
| "ئ": "ي", | |
| "ة": "ه", | |
| "گ": "ك", "ك": "ك", | |
| } | |
| def remove_diacritics(text: str) -> str: | |
| text = _DIACRITICS_RE.sub("", text) | |
| text = _TATWEEL_RE.sub("", text) | |
| return text | |
| def remove_nonverbal_tags(text: str) -> str: | |
| text = _BRACKET_TAG_RE.sub(" ", text) | |
| text = _ANGLE_TAG_RE.sub(" ", text) | |
| return text | |
| def clean_text(text: str, normalize_letters: bool = False) -> str: | |
| """Full cleaning pipeline. Returns '' if nothing usable remains.""" | |
| if not text: | |
| return "" | |
| # Canonical form first, so precomposed vs. decomposed diacritics behave. | |
| text = unicodedata.normalize("NFC", text) | |
| text = _ZERO_WIDTH_RE.sub("", text) | |
| text = remove_nonverbal_tags(text) | |
| text = remove_diacritics(text) | |
| if normalize_letters: | |
| text = "".join(_LETTER_FOLD.get(ch, ch) for ch in text) | |
| text = _WS_RE.sub(" ", text).strip() | |
| return text | |
| # --- self test ------------------------------------------------------------- | |
| _SAMPLES = [ | |
| "طريقة زوجي، كي رجعت ليه ... عايشين [inhale]", | |
| "مَدارِسْ تقريبًا، وْمُستشفىٰ وَاحِدة فقط [exhale] وكانت الخدمات.", | |
| "شُو فُهُّم عِند الجَمَال؟ ... طلبية كبيرة؟ [laughter]", | |
| "هذيك الشمس خرجت وماذا بيا [mumble] [exhale]", | |
| "المسؤول اللجنة انه يخليه، گال له اني محتاج هذا الراتب", # keep گ | |
| "و كانْ مانْقْدروشْ ... ما عَنْدي حاجة. ڨالي و كانْ [exhale]", # keep ڨ | |
| "[laughter]", # -> becomes empty | |
| "فهَدول الإشياء الكتير مهمين", # multiple spaces | |
| ] | |
| if __name__ == "__main__": | |
| import sys | |
| fold = "--fold" in sys.argv | |
| print(f"clean_text(normalize_letters={fold})\n" + "=" * 60) | |
| for s in _SAMPLES: | |
| out = clean_text(s, normalize_letters=fold) | |
| print(f"IN : {s}") | |
| print(f"OUT: {out!r}") | |
| print("-" * 60) | |