إن orthography2ipa هو حزمة Python قائمة على البيانات الصرفة — JSON تصريحي، ومنطق رفيع قابل للتوصيل، دون أوزان مُدرَّبة — يربط الكتابة الإملائية بأبجدية IPA ويُنمذج كيفية ظهور تلك الفونيمات في السياق. يأتي مزوَّدًا بـ909 مواصفة لغوية تغطي 820 لغة (إضافةً إلى 89 عقدة سلالية للتصنيف فقط) عبر أكثر من 20 عائلة لغوية. ثبّتها، واقرأ البيانات، واعمل fork للبيانات. لا شيء مخفيّ في checkpoint.
إنه طبقة الفونولوجيا الكامنة تحت كل ما يأتي في المراحل اللاحقة: شبكة المرشّحين (lattice) التي يُنتجها يستهلكها واجهة TTS العربية arbtok، ومجموعتا البرتغالية TugaPhone وsilabificador (انظر معالجة اللغة الطبيعية الكلاسيكية لمقاطع وفونيمات البرتغالية)، ومُحوِّل البرانكينهو الفونيمي، ومُحوِّل الميرانديزية الفونيمي، والأساس الفونيمي لـ**TTS الذي يعمل على بطاطس**.
خريطتان، لا واحدة
التمييز الجوهري: خريطة الحروف الكتابية (grapheme map) تخبرك بالفونيمات التي يمكن لكتابةٍ ما أن تمثّلها. أما خريطة التنويعات الصوتية (allophone map) فتخبرك بكيفية ظهور الفونيم في السياق. والخلط بينهما هو أشيع نمط للفشل في أنظمة G2P.
import orthography2ipa
en = orthography2ipa.get("en-GB")
en.graphemes["th"] # ['θ', 'ð'] — one spelling, two possible phonemes
en.allophones["t"] # ['t', 'tʰ', 'ʔ', 'ɾ'] — one phoneme, four realisations
إن ⟨th⟩ في الإنجليزية غامضة حقًا بين /θ/ و/ð/ — وهذه حقيقة تخص العلاقة بين الكتابة والفونيم. و/t/ الإنجليزية تظهر بوصفها وقفة بسيطة، أو وقفة مهموسة، أو وقفة حنجرية، أو نقرة (flap) بحسب موضعها — وهذه حقيقة تخص العلاقة بين الفونيم والظهور الصوتي. والإبقاء على الاثنين منفصلين يعني أنه بإمكانك الانتقال من النص → الفونيمات المرشّحة من أجل النسخ الصوتي، ومن الفونيم → الظهور السطحي من أجل نمذجة النطق، دون أن يفسد أحدهما الآخر. بالنسبة إلى TTS، هذا هو الفارق بين لكنة مقنعة وأخرى آلية؛ وبالنسبة إلى ASR، هو الفارق بين معجم يطابق ما يقوله الناس فعلًا وآخر يطابق القاموس.
ما تحمله كل لغة
كل لغة هي dataclass مجمّدة من نوع LanguageSpec، وهي تحمل ما هو أكثر بكثير من قائمة فونيمات: الحروف الكتابية (بما في ذلك الثنائيات والثلاثيات)، وخريطة تنويعات صوتية، وحروف كتابية موضعية (positional graphemes) للتجاوزات الحساسة للسياق (بداية الكلمة، بين الصائتين، قبل /i/)، ونَسَب (ancestry) موزون بأسلاف متعددين، وقواعد سَنْدي (sandhi rules) عبر الكلمات، ومخزون نبري (tone inventory) اختياري، والمصدرية (provenance) — QualityTier يتدرج عبر stub → skeleton → research → production، وScriptType (أبجدي، abjad، abugida، …)، ومصادر ببليوغرافية بإحالات إلى أرقام الصفحات.
قاعدة الإدراج صارمة وجديرة بالتصريح بها بوضوح: لا يدخل إلا التطابقات المؤسَّسة على الإملاء الرسمي والقواعد النحوية المُوثَّقة. أما قواعد السلاسل الجزئية الاعتباطية فمُستبعَدة. إن ⟨lh⟩ البرتغالية، و⟨sch⟩ الألمانية، و⟨th⟩ الإنجليزية موجودة لأنها وحدات إملائية معيارية. أما الاستدلالات المريحة-لكن-المُختلَقة فليست كذلك. وعندما تعلن مواصفة عن حروف كتابية دون خريطة تنويعات صوتية صريحة، تُشتَقّ خريطة هوية أساسية — إذ يكون كل فونيم على الأقل ظهوره السطحي الخاص — بحيث لا يختفي شيء بصمت.
تحصل التنويعات الإقليمية على مواصفاتها الخاصة بدلًا من راية (flag) على أصلٍ أب. تتباعد البرتغالية البرازيلية والأوروبية بصورة منهجية، ولذا فهما كائنان LanguageSpec متمايزان مرتبطان بالنَسَب:
pt_br = orthography2ipa.get("pt-BR")
pt_br.graphemes["t"] # ['t', 't͡ʃ'] — palatalisation before /i/
تظل أشجار اللهجات قابلة للصيانة لأن ملفات JSON تدعم وراثة graphemes_base / allophones_base: إذ يعلن التنويع عمّا يختلف فيه عن أصله فقط. والسلالة موزونة وبأسلاف متعددين — أب، وركيزة (substrate)، وطبقة عليا (superstrate)، وطبقة مجاورة (adstrate) — وهي الطريقة الأمينة لنمذجة اللغات التي هي نواتج تماس لا أحفاد صرفاء.
عمق على الأرض، لا اتساع فحسب
رقم الـ 820 هو الاتساع؛ أما العمق فهو حيث يكمن الجهد. تمضي المواصفات لهجةً لهجةً حيثما تمضي الأدبيات اللهجية، وكل واحدة منها مُستشهَد بها إلى تلك الأدبيات بإحالات إلى أرقام الصفحات، لا مُستنبطة بالمطابقة النمطية من جدول فونيمات.
إن تغطية شبه الجزيرة الإيبيرية هي المثال الأوضح: أكثر من 100 مواصفة للغات شبه الجزيرة. كل لغة رومانسية في إسبانيا — القشتالية، والكتالانية/الفالنسية، والغاليسية (بمعياريها: RAG والإدماجي)، والأستورية، والأراغونية وتنويعات أوديتها (Ansotano و Chistabín و Benasqués…)، والإكستريمادورية — إلى جانب الباسكية، والكريولات الإيبيرية-الرومانسية، والطبقات التاريخية التي تتجاهلها معظم الموارد كليًا: العربية الأندلسية والمُستعرَبية (Mozarabic). ويحمل الجانب العربي 34 لهجة (من النجدية والحجازية مرورًا بالشامية والمغاربية وتنويعات شبه الجزيرة)، والجانب اللوسوفوني 46 لهجة برتغالية-ولغات-البرتغال، وصولًا إلى الريونوريزية والغوادراميليزية واللهجات الفرعية الميرانديزية.
وعلى حد علمنا، فإن عددًا من هذه هو أول فونولوجيا قابلة للقراءة الآلية تُنشَر على الإطلاق للتنويع — بمعنى مواصفة مُبنيَنة ومُتحقَّق منها بمخطط للحروف الكتابية/الألوفونات يستطيع برنامج ما استعلامها، بخلاف قائمة فونيمات موصوفة فقط نثرًا في الأدبيات اللهجية — الريونوريزية والغوادراميليزية من بينها. وتأتي الأعمال اللاحقة بأول معاجم IPA لـالبرانكينهو والميرانديزية.
شبكة مرشّحين، لا تخمين واحد
الكتابة الإملائية ليست مسألة تقطيع نظيفة، ولذا فإن البنية الرائدة هي شبكة مرشّحين (candidate lattice). يقوم PhonetokTokenizer بتقطيع الحروف الكتابية بأسلوب maximal-munch — مفضّلًا بشراهة أطول وحدة إملائية مطابقة — وينتج، فوق جدول الحروف الكتابية للمواصفة، شبكةً لكل موضع من مرشّحي IPA المرتّبين بدلًا من مخرج وحيد هشّ:
from orthography2ipa.phonetok import PhonetokTokenizer
tok = PhonetokTokenizer(orthography2ipa.get("en-GB"))
tok.ipa_best("through") # 'θɹɔː'
for path in tok.ipa_beam("through", beam_width=8):
print(path.ipa, path.score) # θɹɔː 0.0, ðɹɔː 1.0, θɹoʊ 1.0, …
الشبكة هي العقد الذي تبني عليه العائلة اللاحقة بأكملها. يستهلك محرّك خاص بلغةٍ ما الشبكةَ المشتركة ويضيف فقط الفونولوجيا التي يعجز جدول ساكن عن التعبير عنها، مبقيًا كل مستهلك على النواة المؤسَّسة نفسها:
- يبني arbtok فونولوجيا TTS العربية على الشبكة، مضيفًا إدغام الحروف الشمسية، وحذف همزة الوصل، والتضعيف والتعامل مع الليغاتورات (ligatures) — واندماجًا جديدًا بين الرواة والشبكة (rawi-lattice fusion) يستعيد الصوائت القصيرة المفقودة من النص اللهجي غير المشكول عبر تسجيل توزيع مجموعة نماذج (ensemble) لكل محرف في إطار ترخيص اللهجة المطلوبة، بدلًا من الوثوق بمولّد حر.
- يستهلك كل من TugaPhone، و**mwl_phonemizer** (الميرانديزية)، و**g2p_barranquenho** نفس النواة القائمة على الشبكة (lattice-core) لتنويعاتها اللوسوفونية.
قياس المسافة بين اللغات
بما أن البيانات مُهيكَلة لا مخبوزة في أوزان، يمكنك مقارنة اللغات مباشرةً. تمتد مقاييس المسافة عبر أبعاد المخزون والحرف الكتابي والتنويع الصوتي والنَسَب، إضافةً إلى عائلة منفصلة لمسافة نظام الكتابة:
from orthography2ipa.distance import phonological_distance
d = phonological_distance(orthography2ipa.get("pt-BR"), orthography2ipa.get("pt-PT"))
d.combined # 0.0515 — near-identical
d.inventory.feature_mean # phoneme-inventory distance
d.grapheme.mean_ipa_distance # grapheme-mapping divergence
d.allophone_sim # allophone-overlap similarity
تُكشَف متجهات السمات أيضًا، بحيث يستقر زوج شبه متطابق كالمعيارين البرتغاليين عند 0.0515، بينما تنفصل الأزواج المتباعدة حقًا بوضوح. وهذا مفيد لقرارات نقل التعلّم (transfer learning)، وللإقلاع الأولي للغات شحيحة الموارد، ولقياس اللهجات (dialectometry) على حد سواء.
كيف نعرف أن البيانات جيدة
يكاد لا يوجد “ذهب (gold)” موثوق لـ G2P — فمعظم المجموعات العامة هي مخرجات مُحوِّل فونيمي نفسه مُعادة الاستخدام مرجعًا، ولذا فإن معدّل خطأ منخفض مقابلها يعني “يتفق مع تلك الأداة”، لا “صحيح”. نحن صريحون في هذا الشأن، وبنينا منهجية تحقّق حوله بدلًا من الإبلاغ عن رقم مُطرٍ وحيد.
بالنسبة إلى التنويعات التي تهمّنا أكثر، فإن الذهب مُؤلَّف، لا مكشوط: مجموعة جُمل مثبّتة على المحرّك لكل لهجة، تُحكَّم في أزواج عمياء (blind pairs)، وتُفصَل مقابل أدبيات مثبّتة على الصفحة، وتُعاد عبر فئات تصحيح (correction classes) إلى حلقة تغذية راجعة للمحرّك — وأي خلاف بين مخرج المحرّك والصورة المصحّحة هو دليل على علّة فعلية في المواصفة. وعبر ذهب TTS المثبّت على المحرّك وشواهد المصادر الأولية توجد عدة آلاف من الصفوف المُتحقَّق منها. والتأطير صريح عمدًا بشأن المصدرية: اصطناعي ومُحكَّم أدبيًا حيث لا يوجد سوى ذلك، وذهب بشري حقيقي حيث يوجد — مجموعة الميرانديزية mirandese_g2p من الناطقين الأصليين، وشواهد المصادر الأولية المثبّتة على الصفحة، والمساهمات الأصلية. وتُقدَّم دعاوى الدقة فقط مقابل الذهب البشري؛ إذ إن درجة كاملة مقابل مسوّدة المحرّك نفسه لن تعني شيئًا.
تُقرأ الأرقام على أنها اتجاهية ومُستشهَد بها دائمًا إلى مصدرها (docs/scoreboard.md، وdocs/benchmarks.md، ووثائق مقاييس المستودعات اللاحقة):
- اللهجات العربية، مُدخَل عارٍ غير مشكول — الحالة الصعبة الواقعية للنشر. على ذهب TTS ذي المُدخَل العاري لـ arbtok (33 لهجة)، يبلغ اندماج الرواة والشبكة في إطار ترخيص اللهجة متوسط PER قدره 0.189، متفوّقًا على نفس المجموعة (ensemble) المُشغَّلة كمولّد حر (0.193)، مع تركّز الهامش على اللهجات الأكثر تباعدًا عن الفصحى (MSA). وعلى معظم اللهجات يتفوّق arbtok على espeak-ng في المُدخَل العاري؛ أما على الفصحى نفسها، فما زال espeak — المضبوط على الفصحى — يفوز (espeak 0.176 مقابل arbtok 0.245).
- اللهجات العربية، مُدخَل مشكول — مع وجود العلامات يستقر PER لـ arbtok عند 0.01–0.08 لكل لهجة، وهو أقل بكثير من صوت الفصحى الوحيد لـ espeak (مثلًا النجدية 0.009 مقابل espeak 0.221؛ المصرية 0.027 مقابل espeak 0.287). ليس لـ espeak أصوات لهجية، ولذا فهذه مقارنة تفاح-ببرتقال بأمانة — لكن الفجوة هي المقصد.
- البرتغالية، مقابل ذهب بشري خبير — تستقر البرتغالية الأوروبية اللشبونية عند PER قدره 0.029 (تطابق تام بنسبة 88%) على مصادر أولية مثبّتة على الصفحة، والذهب الميرانديزي من الناطقين الأصليين عند 0.146.
كل واحدة من هذه خاصية للحالة الراهنة للبيانات، مُقاطَعة مع فترة ثقة بالإقلاع الأولي (bootstrap confidence interval)، لا كأس تصدّرٍ في لوحة صدارة. وحيث تكون الفترة واسعة أو العيّنة ضئيلة، تصرّح لوحة النتائج بذلك.
واجهة سطر الأوامر (CLI)
كل ما سبق متاح دون كتابة Python. يأتي سكربت الطرفية orthography2ipa مزوَّدًا بـlist وinfo وtranscribe وdistance، ويقبل كل أمر فرعي --json للتوجيه إلى pipeline.
orthography2ipa list --family Romance
orthography2ipa info pt-BR --graphemes
orthography2ipa transcribe en-GB "through" --beam 8
orthography2ipa distance es-ES it-IT --json
لماذا تهمّ البيانات الصرفة
مجموعة المواصفات بأكملها مُتحقَّق منها بمخطط — dataclasses مجمّدة على غرار pydantic، تمسحها مجموعة اختبارات تكامل، مع SCHEMA.md الذي يوثّق البنية. وحيث يعجز جدول ساكن حقًا عن التعبير عن القواعد، يندرج منطق خاص باللغة حول البيانات: إذ تُسجَّل مُقطِّعات المقاطع عبر مجموعة entry-point، وتبني المحرّكات الأثقل على الشبكة المشتركة في المراحل اللاحقة.
ليس ثمة نموذج غامض يقرّر كيف تبدو أصوات لغات مستخدميك. فالتطابقات قابلة للتدقيق، والمصادر مُستشهَد بها إلى الصفحة، وإضافة لغة هي كتابة ملف JSON واحد مُتحقَّق منه — ابدأ من docs/adding_a_language.md ودليل البدء. وبالنسبة إلى كل من يبني TTS أو ASR أو NLP فونيتيًا ويرفض إسناد فونولوجيته إلى صندوق أسود — ويريدها تعمل على عتاده الخاص — فهذا هو المقصد. إنه بترخيص Apache 2.0، وهو ملكك لتفحصه وتوسّعه وتستضيفه ذاتيًا.