JamboGPT Bot commited on
Commit
dd6ced7
Β·
1 Parent(s): 15fa865

Simple lightweight version - text responses only, no heavy TTS

Browse files
Files changed (1) hide show
  1. app.py +150 -427
app.py CHANGED
@@ -1,30 +1,15 @@
1
  #!/usr/bin/env python3
2
  """
3
  JamboGPT - African Language AI Voice Agent
4
- Simplified version for Hugging Face Spaces
5
  """
6
 
7
- import os
8
  import gradio as gr
9
- import torch
10
- from transformers import pipeline
11
- import numpy as np
12
- from scipy.io import wavfile
13
- import tempfile
14
  from datetime import datetime
15
- import librosa
16
-
17
- # Set device
18
- device = "cuda" if torch.cuda.is_available() else "cpu"
19
- print(f"🌍 Starting JamboGPT - African Language AI Voice Agent")
20
- print(f"Using device: {device}")
21
- print("=" * 50)
22
 
23
  # Language configurations
24
  LANGUAGES = {
25
  "Swahili": {
26
- "code": "swh",
27
- "tts_model": "facebook/mms-tts-swh",
28
  "emoji": "πŸ‡°πŸ‡ͺ",
29
  "speakers": "100M+",
30
  "region": "East Africa",
@@ -43,8 +28,6 @@ LANGUAGES = {
43
  }
44
  },
45
  "Kikuyu": {
46
- "code": "ki",
47
- "tts_model": "BrianMwangi/African-Kikuyu-TTS",
48
  "emoji": "πŸ‡°πŸ‡ͺ",
49
  "speakers": "7M",
50
  "region": "Kenya",
@@ -63,8 +46,6 @@ LANGUAGES = {
63
  }
64
  },
65
  "Yoruba": {
66
- "code": "yor",
67
- "tts_model": "facebook/mms-tts-yor",
68
  "emoji": "πŸ‡³πŸ‡¬",
69
  "speakers": "45M",
70
  "region": "West Africa",
@@ -83,8 +64,6 @@ LANGUAGES = {
83
  }
84
  },
85
  "Hausa": {
86
- "code": "hau",
87
- "tts_model": "facebook/mms-tts-hau",
88
  "emoji": "πŸ‡³πŸ‡¬",
89
  "speakers": "90M",
90
  "region": "West Africa",
@@ -99,112 +78,100 @@ LANGUAGES = {
99
  "help": "Ina iya taimakawa ka. Me na gida!",
100
  "thanks": "Nagode! Na gida!",
101
  "bye": "Sai anjima! Jiya!",
102
- "default": "Yoo, na ji ka. Me na gida!"
103
  }
104
  },
105
  "Amharic": {
106
- "code": "amh",
107
- "tts_model": "facebook/mms-tts-amh",
108
  "emoji": "πŸ‡ͺπŸ‡Ή",
109
  "speakers": "32M",
110
- "region": "Ethiopia",
111
  "keywords": {
112
- "greeting": ["αˆ°αˆ‹αˆ", "hello", "hi"],
113
  "thanks": ["αŠ αˆ˜αˆ°αŒαŠ“αˆˆαˆ", "thank"],
114
- "help": ["αˆŠαˆ¨α‹³αˆ…", "help"],
115
- "bye": ["α‹°αˆ…αŠ“", "goodbye"]
116
  },
117
  "responses": {
118
- "greeting": "αˆ°αˆ‹αˆ! αŠ₯αŠ•α‹°αˆαŠ• αŠαˆ…?",
119
- "help": "αˆŠαˆ¨α‹³αˆ… αŠ₯α‰½αˆ‹αˆˆαˆα’ αˆαŠ• α‹«αˆ΅αˆαˆαŒαˆƒαˆ?",
120
  "thanks": "αŠ αˆ˜αˆ°αŒαŠ“αˆˆαˆ! α‹°αˆ…αŠ“!",
121
- "bye": "α‹°αˆ…αŠ“ αˆαŠ•! αˆ°αˆ‹αˆ!",
122
- "default": "ሞክርፒ αˆαŠ• αˆŒαˆ‹ αˆŠαˆ¨α‹³αˆ… α‹­α‰½αˆ‹αˆ‰?"
123
  }
124
  },
125
  "Fon": {
126
- "code": "fon",
127
- "tts_model": "facebook/mms-tts-fon",
128
  "emoji": "πŸ‡§πŸ‡―",
129
  "speakers": "2M",
130
- "region": "Benin, Togo",
131
  "keywords": {
132
- "greeting": ["alekun", "hello", "hi"],
133
- "thanks": ["e ku", "thank"],
134
- "help": ["help"],
135
- "bye": ["daabo", "goodbye"]
136
  },
137
  "responses": {
138
- "greeting": "Alekun! Inu mαΊΉ?",
139
- "help": "MαΊΉ lαΊΉ wαΊΉ mαΊΉ. Kini nkan?",
140
- "thanks": "E ku ọpẹ! Ẹ kú!",
141
- "bye": "Γ“ dÑàbΓ²! αΊΈ kΓΊ ọjọ́!",
142
- "default": "Yoo, mo gbe e. Kini nkan?"
143
  }
144
  },
145
  "Oromo": {
146
- "code": "orm",
147
- "tts_model": "facebook/mms-tts-orm",
148
  "emoji": "πŸ‡ͺπŸ‡Ή",
149
  "speakers": "40M",
150
- "region": "Ethiopia, Kenya",
151
  "keywords": {
152
- "greeting": ["salaam", "hello", "hi", "akkam"],
153
- "thanks": ["galatomi", "thank"],
154
- "help": ["gargaaruu", "help"],
155
- "bye": ["nagaa", "goodbye"]
156
  },
157
  "responses": {
158
- "greeting": "Salaam! Akkam jirta?",
159
- "help": "Gargaaruu dandeenya. Maal barbaadda?",
160
- "thanks": "Galatomi! Nagaa!",
161
- "bye": "Nagaa! Booda beekta!",
162
- "default": "Eeyyee, hubadhe. Maal biraa?"
163
  }
164
  },
165
  "Somali": {
166
- "code": "som",
167
- "tts_model": "facebook/mms-tts-som",
168
  "emoji": "πŸ‡ΈπŸ‡΄",
169
  "speakers": "20M",
170
  "region": "East Africa",
171
  "keywords": {
172
- "greeting": ["salaam", "hello", "hi", "iska"],
173
  "thanks": ["mahadsanid", "thank"],
174
- "help": ["caawin", "help"],
175
- "bye": ["nabad", "goodbye"]
176
  },
177
  "responses": {
178
- "greeting": "Salaam! Iska warran?",
179
- "help": "Waan kaa caawin karaa. Maxaad doonaysaa?",
180
  "thanks": "Mahadsanid! Nabad!",
181
- "bye": "Nabad! Marka danbe!",
182
- "default": "Hah, waan ogsadaye. Wax kale?"
183
  }
184
  },
185
  "Tigrinya": {
186
- "code": "tir",
187
- "tts_model": "facebook/mms-tts-tir",
188
  "emoji": "πŸ‡ͺπŸ‡·",
189
  "speakers": "7M",
190
  "region": "Horn of Africa",
191
  "keywords": {
192
  "greeting": ["αˆ°αˆ‹αˆ", "hello", "hi"],
193
- "thanks": ["α‹΅αˆŠ", "thank"],
194
- "help": ["αˆ“αŒˆα‹", "help"],
195
- "bye": ["α‹°αˆ…αŠ“", "goodbye"]
196
  },
197
  "responses": {
198
- "greeting": "αˆ°αˆ‹αˆ! αŠ­αˆ˜α‹­ α‹²αŠ«?",
199
- "help": "αŠ­α‹‹ αˆ“αŒˆα‹ α‹­αŠ½αŠ₯ልፒ αŠ₯αŠ•α‰³α‹­ α‰΅α‹°αˆα‹©?",
200
- "thanks": "α‹΅αˆŠ! αŠ“α‹­ αˆ°αˆ‹αˆ!",
201
  "bye": "αˆ°αˆ‹αˆ! αˆšα‹›αŠ•!",
202
  "default": "αˆ™αˆŠα’ αŠ₯αŠ•α‰³α‹­ α‰°α‹ˆαˆ³αŠΊ?"
203
  }
204
  },
205
  "English": {
206
- "code": "eng",
207
- "tts_model": "facebook/mms-tts-eng",
208
  "emoji": "🌍",
209
  "speakers": "1.5B",
210
  "region": "Global",
@@ -224,203 +191,8 @@ LANGUAGES = {
224
  }
225
  }
226
 
227
- # Cache for loaded models
228
- model_cache = {}
229
  conversation_history = []
230
 
231
- # CSS
232
- CUSTOM_CSS = """
233
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
234
-
235
- * {
236
- font-family: 'Inter', sans-serif;
237
- }
238
-
239
- body {
240
- background: #ffffff;
241
- }
242
-
243
- .gradio-container {
244
- max-width: 100%;
245
- margin: 0;
246
- padding: 0;
247
- background: #ffffff;
248
- }
249
-
250
- .main-container {
251
- display: grid;
252
- grid-template-columns: 350px 1fr;
253
- min-height: 100vh;
254
- gap: 0;
255
- }
256
-
257
- .sidebar {
258
- background: #f8f9fa;
259
- border-right: 1px solid #e0e0e0;
260
- padding: 24px;
261
- overflow-y: auto;
262
- max-height: 100vh;
263
- }
264
-
265
- .sidebar-title {
266
- font-size: 14px;
267
- font-weight: 600;
268
- color: #666;
269
- text-transform: uppercase;
270
- letter-spacing: 0.5px;
271
- margin-bottom: 16px;
272
- }
273
-
274
- .content {
275
- padding: 40px 60px;
276
- display: flex;
277
- flex-direction: column;
278
- }
279
-
280
- .header {
281
- margin-bottom: 40px;
282
- }
283
-
284
- .logo {
285
- font-size: 28px;
286
- font-weight: 700;
287
- color: #000;
288
- margin-bottom: 20px;
289
- }
290
-
291
- .headline {
292
- font-size: 48px;
293
- font-weight: 700;
294
- color: #000;
295
- line-height: 1.2;
296
- margin-bottom: 16px;
297
- }
298
-
299
- .subheadline {
300
- font-size: 16px;
301
- color: #666;
302
- line-height: 1.5;
303
- }
304
-
305
- .input-section {
306
- background: #f8f9fa;
307
- border-radius: 8px;
308
- padding: 24px;
309
- margin-bottom: 24px;
310
- }
311
-
312
- .language-selector label {
313
- display: block;
314
- font-size: 13px;
315
- font-weight: 600;
316
- color: #333;
317
- margin-bottom: 8px;
318
- text-transform: uppercase;
319
- letter-spacing: 0.5px;
320
- }
321
-
322
- .language-selector select {
323
- width: 100%;
324
- padding: 12px;
325
- border: 1px solid #d0d0d0;
326
- border-radius: 6px;
327
- font-size: 14px;
328
- background: white;
329
- cursor: pointer;
330
- }
331
-
332
- .generate-btn {
333
- background: #000 !important;
334
- color: white !important;
335
- border: none !important;
336
- border-radius: 6px !important;
337
- padding: 12px 24px !important;
338
- font-weight: 600 !important;
339
- font-size: 14px !important;
340
- cursor: pointer !important;
341
- }
342
-
343
- .generate-btn:hover {
344
- background: #333 !important;
345
- }
346
-
347
- .output-section {
348
- background: #f8f9fa;
349
- border-radius: 8px;
350
- padding: 24px;
351
- }
352
-
353
- .output-label {
354
- font-size: 13px;
355
- font-weight: 600;
356
- color: #333;
357
- text-transform: uppercase;
358
- letter-spacing: 0.5px;
359
- margin-bottom: 16px;
360
- }
361
-
362
- .status-message {
363
- padding: 12px 16px;
364
- border-radius: 6px;
365
- font-size: 14px;
366
- margin-bottom: 16px;
367
- }
368
-
369
- .status-success {
370
- background: #d4edda;
371
- color: #155724;
372
- border: 1px solid #c3e6cb;
373
- }
374
-
375
- .status-error {
376
- background: #f8d7da;
377
- color: #721c24;
378
- border: 1px solid #f5c6cb;
379
- }
380
-
381
- @media (max-width: 768px) {
382
- .main-container {
383
- grid-template-columns: 1fr;
384
- }
385
-
386
- .sidebar {
387
- display: none;
388
- }
389
-
390
- .content {
391
- padding: 20px;
392
- }
393
-
394
- .headline {
395
- font-size: 32px;
396
- }
397
- }
398
- """
399
-
400
- def load_tts_model(language_name):
401
- """Load TTS model for the specified language."""
402
- if language_name not in LANGUAGES:
403
- return None
404
-
405
- lang_config = LANGUAGES[language_name]
406
- model_id = lang_config["tts_model"]
407
-
408
- if model_id in model_cache:
409
- return model_cache[model_id]
410
-
411
- try:
412
- print(f"Loading TTS model for {language_name}: {model_id}")
413
- synthesizer = pipeline(
414
- "text-to-speech",
415
- model=model_id,
416
- device=device if device == "cuda" else -1
417
- )
418
- model_cache[model_id] = synthesizer
419
- return synthesizer
420
- except Exception as e:
421
- print(f"Error loading model {model_id}: {e}")
422
- return None
423
-
424
  def detect_intent(text, language):
425
  """Detect user intent from text."""
426
  text_lower = text.lower()
@@ -444,188 +216,139 @@ def generate_response(text, language):
444
  intent = detect_intent(text, language)
445
  response = responses.get(intent, responses.get("default", "I understand."))
446
 
447
- return response, f"βœ… Response generated!"
448
- except Exception as e:
449
- print(f"Error generating response: {e}")
450
- return None, f"❌ Error: {str(e)}"
451
-
452
- def synthesize_speech(text, language):
453
- """Convert text to speech."""
454
- if not text or not text.strip():
455
- return None, "❌ No text to synthesize."
456
-
457
- try:
458
- synthesizer = load_tts_model(language)
459
- if synthesizer is None:
460
- return None, f"❌ Failed to load TTS model for {language}."
461
-
462
- print(f"Generating speech for: {text[:50]}...")
463
- speech = synthesizer(text)
464
-
465
- audio_array = np.array(speech["audio"]).flatten()
466
- sample_rate = speech["sampling_rate"]
467
-
468
- with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
469
- wavfile.write(f.name, sample_rate, (audio_array * 32767).astype(np.int16))
470
- temp_path = f.name
471
-
472
- return temp_path, "βœ… Speech generated!"
473
- except Exception as e:
474
- print(f"Error synthesizing: {e}")
475
- return None, f"❌ Error: {str(e)}"
476
-
477
- def process_text_input(text, language):
478
- """Process text input: generate response -> synthesize."""
479
- try:
480
- # Generate response
481
- response_text, response_status = generate_response(text, language)
482
- if response_text is None:
483
- return None, response_text, response_status
484
-
485
- # Synthesize response
486
- audio_output, synth_status = synthesize_speech(response_text, language)
487
-
488
  # Add to history
489
  conversation_history.append({
490
  "user": text,
491
- "agent": response_text,
492
- "timestamp": datetime.now().isoformat()
 
493
  })
494
 
495
- return audio_output, response_text, synth_status
496
  except Exception as e:
497
- print(f"Error processing: {e}")
498
- return None, None, f"❌ Error: {str(e)}"
499
 
500
  def create_interface():
501
  """Create the voice agent interface."""
502
 
503
  with gr.Blocks(
504
- title="JamboGPT - African Language AI Voice Agent",
505
- css=CUSTOM_CSS
506
  ) as demo:
507
 
508
- # Main container
509
- with gr.Row(equal_height=True):
510
- # Sidebar
511
- with gr.Column(scale=0, min_width=350):
512
- gr.Markdown(
513
- """
514
- <div class="sidebar">
515
- <div class="sidebar-title">πŸ—£οΈ Conversation History</div>
516
- <div style="text-align: center; color: #999; padding: 20px; font-size: 13px;">
517
- No conversations yet
518
- </div>
519
- </div>
520
- """
521
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
522
 
523
- # Main content
524
- with gr.Column(scale=1):
525
- # Header
526
- gr.Markdown(
527
- """
528
- <div class="header">
529
- <div class="logo">🌍 JamboGPT</div>
530
- <div class="headline">African Language AI Voice Agent</div>
531
- <div class="subheadline">Chat with AI in 9 African languages. Type or speak, and get intelligent responses in your language.</div>
532
- </div>
533
- """
534
- )
535
-
536
- # Input section
537
- with gr.Group():
538
- gr.Markdown('<div class="input-section">')
539
-
540
- # Language selector
541
- language_choice = gr.Dropdown(
542
- choices=list(LANGUAGES.keys()),
543
- value="Swahili",
544
- label="Select Language",
545
- interactive=True
546
- )
547
-
548
- # Language info
549
- language_info = gr.Markdown(
550
- f"πŸ‡°πŸ‡ͺ **Swahili** β€’ 100M+ speakers β€’ East Africa"
551
- )
552
-
553
- def update_language_info(language):
554
- if language in LANGUAGES:
555
- lang_data = LANGUAGES[language]
556
- return f"{lang_data['emoji']} **{language}** β€’ {lang_data['speakers']} speakers β€’ {lang_data['region']}"
557
- return ""
558
-
559
- language_choice.change(update_language_info, inputs=language_choice, outputs=language_info)
560
-
561
- # Text input
562
- text_input = gr.Textbox(
563
- label="Type your message in the selected language",
564
- placeholder="Type your message here...",
565
- lines=3,
566
- interactive=True
567
- )
568
-
569
- # Process button
570
- process_btn = gr.Button(
571
- "🎀 Generate Response",
572
- variant="primary",
573
- size="lg"
574
- )
575
-
576
- gr.Markdown('</div>')
577
-
578
- # Output section
579
- with gr.Group():
580
- gr.Markdown('<div class="output-section">')
581
-
582
- gr.Markdown('<div class="output-label">πŸ€– Agent Response</div>')
583
- agent_response = gr.Textbox(
584
- label="",
585
- interactive=False,
586
- placeholder="The agent's response will appear here"
587
- )
588
-
589
- gr.Markdown('<div class="output-label">πŸ”Š Agent Voice</div>')
590
- audio_output = gr.Audio(
591
- label="",
592
- type="filepath",
593
- interactive=False
594
- )
595
-
596
- status_message = gr.Textbox(
597
- label="Status",
598
- interactive=False,
599
- value="Ready to chat!"
600
- )
601
-
602
- gr.Markdown('</div>')
603
-
604
- # Footer
605
- gr.Markdown(
606
- """
607
- <div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #e0e0e0; font-size: 13px; color: #999;">
608
- <p>🌍 <strong>JamboGPT</strong> - African Language AI Voice Agent</p>
609
- <p>Chat in 9 African languages β€’ Powered by Hugging Face β€’ <a href="https://huggingface.co/spaces/stano03/jambogpt" style="color: #666;">View on Hugging Face</a></p>
610
- </div>
611
- """
612
- )
613
 
614
  # Connect process button
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
  process_btn.click(
616
- fn=process_text_input,
 
 
 
 
 
 
 
 
 
 
 
 
617
  inputs=[text_input, language_choice],
618
- outputs=[audio_output, agent_response, status_message]
 
 
619
  )
 
 
 
 
 
 
 
620
 
621
  return demo
622
 
623
  if __name__ == "__main__":
624
- print("πŸš€ Creating JamboGPT Voice Agent Interface...")
625
  demo = create_interface()
626
 
627
  print("=" * 50)
628
- print("βœ… JamboGPT Voice Agent is ready!")
629
  print("=" * 50)
630
 
631
  demo.launch(
 
1
  #!/usr/bin/env python3
2
  """
3
  JamboGPT - African Language AI Voice Agent
4
+ Simple, Lightweight Version for Hugging Face Spaces
5
  """
6
 
 
7
  import gradio as gr
 
 
 
 
 
8
  from datetime import datetime
 
 
 
 
 
 
 
9
 
10
  # Language configurations
11
  LANGUAGES = {
12
  "Swahili": {
 
 
13
  "emoji": "πŸ‡°πŸ‡ͺ",
14
  "speakers": "100M+",
15
  "region": "East Africa",
 
28
  }
29
  },
30
  "Kikuyu": {
 
 
31
  "emoji": "πŸ‡°πŸ‡ͺ",
32
  "speakers": "7M",
33
  "region": "Kenya",
 
46
  }
47
  },
48
  "Yoruba": {
 
 
49
  "emoji": "πŸ‡³πŸ‡¬",
50
  "speakers": "45M",
51
  "region": "West Africa",
 
64
  }
65
  },
66
  "Hausa": {
 
 
67
  "emoji": "πŸ‡³πŸ‡¬",
68
  "speakers": "90M",
69
  "region": "West Africa",
 
78
  "help": "Ina iya taimakawa ka. Me na gida!",
79
  "thanks": "Nagode! Na gida!",
80
  "bye": "Sai anjima! Jiya!",
81
+ "default": "I na gida. Me na gida?"
82
  }
83
  },
