File size: 14,997 Bytes
4f4e064
f536a8a
93683f0
b97cadb
4f4e064
93683f0
 
 
 
4f4e064
93683f0
 
 
 
 
 
f536a8a
93683f0
f536a8a
 
 
 
 
93683f0
 
 
 
 
 
 
 
 
 
4f4e064
b97cadb
 
 
 
 
 
 
 
 
 
 
 
 
725d97d
 
 
 
 
b97cadb
725d97d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93683f0
 
b97cadb
 
725d97d
 
b97cadb
725d97d
 
 
 
 
 
 
b97cadb
725d97d
 
93683f0
725d97d
93683f0
725d97d
93683f0
 
725d97d
93683f0
 
725d97d
93683f0
 
 
 
 
 
 
 
 
725d97d
93683f0
 
725d97d
93683f0
725d97d
93683f0
 
 
 
b97cadb
93683f0
b97cadb
93683f0
 
b97cadb
93683f0
 
b97cadb
725d97d
 
93683f0
725d97d
 
93683f0
 
 
725d97d
 
 
 
93683f0
 
 
 
 
 
725d97d
93683f0
 
 
 
964322b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
725d97d
b97cadb
725d97d
 
 
 
 
 
 
93683f0
 
 
725d97d
b97cadb
93683f0
725d97d
93683f0
725d97d
 
93683f0
725d97d
 
 
 
b97cadb
93683f0
b97cadb
f536a8a
93683f0
f536a8a
93683f0
f536a8a
 
93683f0
 
f536a8a
725d97d
 
b97cadb
a0cbc8f
 
 
 
 
 
725d97d
 
93683f0
a0cbc8f
93683f0
a0cbc8f
725d97d
b97cadb
725d97d
a0cbc8f
725d97d
 
a0cbc8f
 
 
725d97d
 
f536a8a
93683f0
f536a8a
 
 
 
93683f0
f536a8a
 
 
 
a0cbc8f
b97cadb
725d97d
 
a0cbc8f
725d97d
a0cbc8f
 
 
 
725d97d
 
 
a0cbc8f
 
 
 
725d97d
f536a8a
 
a0cbc8f
 
725d97d
 
 
 
 
4f4e064
f536a8a
4f4e064
f536a8a
93683f0
f536a8a
93683f0
f536a8a
93683f0
725d97d
93683f0
725d97d
b97cadb
964322b
93683f0
 
 
f536a8a
 
 
 
 
b97cadb
 
 
f536a8a
b97cadb
f536a8a
b97cadb
725d97d
 
 
 
93683f0
 
 
4f4e064
0615894
4f4e064
 
f536a8a
4f4e064
f536a8a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
import gradio as gr
import torch
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
import re

# Global variables to store the models
atlas_pipe = None
transliteration_tokenizer = None
transliteration_model = None

def load_models():
    """Load both Atlas-Chat and Transliteration models"""
    global atlas_pipe, transliteration_tokenizer, transliteration_model
    
    # Load Atlas-Chat model
    if atlas_pipe is None:
        print("🏔️ Loading Atlas-Chat-2B model...")
        atlas_pipe = pipeline(
            "text-generation",
            model="MBZUAI-Paris/Atlas-Chat-2B",
            model_kwargs={"torch_dtype": torch.bfloat16},
            device="cuda" if torch.cuda.is_available() else "cpu"
        )
        print("✅ Atlas-Chat model loaded!")
    
    # Load Transliteration model
    if transliteration_tokenizer is None or transliteration_model is None:
        print("🔄 Loading Transliteration model...")
        transliteration_tokenizer = AutoTokenizer.from_pretrained("atlasia/Transliteration-Moroccan-Darija")
        transliteration_model = AutoModelForSeq2SeqLM.from_pretrained("atlasia/Transliteration-Moroccan-Darija")
        print("✅ Transliteration model loaded!")
    
    return atlas_pipe, transliteration_tokenizer, transliteration_model

