besucoder commited on
Commit
026c626
Β·
verified Β·
1 Parent(s): df8a083
Files changed (1) hide show
  1. app.py +244 -176
app.py CHANGED
@@ -1,223 +1,293 @@
1
- import subprocess
2
- subprocess.run(["pip", "install", "faiss-cpu"], check=True)
3
  import gradio as gr
4
  import wikipedia
5
  import numpy as np
6
- import faiss
7
- from gtts import gTTS
8
  import tempfile
 
 
 
 
9
  from langdetect import detect
10
- import speech_recognition as sr
11
  from pydub import AudioSegment
12
- from transformers import pipeline
13
- from sentence_transformers import SentenceTransformer
14
- import os
15
  from pydub.silence import split_on_silence
16
- import time
 
 
 
 
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- # Initialize models
20
- models = {
21
- 'translator': pipeline('translation', model='Helsinki-NLP/opus-mt-mul-en'),
22
- 'answer_gen': pipeline('text2text-generation', model='google/flan-t5-base'),
23
- 'encoder': SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
24
- }
25
 
26
- # Add translation models
27
- for lang in ['fr', 'ar', 'zh', 'es']:
28
- models[f'en_to_{lang}'] = pipeline(f'translation_en_to_{lang}',
29
- model=f'Helsinki-NLP/opus-mt-en-{lang}')
 
 
 
 
 
 
 
 
 
 
30
 
31
- def translate(text, src, tgt):
32
- if src == tgt: return text
33
- if src != 'en': text = models['translator'](text)[0]['translation_text']
34
- if f'en_to_{tgt}' in models: return models[f'en_to_{tgt}'](text)[0]['translation_text']
35
- return text
36
 
37
- def text_to_speech(text, lang):
38
- try:
39
- tts = gTTS(text=text, lang=lang)
40
- audio_path = tempfile.mktemp(suffix='.mp3')
41
- tts.save(audio_path)
42
- return audio_path
43
- except Exception as e:
44
- print(f"TTS Error: {e}")
45
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
- def process_audio(audio_path):
48
- recognizer = sr.Recognizer()
49
- sound = AudioSegment.from_file(audio_path)
50
- chunks = split_on_silence(sound,
51
- min_silence_len=500,
52
- silence_thresh=sound.dBFS-14,
53
- keep_silence=500
54
- )
55
 
56
- full_text = ""
57
- for chunk in chunks:
58
- chunk_path = tempfile.mktemp(suffix='.wav')
59
- chunk.export(chunk_path, format="wav")
60
- with sr.AudioFile(chunk_path) as source:
61
- audio = recognizer.record(source)
62
- try:
63
- text = recognizer.recognize_google(audio)
64
- full_text += f" {text}"
65
- except:
66
- continue
67
- os.unlink(chunk_path)
68
-
69
- return full_text.strip() if full_text else None
70
-
71
- def get_wikipedia_content(topic):
72
  try:
73
  wikipedia.set_lang('en')
74
  try:
75
  page = wikipedia.page(topic, auto_suggest=False)
76
- return page.summary[:1000]
77
  except wikipedia.exceptions.DisambiguationError as e:
78
  page = wikipedia.page(e.options[0])
79
- return page.summary[:1000]
80
  except Exception as e:
81
  print(f"Wikipedia error: {e}")
82
- return None
83
-
84
- def generate_response(text, topic, lang):
85
- context = get_wikipedia_content(topic)
86
- if not context:
87
  return "Could not find information. Please try another topic.", None
88
 
89
  prompt = f"Context: {context}\nQuestion: {text}\nAnswer:"
90
  answer = models['answer_gen'](prompt, max_length=200)[0]['generated_text']
91
  translated = translate(answer, 'en', lang) if lang != 'en' else answer
92
  audio_path = text_to_speech(translated, lang)
93
-
94
  return translated, audio_path
95
 