84
  "Amharic": {
 
 
85
  "emoji": "πŸ‡ͺπŸ‡Ή",
86
  "speakers": "32M",
87
+ "region": "Horn of Africa",
88
  "keywords": {
89
+ "greeting": ["αˆ°αˆ‹αˆ", "hello", "hi", "αˆ³αˆ‹αˆ"],
90
  "thanks": ["αŠ αˆ˜αˆ°αŒαŠ“αˆˆαˆ", "thank"],
91
+ "help": ["αˆšα‹›αŠ•", "help"],
92
+ "bye": ["α‹°αˆ…αŠ“", "goodbye", "bye"]
93
  },
94
  "responses": {
95
+ "greeting": "αˆ°αˆ‹αˆ! α‹°αˆ…αŠ“! αˆαŠ• α‹«αˆ΅αˆαˆαŒαˆƒαˆ?",
96
+ "help": "αˆšα‹›αŠ•! αŠ₯αŠ•α‰³α‹­ α‰΅α‹°αˆα‹©?",
97
  "thanks": "αŠ αˆ˜αˆ°αŒαŠ“αˆˆαˆ! α‹°αˆ…αŠ“!",
98
+ "bye": "αˆ°αˆ‹αˆ! αˆšα‹›αŠ•!",
99
+ "default": "αˆ™αˆŠα’ αŠ₯αŠ•α‰³α‹­ α‰°α‹ˆαˆ³αŠΊ?"
100
  }
101
  },