def detect_arabizi(text):
    """
    Detect if input text is written in Arabizi (Latin script with numbers)
    Returns True if Arabizi is detected
    """
    if not text or len(text.strip()) < 2:
        return False
    
    # Check for Arabic script - if present, it's NOT Arabizi
    arabic_pattern = r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]'
    if re.search(arabic_pattern, text):
        return False
    
    # Arabizi indicators - numbers used as letters
    arabizi_numbers = ['2', '3', '7', '9', '5', '6', '8']
    has_arabizi_numbers = any(num in text for num in arabizi_numbers)
    
    # Common Arabizi words and patterns
    arabizi_patterns = [
        'wach', 'wash', 'ach', 'achno', 'chno', 'shno', 'shkoun', 'chkoun',
        'kif', 'kifash', 'ki', 'kayf', 'kien', 'kima',
        'feen', 'fin', 'fen', 'fain', 'mnin',
        'imta', 'meta', 'waqt', 'mata', 'emta',
        'hna', 'ahna', 'ana', 'nta', 'nti', 'ntuma', 'ntouma',
        'howa', 'hiya', 'huma', 'houma', 'hoa', 'hia',
        'had', 'hadchi', 'hada', 'hadi', 'hadou', 'hadouk',
        'bghit', 'bghiti', 'bgha', 'bghina', 'bghitiou',
        'galt', 'galti', 'gal', 'galet', 'galou',
        'rah', 'raha', 'rahi', 'rahom', 'rahin',
        'kan', 'kanu', 'kana', 'kanet', 'kano',
        'ghadi', 'ghad', 'gha', 'ghadia', 'ghadiyin',
        'daba', 'dak', 'dakchi', 'dik', 'dok',
        'bzf', 'bzzaf', 'bezzaf', 'bzaaaaf',
        'chway', 'chwiya', 'shwiya', 'chwia',
        'khoya', 'khuya', 'akhi', 'kho',
        'khti', 'khtiya', 'ukhti', 'kht',
        'mama', 'baba', 'lwaldin', 'lwalidin',
        'salam', 'salamu aleikum', 'slm',
        'yallah', 'yalla', 'hya', 'aji',
        'mabghitsh', 'mabghach', 'makansh', 'machi',
        'walakin', 'walaken', 'ama', 'mais',
        'kayn', 'makaynsh', 'chi', 'tayi'
    ]
    
    text_lower = text.lower()
    has_arabizi_words = any(pattern in text_lower for pattern in arabizi_patterns)
    
    # Decision logic
    if has_arabizi_numbers and has_arabizi_words:
        return True
    if has_arabizi_numbers and len([c for c in text if c.isalpha()]) > len(text) * 0.6:
        return True
    if has_arabizi_words and len([c for c in text if c.isalpha()]) > len(text) * 0.7:
        return True
    
    return False

def arabizi_to_arabic_ai(arabizi_text):
    """
    Convert Arabizi text to Arabic using the specialized AI model
    """
    try:
        _, tokenizer, model = load_models()
        
        # Tokenize the input text
        input_tokens = tokenizer(arabizi_text, return_tensors="pt", padding=True, truncation=True, max_length=512)
        
        # Perform transliteration
        with torch.no_grad():
            output_tokens = model.generate(
                **input_tokens,
                max_length=512,
                num_beams=4,
                early_stopping=True,
                no_repeat_ngram_size=2
            )
        
        # Decode the output tokens
        arabic_text = tokenizer.decode(output_tokens[0], skip_special_tokens=True)
        
        return arabic_text.strip()
        
    except Exception as e:
        print(f"❌ Error in Arabizi→Arabic conversion: {e}")
        # Fallback to original text if conversion fails
        return arabizi_text