96
- def handle_interaction(audio, text, topic, lang, chat_history):
97
- if audio is not None:
98
- recognized_text = process_audio(audio)
99
- if recognized_text:
100
- text = recognized_text
101
- else:
102
- chat_history.append(("", "Could not understand audio. Please try again."))
103
- return chat_history, "", None
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  if not text.strip():
106
- chat_history.append(("", "Please enter a question."))
 
 
 
 
 
 
 
 
107
  return chat_history, "", None
108
-
109
  response, audio_output = generate_response(text, topic, lang)
110
  chat_history.append((text, response))
111
-
112
  return chat_history, "", audio_output
113
 
114
- # Custom CSS with light blue and dark blue theme
115
- custom_css = """
116
- .gradio-container {
117
- background: #f0f8ff !important;
118
- border: 3px solid #00008b !important;
119
- border-radius: 10px !important;
120
- font-family: 'Arial', sans-serif;
121
- }
122
- .gr-box {
123
- background-color: #e6f2ff !important;
124
- border: 2px solid #00008b !important;
125
- border-radius: 8px !important;
126
- }
127
- .gr-button {
128
- background-color: #4d94ff !important;
129
- border: 2px solid #00008b !important;
130
- color: white !important;
131
- border-radius: 6px !important;
132
- }
133
- .gr-button:hover {
134
- background-color: #1a75ff !important;
135
- }
136
- .gr-chatbot {
137
- background-color: #e6f2ff !important;
138
- border: 2px solid #00008b !important;
139
- border-radius: 8px !important;
140
- }
141
- .gr-textbox, .gr-dropdown, .gr-audio {
142
- background-color: #e6f2ff !important;
143
- border: 2px solid #00008b !important;
144
- border-radius: 6px !important;
145
- }
146
- .welcome-header {
147
- text-align: center;
148
- color: #00008b !important;
149
- margin-bottom: 20px;
150
- }
151
- .welcome-message {
152
- background-color: #e6f2ff;
153
- padding: 20px;
154
- border-radius: 10px;
155
- border: 2px solid #00008b;
156
- margin-bottom: 20px;
157
- }
158
- .avatar {
159
- width: 80px;
160
- height: 80px;
161
- margin: 0 auto;
162
- display: block;
163
- }
164
- """
165
 
166
- # Welcome page content
167
- welcome_html = """
168
- <div class="welcome-header">
169
- <img src="https://i.imgur.com/6wBs5mO.png" class="avatar" alt="AI Assistant">
170
- <h1>Welcome to Your Multilingual AI Assistant! 🌍</h1>
171
- </div>
172
- <div class="welcome-message">
173
- <h3>Hello! I'm your personal Wikipedia assistant πŸ€–</h3>
174
- <p>I can help you find information on any topic in multiple languages. Here's what I can do:</p>
175
- <ul>
176
- <li>πŸ” Answer questions from Wikipedia knowledge</li>
177
- <li>πŸ—£οΈ Understand both voice and text input</li>
178
- <li>🌐 Respond in English, French, Spanish, Chinese, or Arabic</li>
179
- <li>πŸ”Š Speak answers back to you</li>
180
- </ul>
181
- <p>To get started, simply type your question or click the microphone to speak!</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  </div>
183
  """
184
 
185
- with gr.Blocks(css=custom_css, title="🌍 Multilingual AI Assistant") as demo:
186
- # Welcome page
187
- gr.HTML(welcome_html)
188
-
189
- # Main interface
190
  with gr.Row():
191
  with gr.Column(scale=1):
192
- audio_input = gr.Audio(
193
- sources=["microphone", "upload"],
194
- type="filepath",
195
- label="🎀 Speak or upload audio",
196
- interactive=True
197
- )
198
- topic_input = gr.Textbox(
199
- "Artificial Intelligence",
200
- label="πŸ“š Wikipedia Topic"
201
- )
202
- lang_input = gr.Dropdown(
203
- ["en", "fr", "es", "zh", "ar"],
204
- value="en",
205
- label="🌐 Output Language"
206
- )
207
-
208
  with gr.Column(scale=2):