102
  "Fon": {
 
 
103
  "emoji": "πŸ‡§πŸ‡―",
104
  "speakers": "2M",
105
+ "region": "West Africa",
106
  "keywords": {
107
+ "greeting": ["bonjour", "hello", "hi"],
108
+ "thanks": ["merci", "thank"],
109
+ "help": ["aide", "help"],
110
+ "bye": ["au revoir", "goodbye", "bye"]
111
  },
112
  "responses": {
113
+ "greeting": "Bonjour! Comment allez-vous?",
114
+ "help": "Je peux vous aider. Qu'est-ce que vous voulez?",
115
+ "thanks": "Merci beaucoup! De rien!",
116
+ "bye": "Au revoir! Γ€ bientΓ΄t!",
117
+ "default": "Oui, je comprends. Quoi d'autre?"
118
  }
119
  },
120
  "Oromo": {
 
 
121
  "emoji": "πŸ‡ͺπŸ‡Ή",
122
  "speakers": "40M",
123
+ "region": "East Africa",
124
  "keywords": {
125
+ "greeting": ["salaam", "hello", "hi"],
126
+ "thanks": ["galataa", "thank"],
127
+ "help": ["gargaarsa", "help"],
128
+ "bye": ["nagaa", "goodbye", "bye"]
129
  },
130
  "responses": {
131
+ "greeting": "Salaam! Akkam jirtaa?",
132
+ "help": "Gargaarsa nan geedaru. Maal barbaadda?",
133
+ "thanks": "Galataa! Nagaa!",
134
+ "bye": "Nagaa! Haa jiraatin!",
135
+ "default": "Eeyyee, hubadha. Maal biraa?"
136
  }
137
  },
