Update app.py
Browse files
app.py
CHANGED
|
@@ -28,121 +28,324 @@ def detect_arabizi(text):
|
|
| 28 |
if not text or len(text.strip()) < 2:
|
| 29 |
return False
|
| 30 |
|
| 31 |
-
# Remove spaces and convert to lowercase for analysis
|
| 32 |
-
clean_text = text.lower().replace(" ", "")
|
| 33 |
-
|
| 34 |
# Check for Arabic script - if present, it's NOT Arabizi
|
| 35 |
arabic_pattern = r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]'
|
| 36 |
if re.search(arabic_pattern, text):
|
| 37 |
return False
|
| 38 |
|
| 39 |
-
# Arabizi indicators
|
| 40 |
-
arabizi_numbers = ['2', '3', '7', '9'
|
|
|
|
|
|
|
|
|
|
| 41 |
arabizi_patterns = [
|
| 42 |
-
'wach', 'wash', 'ach', 'achno', 'chno', 'shno',
|
| 43 |
-
'kif', 'kifash', 'ki', 'kayf',
|
| 44 |
-
'feen', 'fin', 'fen',
|
| 45 |
-
'imta', 'meta', 'waqt',
|
| 46 |
-
'
|
| 47 |
-
'
|
| 48 |
-
'
|
| 49 |
-
'
|
| 50 |
-
'
|
| 51 |
-
'
|
| 52 |
-
'
|
| 53 |
-
'
|
| 54 |
-
'
|
| 55 |
-
'
|
| 56 |
-
'
|
| 57 |
-
'
|
| 58 |
-
'
|
| 59 |
-
'
|
| 60 |
-
'
|
| 61 |
-
'
|
| 62 |
-
'
|
| 63 |
-
'
|
| 64 |
-
'hamdulillah', 'alhamdulillah', # Praise God
|
| 65 |
-
'salam', 'salamu aleikum', # Peace
|
| 66 |
-
'baraka', 'barakallahu', # Blessing
|
| 67 |
-
'yallah', 'yalla', 'hya' # Come on/let's go
|
| 68 |
]
|
| 69 |
|
| 70 |
-
|
| 71 |
-
|
| 72 |
|
| 73 |
-
#
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
-
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
-
#
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
#
|
| 83 |
-
|
| 84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
-
|
| 87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
-
#
|
| 90 |
-
|
| 91 |
-
return True
|
| 92 |
|
| 93 |
-
|
| 94 |
-
|
|
|
|
|
|
|
|
|
|
| 95 |
|
| 96 |
-
#
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
if arabizi_number_count >= 1 or arabizi_word_count >= 1:
|
| 100 |
-
return True
|
| 101 |
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
-
def
|
| 105 |
"""
|
| 106 |
-
|
| 107 |
-
|
| 108 |
"""
|
| 109 |
-
if
|
| 110 |
-
return
|
| 111 |
|
| 112 |
-
#
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
-
#
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
Respond naturally in Arabizi about Moroccan culture, language, and general topics."""
|
| 137 |
-
|
| 138 |
-
elif response_lang == 'arabic':
|
| 139 |
-
return """You are Atlas-Chat, an AI assistant specialized in Moroccan Arabic (Darija). Respond in Arabic script (Darija) as this is what the user is using. Be helpful and culturally aware about Morocco and its traditions."""
|
| 140 |
|
| 141 |
-
|
| 142 |
-
return """You are Atlas-Chat, an AI assistant specialized in Moroccan Arabic (Darija) but also fluent in English. The user has written in English, so respond in English while being knowledgeable about Moroccan culture and language."""
|
| 143 |
|
| 144 |
def chat_with_atlas(message, history):
|
| 145 |
-
"""Generate response from Atlas-Chat model with
|
| 146 |
if not message.strip():
|
| 147 |
return "مرحبا! أهلا وسهلا. Please enter a message! / Ahlan wa sahlan!"
|
| 148 |
|
|
@@ -150,29 +353,22 @@ def chat_with_atlas(message, history):
|
|
| 150 |
# Load model if not already loaded
|
| 151 |
model = load_model()
|
| 152 |
|
| 153 |
-
#
|
| 154 |
-
|
| 155 |
|
| 156 |
-
#
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
enhanced_message = f"""System: {system_prompt}
|
| 163 |
-
|
| 164 |
-
User message (in Arabizi): {message}
|
| 165 |
-
|
| 166 |
-
Remember: Respond ONLY in Arabizi (Latin letters + numbers). Do not use Arabic script."""
|
| 167 |
-
|
| 168 |
-
messages = [{"role": "user", "content": enhanced_message}]
|
| 169 |
else:
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
|
|
|
| 174 |
|
| 175 |
-
# Generate response
|
| 176 |
outputs = model(
|
| 177 |
messages,
|
| 178 |
max_new_tokens=256,
|
|
@@ -184,18 +380,21 @@ Remember: Respond ONLY in Arabizi (Latin letters + numbers). Do not use Arabic s
|
|
| 184 |
# Extract the response
|
| 185 |
response = outputs[0]["generated_text"][-1]["content"].strip()
|
| 186 |
|
| 187 |
-
#
|
| 188 |
-
if
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
return response
|
| 196 |
|
| 197 |
except Exception as e:
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
|
| 200 |
# Create the Gradio interface
|
| 201 |
demo = gr.ChatInterface(
|
|
@@ -204,11 +403,12 @@ demo = gr.ChatInterface(
|
|
| 204 |
description="""
|
| 205 |
**مرحبا بك في أطلس شات!** Welcome to Atlas-Chat! 🇲🇦
|
| 206 |
|
| 207 |
-
|
|
|
|
|
|
|
|
|
|
| 208 |
|
| 209 |
-
|
| 210 |
-
- **Arabizi (3arabi bi 7oruf latin)** → I respond in Arabizi
|
| 211 |
-
- **English** → I respond in English
|
| 212 |
|
| 213 |
**جرب هذه الأسئلة / Try these questions:**
|
| 214 |
""",
|
|
@@ -222,7 +422,11 @@ demo = gr.ChatInterface(
|
|
| 222 |
"What is Morocco famous for?",
|
| 223 |
"Tell me about Casablanca",
|
| 224 |
"كيفاش نقدر نتعلم الدارجة؟",
|
| 225 |
-
"kifash n9der nt3elem darija?"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
],
|
| 227 |
cache_examples=False
|
| 228 |
)
|
|
|
|
| 28 |
if not text or len(text.strip()) < 2:
|
| 29 |
return False
|
| 30 |
|
|
|
|
|
|
|
|
|
|
| 31 |
# Check for Arabic script - if present, it's NOT Arabizi
|
| 32 |
arabic_pattern = r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]'
|
| 33 |
if re.search(arabic_pattern, text):
|
| 34 |
return False
|
| 35 |
|
| 36 |
+
# Arabizi indicators - numbers used as letters
|
| 37 |
+
arabizi_numbers = ['2', '3', '7', '9', '5', '6', '8']
|
| 38 |
+
has_arabizi_numbers = any(num in text for num in arabizi_numbers)
|
| 39 |
+
|
| 40 |
+
# Common Arabizi words and patterns
|
| 41 |
arabizi_patterns = [
|
| 42 |
+
'wach', 'wash', 'ach', 'achno', 'chno', 'shno', 'shkoun', 'chkoun',
|
| 43 |
+
'kif', 'kifash', 'ki', 'kayf', 'kien', 'kima',
|
| 44 |
+
'feen', 'fin', 'fen', 'fain', 'mnin',
|
| 45 |
+
'imta', 'meta', 'waqt', 'mata', 'emta',
|
| 46 |
+
'hna', 'ahna', 'ana', 'nta', 'nti', 'ntuma', 'ntouma',
|
| 47 |
+
'howa', 'hiya', 'huma', 'houma', 'hoa', 'hia',
|
| 48 |
+
'had', 'hadchi', 'hada', 'hadi', 'hadou', 'hadouk',
|
| 49 |
+
'bghit', 'bghiti', 'bgha', 'bghina', 'bghitiou',
|
| 50 |
+
'galt', 'galti', 'gal', 'galet', 'galou',
|
| 51 |
+
'rah', 'raha', 'rahi', 'rahom', 'rahin',
|
| 52 |
+
'kan', 'kanu', 'kana', 'kanet', 'kano',
|
| 53 |
+
'ghadi', 'ghad', 'gha', 'ghadia', 'ghadiyin',
|
| 54 |
+
'daba', 'dak', 'dakchi', 'dik', 'dok',
|
| 55 |
+
'bzf', 'bzzaf', 'bezzaf', 'bzaaaaf',
|
| 56 |
+
'chway', 'chwiya', 'shwiya', 'chwia',
|
| 57 |
+
'khoya', 'khuya', 'akhi', 'kho',
|
| 58 |
+
'khti', 'khtiya', 'ukhti', 'kht',
|
| 59 |
+
'mama', 'baba', 'lwaldin', 'lwalidin',
|
| 60 |
+
'salam', 'salamu aleikum', 'slm',
|
| 61 |
+
'yallah', 'yalla', 'hya', 'aji',
|
| 62 |
+
'mabghitsh', 'mabghach', 'makansh', 'machi',
|
| 63 |
+
'walakin', 'walaken', 'ama', 'mais'
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
]
|
| 65 |
|
| 66 |
+
text_lower = text.lower()
|
| 67 |
+
has_arabizi_words = any(pattern in text_lower for pattern in arabizi_patterns)
|
| 68 |
|
| 69 |
+
# Decision logic
|
| 70 |
+
if has_arabizi_numbers and has_arabizi_words:
|
| 71 |
+
return True
|
| 72 |
+
if has_arabizi_numbers and len([c for c in text if c.isalpha()]) > len(text) * 0.6:
|
| 73 |
+
return True
|
| 74 |
+
if has_arabizi_words and len([c for c in text if c.isalpha()]) > len(text) * 0.7:
|
| 75 |
+
return True
|
| 76 |
|
| 77 |
+
return False
|
| 78 |
+
|
| 79 |
+
def arabizi_to_arabic(text):
|
| 80 |
+
"""
|
| 81 |
+
Convert Arabizi text to Arabic script
|
| 82 |
+
COMPLETE HARD-CODED MAPPINGS
|
| 83 |
+
"""
|
| 84 |
+
if not text:
|
| 85 |
+
return text
|
| 86 |
|
| 87 |
+
# COMPREHENSIVE WORD MAPPINGS (Arabizi → Arabic)
|
| 88 |
+
word_mappings = {
|
| 89 |
+
# Pronouns
|
| 90 |
+
'ana': 'أنا', 'nta': 'نتا', 'nti': 'نتي', 'howa': 'هوا', 'hiya': 'هيا',
|
| 91 |
+
'hoa': 'هوا', 'hia': 'هيا', 'hna': 'حنا', 'ahna': 'أحنا',
|
| 92 |
+
'ntuma': 'نتوما', 'ntouma': 'نتوما', 'huma': 'هوما', 'houma': 'هوما',
|
| 93 |
+
|
| 94 |
+
# Question words
|
| 95 |
+
'shkoun': 'شكون', 'chkoun': 'شكون', 'skoun': 'شكون',
|
| 96 |
+
'achno': 'أشنو', 'chno': 'شنو', 'shno': 'شنو', 'ach': 'أش',
|
| 97 |
+
'wach': 'واش', 'wash': 'واش', 'ouach': 'واش',
|
| 98 |
+
'kifash': 'كيفاش', 'kif': 'كيف', 'ki': 'كي', 'kayf': 'كيف',
|
| 99 |
+
'feen': 'فين', 'fin': 'فين', 'fen': 'فين', 'fain': 'فين', 'mnin': 'منين',
|
| 100 |
+
'imta': 'إمتا', 'meta': 'متا', 'mata': 'متا', 'emta': 'إمتا',
|
| 101 |
+
'3lach': 'علاش', 'alach': 'علاش', '3la ach': 'علاش',
|
| 102 |
+
|
| 103 |
+
# Common verbs
|
| 104 |
+
'bghit': 'بغيت', 'bghiti': 'بغيتي', 'bgha': 'بغا', 'bghina': 'بغينا',
|
| 105 |
+
'kan': 'كان', 'kana': 'كانا', 'kanet': 'كانت', 'kanu': 'كانو',
|
| 106 |
+
'galt': 'قلت', 'galti': 'قلتي', 'gal': 'قال', 'galet': 'قالت',
|
| 107 |
+
'galou': 'قالو', 'galina': 'قلنا',
|
| 108 |
+
'rah': 'راح', 'raha': 'راها', 'rahi': 'راهي', 'rahom': 'راهم',
|
| 109 |
+
'ghadi': 'غادي', 'ghad': 'غاد', 'gha': 'غا', 'ghadia': 'غادية',
|
| 110 |
+
'dir': 'دير', 'dert': 'درت', 'derat': 'درات', 'derna': 'درنا',
|
| 111 |
+
'ja': 'جا', 'jat': 'جات', 'jina': 'جينا', 'jaou': 'جاو',
|
| 112 |
+
'mcha': 'مشا', 'mchat': 'مشات', 'mchina': 'مشينا', 'mchaou': 'مشاو',
|
| 113 |
+
'khrj': 'خرج', 'khrja': 'خرجا', 'khrjat': 'خرجات', 'khrjna': 'خرجنا',
|
| 114 |
+
'dkhl': 'دخل', 'dkhla': 'دخلا', 'dkhlat': 'دخلات', 'dkhlna': 'دخلنا',
|
| 115 |
+
|
| 116 |
+
# Demonstratives
|
| 117 |
+
'had': 'هاد', 'hada': 'هادا', 'hadi': 'هادي', 'hadou': 'هادو',
|
| 118 |
+
'hadouk': 'هادوك', 'hadchi': 'هادشي', 'hadak': 'هاداك',
|
| 119 |
+
'dak': 'داك', 'dik': 'ديك', 'dok': 'دوك', 'dakchi': 'داكشي',
|
| 120 |
+
|
| 121 |
+
# Prepositions
|
| 122 |
+
'fi': 'في', 'f': 'ف', 'men': 'من', 'mn': 'من', 'l': 'ل', 'li': 'لي',
|
| 123 |
+
'bla': 'بلا', 'b': 'ب', 'bi': 'بي', 'bih': 'بيه', 'biha': 'بيها',
|
| 124 |
+
'mea': 'معا', 'maak': 'معاك', 'maaki': 'معاكي', 'maana': 'معانا',
|
| 125 |
+
'maahom': 'معاهم', 'maaha': 'معاها',
|
| 126 |
+
|
| 127 |
+
# Numbers
|
| 128 |
+
'wahed': 'واحد', 'joj': 'جوج', 'tlata': 'تلاتا', 'rebaa': 'ربعا',
|
| 129 |
+
'khamsa': 'خمسا', 'setta': 'ستا', 'sebaa': 'سبعا', 'tmanya': 'تمنيا',
|
| 130 |
+
'tesaa': 'تسعا', 'ashra': 'عشرا',
|
| 131 |
+
|
| 132 |
+
# Time expressions
|
| 133 |
+
'daba': 'دابا', 'tawa': 'توا', 'ghda': 'غدا', 'lbareeh': 'البارح',
|
| 134 |
+
'nhar': 'نهار', 'lila': 'ليلا', 'sbah': 'صباح', 'aachia': 'عشيا',
|
| 135 |
+
|
| 136 |
+
# Family
|
| 137 |
+
'mama': 'ماما', 'baba': 'بابا', 'khoya': 'خويا', 'khti': 'ختي',
|
| 138 |
+
'khuya': 'خويا', 'khtiya': 'ختيا', 'akhi': 'أخي', 'ukhti': 'أختي',
|
| 139 |
+
'jad': 'جد', 'jada': 'جدا', 'amo': 'عمو', 'ama': 'عما',
|
| 140 |
+
'khal': 'خال', 'khala': 'خالا',
|
| 141 |
+
|
| 142 |
+
# Adjectives
|
| 143 |
+
'zwin': 'زوين', 'zwina': 'زوينا', 'qbih': 'قبيح', 'qbiha': 'قبيحا',
|
| 144 |
+
'kbir': 'كبير', 'kbira': 'كبيرا', 'sghir': 'صغير', 'sghira': 'صغيرا',
|
| 145 |
+
'tqil': 'تقيل', 'tqila': 'تقيلا', 'khfif': 'خفيف', 'khfifa': 'خفيفا',
|
| 146 |
+
'sahel': 'ساهل', 'sahla': 'ساهلا', 'saab': 'صعب', 'saba': 'صعبا',
|
| 147 |
+
|
| 148 |
+
# Quantities
|
| 149 |
+
'bzf': 'بزاف', 'bzzaf': 'بزاف', 'bezzaf': 'بزاف', 'ktir': 'كتير',
|
| 150 |
+
'chway': 'شوياة', 'chwiya': 'شوياة', 'shwiya': 'شوياة', 'chwia': 'شوياة',
|
| 151 |
+
'kolchi': 'كولشي', 'kol': 'كول', 'ga': 'غاع', 'gaa': 'غاع',
|
| 152 |
+
'hta': 'حتا', 'walo': 'والو', 'walou': 'والو',
|
| 153 |
+
|
| 154 |
+
# Negations
|
| 155 |
+
'ma': 'ما', 'machi': 'ماشي', 'mabghitsh': 'مابغيتش', 'makainch': 'ماكاينش',
|
| 156 |
+
'makansh': 'ماكانش', 'maghatch': 'ماغاتش', 'mabaghish': 'مابغيش',
|
| 157 |
+
|
| 158 |
+
# Conjunctions
|
| 159 |
+
'walakin': 'والاكين', 'walaken': 'والاكين', 'mais': 'ولكن',
|
| 160 |
+
'ama': 'أما', 'ida': 'إذا', 'ila': 'إلا', 'hta': 'حتا',
|
| 161 |
+
'ou': 'أو', 'o': 'أو', 'aw': 'أو', 'wla': 'ولا',
|
| 162 |
+
|
| 163 |
+
# Expressions
|
| 164 |
+
'salam': 'سلام', 'yallah': 'يالاه', 'yalla': 'يالا', 'hya': 'هيا',
|
| 165 |
+
'aji': 'أجي', 'sir': 'سير', 'siri': 'سيري', 'ajou': 'أجو',
|
| 166 |
+
'mabrook': 'مبروك', 'baraka': 'باركا', 'besaha': 'بصحا',
|
| 167 |
+
'allah': 'الله', 'rabi': 'ربي', 'llah': 'الله',
|
| 168 |
+
'inchallah': 'إن شاء الله', 'machallah': 'ما شاء الله',
|
| 169 |
+
'hamdulillah': 'الحمد لله', 'alhamdulillah': 'الحمد لله',
|
| 170 |
+
'la hawla': 'لا حول', 'astghfirullah': 'أستغفر الله',
|
| 171 |
+
|
| 172 |
+
# Countries and places
|
| 173 |
+
'lmaghrib': 'المغرب', 'maghrib': 'مغرب', 'casa': 'كازا',
|
| 174 |
+
'rbat': 'الرباط', 'fas': 'فاس', 'mknas': 'مكناس',
|
| 175 |
+
'tanja': 'طنجا', 'agadir': 'أكادير', 'marrakech': 'مراكش',
|
| 176 |
+
|
| 177 |
+
# Common nouns
|
| 178 |
+
'dar': 'دار', 'bit': 'بيت', 'tomo': 'طوموبيل', 'karhouba': 'كرهوبا',
|
| 179 |
+
'makla': 'ماكلا', 'atay': 'أتاي', 'khobz': 'خوبز', 'lma': 'الما',
|
| 180 |
+
'tajin': 'طاجين', 'tajine': 'طاجين', 'couscous': 'كوسكوس',
|
| 181 |
+
'msemen': 'مسمن', 'rghaif': 'رغايف', 'harira': 'حريرا',
|
| 182 |
+
'khodra': 'خضرا', 'fawakeh': 'فواكه', 'lahem': 'ل��م',
|
| 183 |
+
'djaj': 'دجاج', 'hout': 'حوت', 'lben': 'اللبن',
|
| 184 |
+
'skar': 'سكر', 'melh': 'ملح', 'zit': 'زيت', 'zebda': 'زبدا',
|
| 185 |
+
|
| 186 |
+
# Verbs (additional)
|
| 187 |
+
'chreb': 'شرب', 'chrba': 'شربا', 'chrebat': 'شربات', 'chrebna': 'شربنا',
|
| 188 |
+
'kla': 'كلا', 'klat': 'كلات', 'klina': 'كلينا', 'klaw': 'كلاو',
|
| 189 |
+
'nees': 'نعس', 'neesat': 'نعسات', 'neesna': 'نعسنا', 'neasou': 'نعسو',
|
| 190 |
+
'faq': 'فاق', 'faqat': 'فاقات', 'faqna': 'فقنا', 'faqou': 'فاقو',
|
| 191 |
+
'tlab': 'طلب', 'tlbat': 'طلبات', 'tlabna': 'طلبنا', 'tlabou': 'طلبو',
|
| 192 |
+
'khdam': 'خدم', 'khdmat': 'خدمات', 'khdamna': 'خدمنا', 'khdamou': 'خدمو',
|
| 193 |
+
'qra': 'قرا', 'qrat': 'قرات', 'qrina': 'قرينا', 'qraw': 'قراو',
|
| 194 |
+
'kteb': 'كتب', 'ktbat': 'كتبات', 'ktebna': 'كتبنا', 'ktbou': 'كتبو',
|
| 195 |
+
'chaf': 'شاف', 'chafat': 'شافات', 'chfna': 'شفنا', 'chafou': 'شافو',
|
| 196 |
+
'sma': 'سمع', 'smat': 'سمعات', 'smana': 'سمعنا', 'smaou': 'سمعو'
|
| 197 |
+
}
|
| 198 |
|
| 199 |
+
# CHARACTER MAPPINGS (Arabizi numbers/letters → Arabic)
|
| 200 |
+
char_mappings = {
|
| 201 |
+
'2': 'ء', '3': 'ع', '5': 'خ', '6': 'ط', '7': 'ح', '8': 'غ', '9': 'ق',
|
| 202 |
+
'a': 'ا', 'b': 'ب', 't': 'ت', 'th': 'ث', 'j': 'ج', 'd': 'د',
|
| 203 |
+
'r': 'ر', 'z': 'ز', 's': 'س', 'sh': 'ش', 'f': 'ف', 'k': 'ك',
|
| 204 |
+
'l': 'ل', 'm': 'م', 'n': 'ن', 'h': 'ه', 'w': 'و', 'y': 'ي',
|
| 205 |
+
'aa': 'آ', 'ee': 'ي', 'oo': 'و', 'ou': 'و', 'ai': 'ي', 'ay': 'ي'
|
| 206 |
+
}
|
| 207 |
|
| 208 |
+
# DIGRAPH MAPPINGS (two-letter combinations first)
|
| 209 |
+
digraph_mappings = {
|
| 210 |
+
'kh': 'خ', 'gh': 'غ', 'ch': 'ش', 'th': 'ث', 'dh': 'ذ',
|
| 211 |
+
'sh': 'ش', 'ts': 'ص', 'dz': 'ض', 'ss': 'ص', 'tt': 'ط',
|
| 212 |
+
'zz': 'ظ', 'aa': 'آ', 'ee': 'ي', 'ii': 'ي', 'oo': 'و',
|
| 213 |
+
'uu': 'و', 'ou': 'و', 'ai': 'ي', 'ay': 'ي', 'ey': 'ي'
|
| 214 |
+
}
|
| 215 |
|
| 216 |
+
# Convert text
|
| 217 |
+
result = text.lower()
|
|
|
|
| 218 |
|
| 219 |
+
# Step 1: Apply word mappings (most specific first)
|
| 220 |
+
for arabizi_word, arabic_word in word_mappings.items():
|
| 221 |
+
# Use word boundaries to avoid partial matches
|
| 222 |
+
pattern = r'\b' + re.escape(arabizi_word) + r'\b'
|
| 223 |
+
result = re.sub(pattern, arabic_word, result, flags=re.IGNORECASE)
|
| 224 |
|
| 225 |
+
# Step 2: Apply digraph mappings
|
| 226 |
+
for digraph, arabic_char in digraph_mappings.items():
|
| 227 |
+
result = result.replace(digraph, arabic_char)
|
|
|
|
|
|
|
| 228 |
|
| 229 |
+
# Step 3: Apply single character mappings
|
| 230 |
+
for char, arabic_char in char_mappings.items():
|
| 231 |
+
if len(char) == 1: # Only single chars in this step
|
| 232 |
+
result = result.replace(char, arabic_char)
|
| 233 |
+
|
| 234 |
+
return result
|
| 235 |
|
| 236 |
+
def arabic_to_arabizi(text):
|
| 237 |
"""
|
| 238 |
+
Convert Arabic script to Arabizi
|
| 239 |
+
COMPLETE HARD-CODED MAPPINGS
|
| 240 |
"""
|
| 241 |
+
if not text:
|
| 242 |
+
return text
|
| 243 |
|
| 244 |
+
# COMPREHENSIVE WORD MAPPINGS (Arabic → Arabizi)
|
| 245 |
+
word_mappings = {
|
| 246 |
+
# Pronouns
|
| 247 |
+
'أنا': 'ana', 'نتا': 'nta', 'نتي': 'nti', 'هوا': 'howa', 'هيا': 'hiya',
|
| 248 |
+
'حنا': 'hna', 'أحنا': 'ahna', 'نتوما': 'ntuma', 'هوما': 'huma',
|
| 249 |
+
|
| 250 |
+
# Question words
|
| 251 |
+
'شكون': 'shkoun', 'أشنو': 'achno', 'شنو': 'chno', 'أش': 'ach',
|
| 252 |
+
'واش': 'wach', 'كيفاش': 'kifash', 'كيف': 'kif', 'فين': 'feen',
|
| 253 |
+
'منين': 'mnin', 'إمتا': 'imta', 'متا': 'meta', 'علاش': '3lach',
|
| 254 |
+
|
| 255 |
+
# Common verbs
|
| 256 |
+
'بغيت': 'bghit', 'بغيتي': 'bghiti', 'بغا': 'bgha', 'بغينا': 'bghina',
|
| 257 |
+
'كان': 'kan', 'كانا': 'kana', 'كانت': 'kanet', 'كانو': 'kanu',
|
| 258 |
+
'قلت': 'galt', 'قلتي': 'galti', 'قال': 'gal', 'قالت': 'galet',
|
| 259 |
+
'قالو': 'galou', 'قلنا': 'galina',
|
| 260 |
+
'راح': 'rah', 'راها': 'raha', 'راهي': 'rahi', 'راهم': 'rahom',
|
| 261 |
+
'غادي': 'ghadi', 'غاد': 'ghad', 'غ��': 'gha', 'غادية': 'ghadia',
|
| 262 |
+
'دير': 'dir', 'درت': 'dert', 'درات': 'derat', 'درنا': 'derna',
|
| 263 |
+
'جا': 'ja', 'جات': 'jat', 'جينا': 'jina', 'جاو': 'jaou',
|
| 264 |
+
'مشا': 'mcha', 'مشات': 'mchat', 'مشينا': 'mchina', 'مشاو': 'mchaou',
|
| 265 |
+
|
| 266 |
+
# Demonstratives
|
| 267 |
+
'هاد': 'had', 'هادا': 'hada', 'هادي': 'hadi', 'هادو': 'hadou',
|
| 268 |
+
'هادوك': 'hadouk', 'هادشي': 'hadchi', 'هاداك': 'hadak',
|
| 269 |
+
'داك': 'dak', 'ديك': 'dik', 'دوك': 'dok', 'داكشي': 'dakchi',
|
| 270 |
+
|
| 271 |
+
# Numbers
|
| 272 |
+
'واحد': 'wahed', 'جوج': 'joj', 'تلاتا': 'tlata', 'ربعا': 'rebaa',
|
| 273 |
+
'خمسا': 'khamsa', 'ستا': 'setta', 'سبعا': 'sebaa', 'تمنيا': 'tmanya',
|
| 274 |
+
'تسعا': 'tesaa', 'عشرا': 'ashra',
|
| 275 |
+
|
| 276 |
+
# Time
|
| 277 |
+
'دابا': 'daba', 'توا': 'tawa', 'غدا': 'ghda', 'البارح': 'lbareeh',
|
| 278 |
+
'نهار': 'nhar', 'ليلا': 'lila', 'صباح': 'sbah', 'عشيا': 'aachia',
|
| 279 |
+
|
| 280 |
+
# Family
|
| 281 |
+
'ماما': 'mama', 'بابا': 'baba', 'خويا': 'khoya', 'ختي': 'khti',
|
| 282 |
+
'ختيا': 'khtiya', 'أخي': 'akhi', 'أختي': 'ukhti',
|
| 283 |
+
'جد': 'jad', 'جدا': 'jada', 'عمو': 'amo', 'عما': 'ama',
|
| 284 |
+
|
| 285 |
+
# Adjectives
|
| 286 |
+
'زوين': 'zwin', 'زوينا': 'zwina', 'قبيح': 'qbih', 'قبيحا': 'qbiha',
|
| 287 |
+
'كبير': 'kbir', 'كبيرا': 'kbira', 'صغير': 'sghir', 'صغيرا': 'sghira',
|
| 288 |
+
'تقيل': 'tqil', 'تقيلا': 'tqila', 'خفيف': 'khfif', 'خفيفا': 'khfifa',
|
| 289 |
+
|
| 290 |
+
# Quantities
|
| 291 |
+
'بزاف': 'bzzaf', 'كتير': 'ktir', 'شوياة': 'chwiya', 'كولشي': 'kolchi',
|
| 292 |
+
'كول': 'kol', 'غاع': 'gaa', 'حتا': 'hta', 'والو': 'walo',
|
| 293 |
+
|
| 294 |
+
# Negations
|
| 295 |
+
'ما': 'ma', 'ماشي': 'machi', 'مابغيتش': 'mabghitsh', 'ماكاينش': 'makainch',
|
| 296 |
+
'ماكانش': 'makansh', 'ماغاتش': 'maghatch', 'مابغيش': 'mabaghish',
|
| 297 |
+
|
| 298 |
+
# Expressions
|
| 299 |
+
'سلام': 'salam', 'يالاه': 'yallah', 'يالا': 'yalla', 'هيا': 'hya',
|
| 300 |
+
'أجي': 'aji', 'سير': 'sir', 'سيري': 'siri', 'أجو': 'ajou',
|
| 301 |
+
'مبروك': 'mabrook', 'باركا': 'baraka', 'بصحا': 'besaha',
|
| 302 |
+
'الله': 'allah', 'ربي': 'rabi', 'إن شاء الله': 'inchallah',
|
| 303 |
+
'ما شاء الله': 'machallah', 'الحمد لله': 'hamdulillah',
|
| 304 |
+
|
| 305 |
+
# Places
|
| 306 |
+
'المغرب': 'lmaghrib', 'مغرب': 'maghrib', 'كازا': 'casa',
|
| 307 |
+
'الرباط': 'rbat', 'فاس': 'fas', 'مكناس': 'mknas',
|
| 308 |
+
'طنجا': 'tanja', 'أكادير': 'agadir', 'مراكش': 'marrakech',
|
| 309 |
+
|
| 310 |
+
# Food and drinks
|
| 311 |
+
'طاجين': 'tajine', 'كوسكوس': 'couscous', 'مسمن': 'msemen',
|
| 312 |
+
'رغايف': 'rghaif', 'حريرا': 'harira', 'أتاي': 'atay',
|
| 313 |
+
'خوبز': 'khobz', 'الما': 'lma', 'لحم': 'lahem', 'دجاج': 'djaj',
|
| 314 |
+
|
| 315 |
+
# Common nouns
|
| 316 |
+
'دار': 'dar', 'بيت': 'bit', 'طوموبيل': 'tomo', 'كرهوبا': 'karhouba',
|
| 317 |
+
'ماكلا': 'makla', 'خضرا': 'khodra', 'فواكه': 'fawakeh',
|
| 318 |
+
'حوت': 'hout', 'اللبن': 'lben', 'سكر': 'skar', 'ملح': 'melh'
|
| 319 |
+
}
|
| 320 |
|
| 321 |
+
# CHARACTER MAPPINGS (Arabic → Arabizi)
|
| 322 |
+
char_mappings = {
|
| 323 |
+
'ا': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'j', 'ح': '7',
|
| 324 |
+
'خ': 'kh', 'د': 'd', 'ذ': 'dh', 'ر': 'r', 'ز': 'z', 'س': 's',
|
| 325 |
+
'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': '6', 'ظ': 'z', 'ع': '3',
|
| 326 |
+
'غ': 'gh', 'ف': 'f', 'ق': '9', 'ك': 'k', 'ل': 'l', 'م': 'm',
|
| 327 |
+
'ن': 'n', 'ه': 'h', 'و': 'w', 'ي': 'y', 'ء': '2',
|
| 328 |
+
'آ': 'aa', 'أ': 'a', 'إ': 'i', 'ئ': '2', 'ؤ': 'w2', 'ة': 'a',
|
| 329 |
+
'ى': 'a', 'ً': 'an', 'ٌ': 'on', 'ٍ': 'in', 'َ': 'a', 'ُ': 'o', 'ِ': 'i'
|
| 330 |
+
}
|
| 331 |
|
| 332 |
+
# Convert text
|
| 333 |
+
result = text
|
| 334 |
+
|
| 335 |
+
# Step 1: Apply word mappings (most specific first)
|
| 336 |
+
for arabic_word, arabizi_word in word_mappings.items():
|
| 337 |
+
# Use word boundaries to avoid partial matches
|
| 338 |
+
pattern = r'\b' + re.escape(arabic_word) + r'\b'
|
| 339 |
+
result = re.sub(pattern, arabizi_word, result)
|
| 340 |
+
|
| 341 |
+
# Step 2: Apply character mappings
|
| 342 |
+
for arabic_char, arabizi_char in char_mappings.items():
|
| 343 |
+
result = result.replace(arabic_char, arabizi_char)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
|
| 345 |
+
return result
|
|
|
|
| 346 |
|
| 347 |
def chat_with_atlas(message, history):
|
| 348 |
+
"""Generate response from Atlas-Chat model with Arabizi conversion"""
|
| 349 |
if not message.strip():
|
| 350 |
return "مرحبا! أهلا وسهلا. Please enter a message! / Ahlan wa sahlan!"
|
| 351 |
|
|
|
|
| 353 |
# Load model if not already loaded
|
| 354 |
model = load_model()
|
| 355 |
|
| 356 |
+
# Detect if input is Arabizi
|
| 357 |
+
is_arabizi_input = detect_arabizi(message)
|
| 358 |
|
| 359 |
+
# Prepare input for the model
|
| 360 |
+
if is_arabizi_input:
|
| 361 |
+
# Convert Arabizi to Arabic for the model
|
| 362 |
+
arabic_input = arabizi_to_arabic(message)
|
| 363 |
+
print(f"🔄 Converted Arabizi '{message}' → Arabic '{arabic_input}'")
|
| 364 |
+
model_input = arabic_input
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 365 |
else:
|
| 366 |
+
# Use original input (Arabic or English)
|
| 367 |
+
model_input = message
|
| 368 |
+
|
| 369 |
+
# Generate response using Arabic input
|
| 370 |
+
messages = [{"role": "user", "content": model_input}]
|
| 371 |
|
|
|
|
| 372 |
outputs = model(
|
| 373 |
messages,
|
| 374 |
max_new_tokens=256,
|
|
|
|
| 380 |
# Extract the response
|
| 381 |
response = outputs[0]["generated_text"][-1]["content"].strip()
|
| 382 |
|
| 383 |
+
# Convert response back to Arabizi if input was Arabizi
|
| 384 |
+
if is_arabizi_input:
|
| 385 |
+
arabizi_response = arabic_to_arabizi(response)
|
| 386 |
+
print(f"🔄 Converted response '{response}' → Arabizi '{arabizi_response}'")
|
| 387 |
+
return arabizi_response
|
| 388 |
+
else:
|
| 389 |
+
# Return original response for Arabic/English
|
| 390 |
+
return response
|
|
|
|
| 391 |
|
| 392 |
except Exception as e:
|
| 393 |
+
# Return error in appropriate language
|
| 394 |
+
if detect_arabizi(message):
|
| 395 |
+
return f"sorry, kan chi mochkil: {str(e)}. 3awd jar'b!"
|
| 396 |
+
else:
|
| 397 |
+
return f"عذراً، واجهت خطأ: {str(e)}. جرب مرة أخرى! / Sorry, error occurred: {str(e)}. Try again!"
|
| 398 |
|
| 399 |
# Create the Gradio interface
|
| 400 |
demo = gr.ChatInterface(
|
|
|
|
| 403 |
description="""
|
| 404 |
**مرحبا بك في أطلس شات!** Welcome to Atlas-Chat! 🇲🇦
|
| 405 |
|
| 406 |
+
**🧠 Smart Language Detection & Conversion:**
|
| 407 |
+
- **Arabic Script (العربية)** → AI responds in Arabic
|
| 408 |
+
- **Arabizi (3arabi bi 7oruf latin)** → AI responds in Arabizi
|
| 409 |
+
- **English** → AI responds in English
|
| 410 |
|
| 411 |
+
**✨ Full Arabizi Support:** Type "shkoun nta?" and get "ana atlas-chat..."
|
|
|
|
|
|
|
| 412 |
|
| 413 |
**جرب هذه الأسئلة / Try these questions:**
|
| 414 |
""",
|
|
|
|
| 422 |
"What is Morocco famous for?",
|
| 423 |
"Tell me about Casablanca",
|
| 424 |
"كيفاش نقدر نتعلم الدارجة؟",
|
| 425 |
+
"kifash n9der nt3elem darija?",
|
| 426 |
+
"wach kayn atay f lmaghrib?",
|
| 427 |
+
"3lach lmaghrib zwien bzzaf?",
|
| 428 |
+
"kifash nsali tajine?",
|
| 429 |
+
"chno homa l2aklat lmaghribiya?"
|
| 430 |
],
|
| 431 |
cache_examples=False
|
| 432 |
)
|