209
  chatbot = gr.Chatbot(label="Conversation")
210
- text_input = gr.Textbox(
211
- placeholder="Type your question here...",
212
- label="✏️ Or type here"
213
- )
214
  with gr.Row():
215
  clear_btn = gr.Button("πŸ—‘οΈ Clear Chat")
216
  submit_btn = gr.Button("πŸš€ Submit", variant="primary")
217
-
218
  audio_output = gr.Audio(label="πŸ”Š Answer", visible=True)
219
-
220
- # Event handlers
221
  submit_btn.click(
222
  handle_interaction,
223
  inputs=[audio_input, text_input, topic_input, lang_input, chatbot],
@@ -228,9 +298,7 @@ with gr.Blocks(css=custom_css, title="🌍 Multilingual AI Assistant") as demo:
228
  inputs=[audio_input, text_input, topic_input, lang_input, chatbot],
229
  outputs=[chatbot, text_input, audio_output]
230
  )
231
- clear_btn.click(
232
- lambda: ([], "", None),
233
- outputs=[chatbot, text_input, audio_output]
234
- )
235
 
236
- demo.launch(share=True)
 
 
1
+ # app.py
 
2
  import gradio as gr
3
  import wikipedia
4
  import numpy as np
 
 
5
  import tempfile
6
+ import os
7
+ import time
8
+ from datetime import datetime, timedelta
9
+ from gtts import gTTS
10
  from langdetect import detect
 
11
  from pydub import AudioSegment
 
 
 
12
  from pydub.silence import split_on_silence
13
+ import speech_recognition as sr
14
+ from sentence_transformers import SentenceTransformer
15
+ from transformers import pipeline
16
+ import re
17
+ import torch
18
 
19
+ # --- USER MANAGEMENT SYSTEM ---
20
+ class UserManager:
21
+ def __init__(self):
22
+ self.user_data = {}
23
+ self.max_warnings = 1
24
+ self.block_duration = timedelta(days=30)
25
+
26
+ def get_user_status(self, user_id):
27
+ if user_id not in self.user_data:
28
+ return "active"
29
+ if self.user_data[user_id].get('permanently_banned', False):
30
+ return "banned"
31
+ if 'blocked_until' in self.user_data[user_id]:
32
+ if datetime.now() < self.user_data[user_id]['blocked_until']:
33
+ return "blocked"
34
+ del self.user_data[user_id]['blocked_until']
35
+ return "active"
36
+
37
+ def add_warning(self, user_id, violation_type):
38
+ if user_id not in self.user_data:
39
+ self.user_data[user_id] = {'warnings': 1, 'flags': [violation_type]}
40
+ else:
41
+ self.user_data[user_id]['warnings'] += 1
42
+ self.user_data[user_id]['flags'].append(violation_type)
43
+
44
+ if self.user_data[user_id]['warnings'] > self.max_warnings:
45
+ self.user_data[user_id]['blocked_until'] = datetime.now() + self.block_duration
46
+ return "blocked"
47
+ return "warned"
48
 
49
+ user_manager = UserManager()
 
 
 
 
 
50
 
51
+ # --- MODEL INITIALIZATION ---
52
+ def load_models():
53
+ models = {
54
+ 'translator': pipeline('translation', model='Helsinki-NLP/opus-mt-mul-en'),
55
+ 'answer_gen': pipeline('text2text-generation', model='google/flan-t5-base'),
56
+ 'encoder': SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2'),
57
+ 'toxic-bert': pipeline("text-classification", model="unitary/toxic-bert"),
58
+ 'roberta-hate': pipeline("text-classification", model="facebook/roberta-hate-speech-dynabench-r4-target")
59
+ }
60
+
61
+ for lang in ['fr', 'ar', 'zh', 'es']:
62
+ models[f'en_to_{lang}'] = pipeline(f'translation_en_to_{lang}', model=f'Helsinki-NLP/opus-mt-en-{lang}')
63
+
64
+ return models
65
 