138
  "Somali": {
 
 
139
  "emoji": "πŸ‡ΈπŸ‡΄",
140
  "speakers": "20M",
141
  "region": "East Africa",
142
  "keywords": {
143
+ "greeting": ["salaam", "hello", "hi"],
144
  "thanks": ["mahadsanid", "thank"],
145
+ "help": ["caawi", "help"],
146
+ "bye": ["nabad", "goodbye", "bye"]
147
  },
148
  "responses": {
149
+ "greeting": "Salaam! Sidee tahay?",
150
+ "help": "Waan kaa caawin karaa. Maxaa baahan?",
151
  "thanks": "Mahadsanid! Nabad!",
152
+ "bye": "Nabad! Halkaa ku joog!",
153
+ "default": "Hah, waan fahmay. Maxaa kale?"
154
  }
155
  },
156
  "Tigrinya": {
 
 
157
  "emoji": "πŸ‡ͺπŸ‡·",
158
  "speakers": "7M",
159
  "region": "Horn of Africa",
160
  "keywords": {
161
  "greeting": ["αˆ°αˆ‹αˆ", "hello", "hi"],
162
+ "thanks": ["αŠ αˆ˜αˆ°αŒαŠ“αˆˆαˆ", "thank"],
163
+ "help": ["αˆšα‹›αŠ•", "help"],
164
+ "bye": ["α‹°αˆ…αŠ“", "goodbye", "bye"]
165
  },
166
  "responses": {
167
+ "greeting": "αˆ°αˆ‹αˆ! α‹΄αˆŒ ኒካ?",
168
+ "help": "αˆšα‹›αŠ•! αŠ₯αŠ•α‰³α‹­ α‰΅α‹°αˆα‹©?",
169
+ "thanks": "αŠ αˆ˜αˆ°αŒαŠ“αˆˆαˆ! α‹°αˆ…αŠ“!",
170
  "bye": "αˆ°αˆ‹αˆ! αˆšα‹›αŠ•!",
171
  "default": "αˆ™αˆŠα’ αŠ₯αŠ•α‰³α‹­ α‰°α‹ˆαˆ³αŠΊ?"
172
  }
173
  },