def arabic_to_arabizi(arabic_text):
    """
    Convert Arabic script to Arabizi using character mappings
    (Keeping this as backup since no reverse model available)
    """
    if not arabic_text:
        return arabic_text
    
    # COMPREHENSIVE WORD MAPPINGS (Arabic → Arabizi)
    word_mappings = {
        # Common words first (most likely to appear)
        'أنا': 'ana', 'نتا': 'nta', 'نتي': 'nti', 'هوا': 'howa', 'هيا': 'hiya',
        'حنا': 'hna', 'أحنا': 'ahna', 'نتوما': 'ntuma', 'هوما': 'huma',
        'شكون': 'shkoun', 'أشنو': 'achno', 'شنو': 'chno', 'واش': 'wach',
        'كيفاش': 'kifash', 'كيف': 'kif', 'فين': 'feen', 'منين': 'mnin',
        'إمتا': 'imta', 'متا': 'meta', 'علاش': '3lach', 'أش': 'ach',
        'بغيت': 'bghit', 'بغيتي': 'bghiti', 'بغا': 'bgha', 'بغينا': 'bghina',
        'كان': 'kan', 'كانا': 'kana', 'كانت': 'kanet', 'كانو': 'kanu',
        'قلت': 'galt', 'قلتي': 'galti', 'قال': 'gal', 'قالت': 'galet',
        'راح': 'rah', 'راها': 'raha', 'راهي': 'rahi', 'راهم': 'rahom',
        'غادي': 'ghadi', 'غاد': 'ghad', 'غا': 'gha',
        'هاد': 'had', 'هادا': 'hada', 'هادي': 'hadi', 'هادشي': 'hadchi',
        'داك': 'dak', 'ديك': 'dik', 'داكشي': 'dakchi',
        'بزاف': 'bzzaf', 'شوياة': 'chwiya', 'كولشي': 'kolchi',
        'ماشي': 'machi', 'مابغيتش': 'mabghitsh', 'ماكاينش': 'makainch',
        'دابا': 'daba', 'توا': 'tawa', 'غدا': 'ghda',
        'ماما': 'mama', 'بابا': 'baba', 'خويا': 'khoya', 'ختي': 'khti',
        'سلام': 'salam', 'يالاه': 'yallah', 'هيا': 'hya',
        'المغرب': 'lmaghrib', 'مغرب': 'maghrib',
        'طاجين': 'tajine', 'أتاي': 'atay', 'خوبز': 'khobz',
        'كاين': 'kayn', 'ماكاينش': 'makaynsh', 'شي': 'chi',
        'زوين': 'zwin', 'زوينا': 'zwina', 'مزيان': 'mzyan', 'مزيانا': 'mzyana',
        'درت': 'dert', 'درتي': 'derti', 'دار': 'dar', 'درات': 'derat',
        'مشيت': 'mchit', 'مشيتي': 'mchiti', 'مشا': 'mcha', 'مشات': 'mchat',
        'جيت': 'jit', 'جيتي': 'jiti', 'جا': 'ja', 'جات': 'jat',
        'شفت': 'cheft', 'شفتي': 'chefti', 'شاف': 'chaf', 'شافت': 'chafat',
        'سمعت': 'sme3t', 'سمعتي': 'sme3ti', 'سمع': 'sma3', 'سمعات': 'sma3at',
        'أكلت': 'klit', 'أكلتي': 'kliti', 'كلا': 'kla', 'كلات': 'klat',
        'شربت': 'chrebt', 'شربتي': 'chrebti', 'شرب': 'chreb', 'شربات': 'chrebat',
        'نعست': 'ne3st', 'نعستي': 'ne3sti', 'نعس': 'ne3s', 'نعسات': 'ne3sat',
        'خرجت': 'khrjt', 'خرجتي': 'khrjti', 'خرج': 'khrj', 'خرجات': 'khrjat',
        'دخلت': 'dkhlt', 'دخلتي': 'dkhlti', 'دخل': 'dkhl', 'دخلات': 'dkhlat',
        'قريت': 'qrit', 'قريتي': 'qriti', 'قرا': 'qra', 'قرات': 'qrat',
        'كتبت': 'ktebt', 'كتبتي': 'ktebti', 'كتب': 'kteb', 'كتبات': 'ktebat',
        'لعبت': 'l3ebt', 'لعبتي': 'l3ebti', 'لعب': 'l3eb', 'لعبات': 'l3ebat',
        'خدمت': 'khdmt', 'خدمتي': 'khdmti', 'خدم': 'khdm', 'خدمات': 'khdmat',
        'صليت': 'sllit', 'صليتي': 'slliti', 'صلا': 'slla', 'صلات': 'sllat',
        'طبخت': '6bkht', 'طبختي': '6bkhti', 'طبخ': '6bekh', 'طبخات': '6bekhat',
        'واحد': 'wa7ed', 'جوج': 'joj', 'تلاتا': 'tlata', 'ربعا': 'reb3a',
        'خمسا': 'khamsa', 'ستا': 'setta', 'سبعا': 'seb3a', 'تمنيا': 'tmnya',
        'تسعا': 'tes3a', 'عشرا': '3echra', 'حداش': '7dach', 'طناش': '6nach',
        'نهار': 'nhar', 'ليلا': 'lila', 'صباح': 'sba7', 'عشيا': '3echiya',
        'أمس': 'ems', 'البارح': 'lbare7', 'غدا': 'ghda', 'بعد غدا': 'b3d ghda',
        'دار': 'dar', 'بيت': 'bit', 'شارع': 'char3', 'مدينا': 'mdina',
        'كرهوبا': 'karhouba', 'طوموبيل': 'tomobil', 'قطار': 'q6ar', 'باص': 'bas',
        'ماكلا': 'makla', 'شراب': 'chrab', 'لما': 'lma', 'عطش': '36ch',
        'جوع': 'jo3', 'شبعان': 'cheb3an', 'عيان': '3yyan', 'صحيح': 's7i7',
        'مريض': 'mrid', 'دكتور': 'doktor', 'سبيطار': 'sbitar', 'دوا': 'dwa',
        'فلوس': 'flous', 'درهم': 'derhem', 'ريال': 'riyal', 'اليورو': 'lyoro',
        'خدما': 'khedma', 'معلم': 'mo3alim', 'طالب': 'talib', 'أستاذ': 'ostaz',
        'كتاب': 'ktab', 'قلم': 'qalam', 'كاغط': 'kaghet', 'طاولا': 'tabla'
    }
    
    # CHARACTER MAPPINGS (Arabic → Arabizi)
    char_mappings = {
        'ا': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'j', 'ح': '7',
        'خ': 'kh', 'د': 'd', 'ذ': 'dh', 'ر': 'r', 'ز': 'z', 'س': 's',
        'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': '6', 'ظ': 'z', 'ع': '3',
        'غ': 'gh', 'ف': 'f', 'ق': '9', 'ك': 'k', 'ل': 'l', 'م': 'm',
        'ن': 'n', 'ه': 'h', 'و': 'w', 'ي': 'y', 'ء': '2',
        'آ': 'aa', 'أ': 'a', 'إ': 'i', 'ة': 'a', 'ى': 'a',
        '؟': '?', '،': ',', '؛': ';', ':': ':', '!': '!',
        'َ': 'a', 'ُ': 'o', 'ِ': 'i', 'ً': 'an', 'ٌ': 'on', 'ٍ': 'in'
    }
    
    result = arabic_text
    
    # Step 1: Apply word mappings
    for arabic_word, arabizi_word in word_mappings.items():
        # Use word boundaries to avoid partial matches
        result = re.sub(r'\b' + re.escape(arabic_word) + r'\b', arabizi_word, result)
    
    # Step 2: Apply character mappings
    for arabic_char, arabizi_char in char_mappings.items():
        result = result.replace(arabic_char, arabizi_char)
    
    return result.strip()