66
+ models = load_models()
 
 
 
 
67
 
68
+ # --- UNIVERSAL HATE SPEECH DETECTION ---
69
+ class HateSpeechDetector:
70
+ def __init__(self):
71
+ self.keyword_banks = {
72
+ 'racial': ['nigger', 'chink', 'spic', 'kike', 'gook', 'wetback'],
73
+ 'gender': ['fag', 'dyke', 'tranny', 'whore', 'slut', 'bitch'],
74
+ 'violence': ['kill', 'murder', 'harm', 'hurt', 'abuse', 'torture'],
75
+ 'general': ['scum', 'vermin', 'subhuman', 'untermensch']
76
+ }
77
+
78
+ self.patterns = [
79
+ (r'\b(all|every)\s\w+\s(should|must)\s(die|burn)', 'group violence'),
80
+ (r'\b(how to|ways? to)\s(kill|harm|hurt)', 'harm instructions'),
81
+ (r'[!@#$%^&*]igg[!@#$%^&*]', 'coded racial slur')
82
+ ]
83
+
84
+ def detect(self, text):
85
+ text_lower = text.lower()
86
+ violations = []
87
+
88
+ # Keyword detection
89
+ for category, keywords in self.keyword_banks.items():
90
+ found = [kw for kw in keywords if kw in text_lower]
91
+ if found:
92
+ violations.append(f"{category} terms: {', '.join(found[:3])}")
93
+
94
+ # Pattern detection
95
+ for pattern, desc in self.patterns:
96
+ if re.search(pattern, text_lower):
97
+ violations.append(f"pattern: {desc}")
98
+
99
+ # Model detection
100
+ try:
101
+ toxic_result = models['toxic-bert'](text)[0]
102
+ if toxic_result['label'].lower() in ['toxic', 'hate'] and toxic_result['score'] > 0.7:
103
+ violations.append(f"toxic-bert: {toxic_result['label']} ({toxic_result['score']:.2f})")
104
+
105
+ hate_result = models['roberta-hate'](text)[0]
106
+ if hate_result['label'].lower() in ['hate', 'offensive'] and hate_result['score'] > 0.7:
107
+ violations.append(f"roberta-hate: {hate_result['label']} ({hate_result['score']:.2f})")
108
+ except Exception as e:
109
+ print(f"Model error: {e}")
110
+
111
+ return violations if violations else None
112
 
113
+ hate_detector = HateSpeechDetector()
 
 
 
 
 
 
 
114
 
115
+ # --- RESPONSE GENERATION ---
116
+ def generate_response(text, topic, lang):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  try:
118
  wikipedia.set_lang('en')
119
  try:
120
  page = wikipedia.page(topic, auto_suggest=False)
121
+ context = page.summary[:1000]
122
  except wikipedia.exceptions.DisambiguationError as e:
123
  page = wikipedia.page(e.options[0])
124
+ context = page.summary[:1000]
125
  except Exception as e:
126
  print(f"Wikipedia error: {e}")
 
 
 
 
 
127
  return "Could not find information. Please try another topic.", None
128
 
129
  prompt = f"Context: {context}\nQuestion: {text}\nAnswer:"
130
  answer = models['answer_gen'](prompt, max_length=200)[0]['generated_text']
131
  translated = translate(answer, 'en', lang) if lang != 'en' else answer
132
  audio_path = text_to_speech(translated, lang)
 
133
  return translated, audio_path
134
 