174
  "English": {
 
 
175
  "emoji": "🌍",
176
  "speakers": "1.5B",
177
  "region": "Global",
 
191
  }
192
  }
193
 
 
 
194
  conversation_history = []
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  def detect_intent(text, language):
197
  """Detect user intent from text."""
198
  text_lower = text.lower()
 
216
  intent = detect_intent(text, language)
217
  response = responses.get(intent, responses.get("default", "I understand."))
218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  # Add to history
220
  conversation_history.append({
221
  "user": text,
222
+ "agent": response,
223
+ "language": language,
224
+ "timestamp": datetime.now().strftime("%H:%M:%S")
225
  })
226
 
227
+ return response
228
  except Exception as e:
229
+ print(f"Error generating response: {e}")
230
+ return "I understand. Can you say more?"
231
 
232
  def create_interface():
233
  """Create the voice agent interface."""
234
 
235
  with gr.Blocks(
236
+ title="JamboGPT - African Language AI",
237
+ theme=gr.themes.Soft(primary_hue="purple")
238
  ) as demo:
239
 
240
+ gr.Markdown("""
241
+ # 🌍 JamboGPT - African Language AI
242
+
243
+ **Chat with AI in 10 African languages**
244
+
245
+ Swahili β€’ Kikuyu β€’ Yoruba β€’ Hausa β€’ Amharic β€’ Fon β€’ Oromo β€’ Somali β€’ Tigrinya β€’ English
246
+ """)
247
+
248
+ with gr.Group():
249
+ # Language selector
250
+ language_choice = gr.Dropdown(
251
+ choices=list(LANGUAGES.keys()),
252
+ value="Swahili",
253
+ label="Select Language",
254
+ interactive=True
255
+ )
256
+
257
+ # Language info
258
+ language_info = gr.Markdown(
259
+ f"πŸ‡°πŸ‡ͺ **Swahili** β€’ 100M+ speakers β€’ East Africa"
260
+ )
261
+
262
+ def update_language_info(language):
263
+ if language in LANGUAGES:
264
+ lang_data = LANGUAGES[language]
265
+ return f"{lang_data['emoji']} **{language}** β€’ {lang_data['speakers']} speakers β€’ {lang_data['region']}"
266
+ return ""
267
+
268
+ language_choice.change(update_language_info, inputs=language_choice, outputs=language_info)
269
 