def chat_with_atlas(message, history):
    """Generate response from Atlas-Chat model with AI-powered Arabizi conversion"""
    if not message.strip():
        return "ahlan wa sahlan! kifash n9der n3awnek? / مرحبا! كيفاش نقدر نعاونك؟"
    
    try:
        # Load models
        atlas_model, _, _ = load_models()
        
        # Detect if input is Arabizi
        is_arabizi_input = detect_arabizi(message)
        
        print("\n" + "="*60)
        print("🔍 DEBUG LOG - FULL CONVERSION PIPELINE")
        print("="*60)
        print(f"📥 ORIGINAL INPUT: '{message}'")
        print(f"🤖 ARABIZI DETECTED: {is_arabizi_input}")
        
        # Prepare input for the model
        if is_arabizi_input:
            # Convert Arabizi to Arabic using AI model
            print(f"\n🔄 STEP 1: Converting Arabizi to Arabic...")
            arabic_input = arabizi_to_arabic_ai(message)
            print(f"✅ ARABIC CONVERSION: '{arabic_input}'")
            model_input = arabic_input
        else:
            # Use original input (Arabic or English)
            print(f"\n➡️  NO CONVERSION NEEDED - Using original input")
            model_input = message
        
        print(f"\n🤖 STEP 2: Sending to Atlas-Chat model...")
        print(f"📤 MODEL INPUT: '{model_input}'")
        
        # Generate response using Arabic input
        messages = [{"role": "user", "content": model_input}]
        
        outputs = atlas_model(
            messages, 
            max_new_tokens=256, 
            temperature=0.1,
            do_sample=True,
            pad_token_id=atlas_model.tokenizer.eos_token_id
        )
        
        # Extract the response
        response = outputs[0]["generated_text"][-1]["content"].strip()
        print(f"✅ MODEL RESPONSE (Arabic): '{response}'")
        
        # Convert response back to Arabizi if input was Arabizi
        if is_arabizi_input:
            print(f"\n🔄 STEP 3: Converting response back to Arabizi...")
            arabizi_response = arabic_to_arabizi(response)
            print(f"✅ FINAL ARABIZI RESPONSE: '{arabizi_response}'")
            print("="*60)
            print("🎯 FINAL OUTPUT TO USER:", arabizi_response)
            print("="*60 + "\n")
            return arabizi_response
        else:
            # Return original response for Arabic/English
            print(f"\n➡️  NO BACK-CONVERSION NEEDED")
            print("="*60)
            print("🎯 FINAL OUTPUT TO USER:", response)
            print("="*60 + "\n")
            return response
        
    except Exception as e:
        print(f"\n❌ ERROR OCCURRED: {str(e)}")
        print("="*60 + "\n")
        # Return error in appropriate language
        if detect_arabizi(message):
            return f"sorry, kan chi mochkil: {str(e)}. 3awd jar'b!"
        else:
            return f"عذراً، واجهت خطأ: {str(e)}. جرب مرة أخرى! / Sorry, error occurred: {str(e)}. Try again!"