135
+ # --- WARNING MESSAGES ---
136
+ def create_warning_message(violations):
137
+ return gr.HTML(f"""
138
+ <div style='
139
+ border: 2px solid #ff0000;
140
+ border-radius: 5px;
141
+ padding: 10px;
142
+ background-color: #fff0f0;
143
+ margin: 10px 0;
144
+ '>
145
+ <div style='color: #ff0000; font-weight: bold;'>
146
+ ⚠️ WARNING: Violation Detected
147
+ </div>
148
+ <div style='margin-top: 8px;'>
149
+ Your message contains prohibited content
150
+ </div>
151
+ <div style='margin-top: 8px; font-size: 0.9em;'>
152
+ <b>Reason:</b> {', '.join(violations[:2])}
153
+ </div>
154
+ </div>
155
+ """)
156
 
157
+ def create_blocked_message():
158
+ return gr.HTML("""
159
+ <div style='
160
+ border: 2px solid #990000;
161
+ border-radius: 5px;
162
+ padding: 10px;
163
+ background-color: #ffebee;
164
+ '>
165
+ β›” ACCOUNT TEMPORARILY SUSPENDED
166
+ </div>
167
+ """)
168
+
169
+ # --- MAIN HANDLER ---
170
+ def handle_interaction(audio, text, topic, lang, chat_history, request: gr.Request):
171
+ user_id = request.client.host if request else "default_user"
172
+ status = user_manager.get_user_status(user_id)
173
+
174
+ if status == "banned":
175
+ return chat_history.append(("", "β›” Account permanently banned")), "", None
176
+ if status == "blocked":
177
+ return chat_history.append(("", create_blocked_message())), "", None
178
+
179
+ if audio:
180
+ text = process_audio(audio) or text
181
+
182
  if not text.strip():
183
+ return chat_history.append(("", "✏️ Please enter a question")), "", None
184
+
185
+ violations = hate_detector.detect(text)
186
+ if violations:
187
+ action = user_manager.add_warning(user_id, violations[0])
188
+ if action == "warned":
189
+ chat_history.append((text, create_warning_message(violations)))
190
+ elif action == "blocked":
191
+ chat_history.append(("", create_blocked_message()))
192
  return chat_history, "", None
193
+
194
  response, audio_output = generate_response(text, topic, lang)
195
  chat_history.append((text, response))
 
196
  return chat_history, "", audio_output
197
 
198
+ # --- AUDIO PROCESSING ---
199
+ def process_audio(audio_path):
200
+ recognizer = sr.Recognizer()
201
+ sound = AudioSegment.from_file(audio_path)
202
+ chunks = split_on_silence(sound, min_silence_len=500, silence_thresh=sound.dBFS-14)
203
+
204
+ full_text = ""
205
+ for chunk in chunks:
206
+ with tempfile.NamedTemporaryFile(suffix='.wav') as f:
207
+ chunk.export(f.name, format="wav")
208
+ with sr.AudioFile(f.name) as source:
209
+ audio = recognizer.record(source)
210
+ try: full_text += recognizer.recognize_google(audio) + " "
211
+ except: continue
212
+ return full_text.strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
 