270
+ # Text input
271
+ text_input = gr.Textbox(
272
+ label="Type your message",
273
+ placeholder="Type in your selected language...",
274
+ lines=3,
275
+ interactive=True
276
+ )
277
+
278
+ # Process button
279
+ process_btn = gr.Button(
280
+ "🎀 Generate Response",
281
+ variant="primary",
282
+ size="lg"
283
+ )
284
+
285
+ # Output section
286
+ with gr.Group():
287
+ agent_response = gr.Textbox(
288
+ label="πŸ€– Agent Response",
289
+ interactive=False,
290
+ placeholder="The agent's response will appear here"
291
+ )
292
+
293
+ # Conversation history
294
+ history_display = gr.Textbox(
295
+ label="πŸ“ Conversation History",
296
+ interactive=False,
297
+ lines=4,
298
+ placeholder="Your conversation history will appear here"
299
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
 
301
  # Connect process button
302
+ def process_input(text, language):
303
+ if not text:
304
+ return "Please enter some text!", ""
305
+
306
+ response = generate_response(text, language)
307
+
308
+ # Format history
309
+ history_text = ""
310
+ for msg in conversation_history[-5:]: # Show last 5 messages
311
+ history_text += f"[{msg['timestamp']}] {msg['language']}\n"
312
+ history_text += f"You: {msg['user']}\n"
313
+ history_text += f"Agent: {msg['agent']}\n\n"
314
+
315
+ return response, history_text
316
+
317
  process_btn.click(
318
+ fn=process_input,
319
+ inputs=[text_input, language_choice],
320
+ outputs=[agent_response, history_display]
321
+ )
322
+
323
+ # Examples
324
+ gr.Examples(
325
+ examples=[
326
+ ["Habari, karibu sana!", "Swahili"],
327
+ ["WΔ© mwega, karibu!", "Kikuyu"],
328
+ ["PαΊΉlαΊΉ o, bawo ni o se?", "Yoruba"],
329
+ ["Hello, how are you?", "English"],
330
+ ],
331
  inputs=[text_input, language_choice],
332
+ outputs=[agent_response],
333
+ fn=process_input,
334
+ cache_examples=False,
335
  )
336
+
337
+ gr.Markdown("""
338
+ ---
339
+ **JamboGPT** - Making AI Accessible to African Languages
340
+
341
+ πŸ”— [GitHub](https://github.com/stano03/jambogpt) | πŸ“Š [Dataset](https://huggingface.co/datasets/stano03/jambogpt-real-dataset)
342
+ """)
343
 
344
  return demo
345
 
346
  if __name__ == "__main__":
347
+ print("πŸš€ Creating JamboGPT Interface...")
348
  demo = create_interface()
349
 
350
  print("=" * 50)
351
+ print("βœ… JamboGPT is ready!")
352
  print("=" * 50)
353
 
354
  demo.launch(