# Create the Gradio interface
demo = gr.ChatInterface(
    fn=chat_with_atlas,
    title="🏔️ Atlas-Chat: Advanced Moroccan Arabic AI",
    description="""
    **مرحبا بك في أطلس شات المطور!** Welcome to Advanced Atlas-Chat! 🇲🇦
    
    **🧠 AI-Powered Language Detection & Conversion:**
    - **Arabic Script (العربية)** → AI responds in Arabic
    - **Arabizi (3arabi bi 7oruf latin)** → AI-powered conversion → Arabizi response  
    - **English** → AI responds in English
    
    **⚡ Professional Arabizi Conversion**
    - Uses specialized AI model trained on Moroccan Darija
    - Perfect understanding of context: "kayn chi" → "كاين شي"
    - Handles complex phrases accurately
    
    **جرب هذه الأسئلة / Try these questions:**
    """,
    examples=[
        "شكون لي صنعك؟",
        "shkoun li sna3ek?",
        "اشنو هو الطاجين؟",
        "achno howa tajine?", 
        "شنو كيتسمى المنتخب المغربي؟",
        "chno kaytsma lmontakhab lmaghribi?",
        "What is Morocco famous for?",
        "كيفاش نقدر نتعلم الدارجة؟",
        "kifash n9der nt3elem darija?",
        "wach kayn atay f lmaghrib?",
        "3lach lmaghrib zwien bzzaf?",
        "kifash nsali tajine?",
        "chno homa l2aklat lmaghribiya?",
        "kayn chi restaurants zwinin f casa?",
        "mr7ba! kif dayr?"
    ],
    cache_examples=False
)

# Launch the app
if __name__ == "__main__":
    demo.launch()