214
+ def text_to_speech(text, lang):
215
+ try:
216
+ tts = gTTS(text=text, lang=lang)
217
+ with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as f:
218
+ tts.save(f.name)
219
+ return f.name
220
+ except Exception as e:
221
+ print(f"TTS Error: {e}")
222
+ return None
223
+
224
+ def translate(text, src, tgt):
225
+ if src == tgt: return text
226
+ if src != 'en': text = models['translator'](text)[0]['translation_text']
227
+ if f'en_to_{tgt}' in models: return models[f'en_to_{tgt}'](text)[0]['translation_text']
228
+ return text
229
+
230
+ # --- INTERACTIVE DESCRIPTION ---
231
+ description_html = """
232
+ <div style="font-family: 'Arial', sans-serif; max-width: 800px; margin: 0 auto;">
233
+ <div style="text-align: center; margin-bottom: 30px;">
234
+ <img src="https://i.imgur.com/6wBs5mO.png" style="width: 120px; height: 120px; border-radius: 50%; border: 3px solid #00008b;">
235
+ <h1 style="color: #00008b; margin-top: 15px;">🌍 Multilingual AI Assistant</h1>
236
+ <p style="color: #555;">Powered by Transformers and Gradio</p>
237
+ </div>
238
+
239
+ <div style="background-color: #e6f2ff; padding: 25px; border-radius: 10px; border: 2px solid #00008b; margin-bottom: 20px;">
240
+ <h2 style="color: #00008b; margin-top: 0;">✨ Features</h2>
241
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
242
+ <div style="background: white; padding: 15px; border-radius: 8px;">
243
+ <h3 style="margin-top: 0;">πŸ” Wikipedia Knowledge</h3>
244
+ <p>Answers questions using Wikipedia content</p>
245
+ </div>
246
+ <div style="background: white; padding: 15px; border-radius: 8px;">
247
+ <h3 style="margin-top: 0;">πŸ—£οΈ Voice Interaction</h3>
248
+ <p>Speak or type your questions</p>
249
+ </div>
250
+ <div style="background: white; padding: 15px; border-radius: 8px;">
251
+ <h3 style="margin-top: 0;">🌐 5 Languages</h3>
252
+ <p>English, French, Spanish, Chinese, Arabic</p>
253
+ </div>
254
+ <div style="background: white; padding: 15px; border-radius: 8px;">
255
+ <h3 style="margin-top: 0;">πŸ›‘οΈ Content Moderation</h3>
256
+ <p>Automated hate speech detection</p>
257
+ </div>
258
+ </div>
259
+ </div>
260
+
261
+ <div style="background-color: #fff0f0; padding: 25px; border-radius: 10px; border: 2px solid #ff0000; margin-bottom: 20px;">
262
+ <h2 style="color: #ff0000; margin-top: 0;">🚫 Restricted Content</h2>
263
+ <ul>
264
+ <li>Hate speech or discrimination</li>
265
+ <li>Violent or harmful content</li>
266
+ <li>Personal/medical/legal advice</li>
267
+ </ul>
268
+ </div>
269
  </div>
270
  """
271
 
272
+ # --- GRADIO INTERFACE ---
273
+ with gr.Blocks(title="🌍 Multilingual AI Assistant") as demo:
274
+ gr.HTML(description_html)
275
+
 
276
  with gr.Row():
277
  with gr.Column(scale=1):
278
+ audio_input = gr.Audio(sources=["microphone", "upload"], type="filepath", label="🎀 Speak or upload audio")
279
+ topic_input = gr.Textbox("Artificial Intelligence", label="πŸ“š Wikipedia Topic")
280
+ lang_input = gr.Dropdown(["en", "fr", "es", "zh", "ar"], value="en", label="🌐 Output Language")
281
+
 
 
 
 
 
 
 
 
 
 
 
 
282
  with gr.Column(scale=2):
283
  chatbot = gr.Chatbot(label="Conversation")
284
+ text_input = gr.Textbox(placeholder="Type your question...", label="✏️ Or type here")
 
 
 
285
  with gr.Row():
286
  clear_btn = gr.Button("πŸ—‘οΈ Clear Chat")
287
  submit_btn = gr.Button("πŸš€ Submit", variant="primary")
288
+
289
  audio_output = gr.Audio(label="πŸ”Š Answer", visible=True)
290
+
 
291
  submit_btn.click(
292
  handle_interaction,
293
  inputs=[audio_input, text_input, topic_input, lang_input, chatbot],
 
298
  inputs=[audio_input, text_input, topic_input, lang_input, chatbot],
299
  outputs=[chatbot, text_input, audio_output]
300
  )
301
+ clear_btn.click(lambda: ([], "", None), outputs=[chatbot, text_input, audio_output])
 
 
 
302
 
303
+ if __name__ == "__main__":
304
+ demo.launch(share=True)