AbdulWahab14 commited on
Commit
6644281
Β·
verified Β·
1 Parent(s): 648b063

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +605 -0
app.py ADDED
@@ -0,0 +1,605 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import pipeline
3
+ import PyPDF2
4
+ import re
5
+ import os
6
+ import io
7
+ import random
8
+ import time
9
+ from groq import Groq
10
+
11
+ # ==================== IMPORT HANDLING ====================
12
+ # Try different import methods for google genai
13
+ try:
14
+ from google import genai
15
+ from google.genai import types
16
+ print("βœ… Imported google.genai successfully")
17
+ except ImportError:
18
+ try:
19
+ import google.genai as genai
20
+ from google.genai import types
21
+ print("βœ… Imported google.genai as module")
22
+ except ImportError:
23
+ try:
24
+ from google_genai import genai
25
+ from google_genai import types
26
+ print("βœ… Imported google_genai")
27
+ except ImportError as e:
28
+ print(f"❌ Failed to import google genai: {e}")
29
+ genai = None
30
+ types = None
31
+
32
+ # ==================== CONFIGURATION ====================
33
+ # Setup tokens
34
+ hf_token = os.getenv("HF_TOKEN")
35
+ gemini_key = os.getenv("GEMINI_API_KEY")
36
+ groq_key = os.getenv("GROQ_API_KEY")
37
+
38
+ print(f"HF_TOKEN: {hf_token is not None}")
39
+ print(f"GEMINI_API_KEY: {gemini_key is not None}")
40
+ print(f"GROQ_API_KEY: {groq_key is not None}")
41
+
42
+ # Configure Gemini client
43
+ gemini_client = None
44
+ if gemini_key and genai:
45
+ try:
46
+ try:
47
+ gemini_client = genai.Client(api_key=gemini_key)
48
+ except:
49
+ try:
50
+ gemini_client = genai.client.Client(api_key=gemini_key)
51
+ except:
52
+ import google.generativeai as old_genai
53
+ old_genai.configure(api_key=gemini_key)
54
+ gemini_client = old_genai
55
+ print("βœ… Using legacy google.generativeai")
56
+
57
+ if gemini_client:
58
+ print("βœ… Gemini client configured")
59
+ except Exception as e:
60
+ print(f"❌ Gemini config error: {e}")
61
+ gemini_client = None
62
+
63
+ # Configure Groq client
64
+ groq_client = None
65
+ if groq_key:
66
+ try:
67
+ groq_client = Groq(api_key=groq_key)
68
+ print("βœ… Groq client configured")
69
+ except Exception as e:
70
+ print(f"❌ Groq config error: {e}")
71
+
72
+ # Lazy load summarizer
73
+ summarizer = None
74
+
75
+ def load_summarizer():
76
+ global summarizer
77
+ if summarizer is None:
78
+ try:
79
+ print("Loading summarizer...")
80
+ summarizer = pipeline("summarization", model="sshleifer/distilbart-cnn-12-6", device=-1)
81
+ print("βœ… Summarizer ready")
82
+ except Exception as e:
83
+ print(f"❌ Summarizer failed: {e}")
84
+ return summarizer
85
+
86
+ # ==================== STATUS CHECK ====================
87
+ def check_status():
88
+ statuses = []
89
+ if gemini_client:
90
+ statuses.append("βœ… Gemini Ready")
91
+ elif gemini_key:
92
+ statuses.append("⚠️ Gemini key present but SDK not loaded")
93
+ else:
94
+ statuses.append("❌ Gemini: Add GEMINI_API_KEY")
95
+
96
+ if groq_client:
97
+ statuses.append("βœ… Groq Ready")
98
+ elif groq_key:
99
+ statuses.append("⚠️ Groq key present but client failed")
100
+ else:
101
+ statuses.append("❌ Groq: Add GROQ_API_KEY")
102
+
103
+ return " | ".join(statuses)
104
+
105
+ # ==================== APP 1: PDF & ESSAY TOOLS ====================
106
+
107
+ def extract_text_from_pdf(pdf_file):
108
+ """Extract text from PDF - handle both file path and bytes"""
109
+ if pdf_file is None:
110
+ return None, "Please upload a PDF file."
111
+
112
+ try:
113
+ if isinstance(pdf_file, str):
114
+ with open(pdf_file, 'rb') as f:
115
+ pdf_reader = PyPDF2.PdfReader(f)
116
+ text = ""
117
+ for page in pdf_reader.pages:
118
+ page_text = page.extract_text()
119
+ if page_text:
120
+ text += page_text + "\n"
121
+ else:
122
+ if hasattr(pdf_file, 'read'):
123
+ pdf_bytes = pdf_file.read()
124
+ if hasattr(pdf_file, 'seek'):
125
+ pdf_file.seek(0)
126
+ else:
127
+ pdf_bytes = pdf_file
128
+
129
+ if isinstance(pdf_bytes, bytes):
130
+ pdf_stream = io.BytesIO(pdf_bytes)
131
+ else:
132
+ pdf_stream = io.BytesIO(pdf_bytes.encode() if isinstance(pdf_bytes, str) else pdf_bytes)
133
+
134
+ pdf_reader = PyPDF2.PdfReader(pdf_stream)
135
+ text = ""
136
+ for page in pdf_reader.pages:
137
+ page_text = page.extract_text()
138
+ if page_text:
139
+ text += page_text + "\n"
140
+
141
+ text = re.sub(r'\s+', ' ', text).strip()
142
+
143
+ if len(text) < 50:
144
+ return None, "Could not extract text. PDF may be image-based or scanned."
145
+
146
+ return text, None
147
+
148
+ except Exception as e:
149
+ return None, f"Error reading PDF: {str(e)}"
150
+
151
+ def summarize_with_gemini(text, max_length, min_length):
152
+ """Try to use Gemini for summarization"""
153
+ if not gemini_client or not gemini_key:
154
+ return None
155
+
156
+ try:
157
+ if hasattr(gemini_client, 'models'):
158
+ prompt = f"Summarize the following text in {min_length}-{max_length} words. Be concise and clear:\n\n{text[:15000]}"
159
+
160
+ try:
161
+ response = gemini_client.models.generate_content(
162
+ model="gemini-2.5-flash",
163
+ contents=prompt
164
+ )
165
+ return response.text
166
+ except:
167
+ try:
168
+ response = gemini_client.models.generate_content(
169
+ model="gemini-2.5-flash",
170
+ contents=prompt,
171
+ config=types.GenerateContentConfig(
172
+ max_output_tokens=500
173
+ ) if types else None
174
+ )
175
+ return response.text
176
+ except:
177
+ pass
178
+
179
+ if hasattr(gemini_client, 'GenerativeModel'):
180
+ model = gemini_client.GenerativeModel('gemini-2.5-flash')
181
+ prompt = f"Summarize the following text in {min_length}-{max_length} words:\n\n{text[:15000]}"
182
+ response = model.generate_content(prompt)
183
+ return response.text
184
+
185
+ except Exception as e:
186
+ print(f"Gemini summary error: {e}")
187
+
188
+ return None
189
+
190
+ def summarize_pdf(pdf_file, max_length, min_length):
191
+ text, error = extract_text_from_pdf(pdf_file)
192
+ if error:
193
+ return error
194
+
195
+ gemini_result = summarize_with_gemini(text, max_length, min_length)
196
+ if gemini_result:
197
+ return gemini_result
198
+
199
+ summ = load_summarizer()
200
+ if summ:
201
+ try:
202
+ result = summ(text[:3500], max_length=max_length, min_length=min_length, do_sample=False)
203
+ return result[0]['summary_text']
204
+ except Exception as e:
205
+ return f"Summarization error: {str(e)}"
206
+
207
+ return "Error: No summarization available"
208
+
209
+ def generate_essay_with_gemini(prompt, essay_type, word_count, tone):
210
+ """Generate essay using Gemini"""
211
+ if not gemini_client or not gemini_key:
212
+ return None
213
+
214
+ try:
215
+ full_prompt = f"""You are an expert academic writer. Write a {essay_type} essay in {tone} tone.
216
+ Target length: approximately {word_count} words.
217
+ Topic: {prompt}
218
+ Requirements:
219
+ - Engaging introduction with clear thesis statement
220
+ - Well-structured body paragraphs with supporting arguments and evidence
221
+ - Strong conclusion that summarizes main points
222
+ - Use academic vocabulary and formal writing style
223
+ Write the essay now:"""
224
+
225
+ if hasattr(gemini_client, 'models'):
226
+ try:
227
+ response = gemini_client.models.generate_content(
228
+ model="gemini-2.5-flash",
229
+ contents=full_prompt
230
+ )
231
+ essay = response.text.strip()
232
+ except:
233
+ if hasattr(gemini_client, 'GenerativeModel'):
234
+ model = gemini_client.GenerativeModel('gemini-2.5-flash')
235
+ response = model.generate_content(full_prompt)
236
+ essay = response.text.strip()
237
+ else:
238
+ return None
239
+ else:
240
+ model = gemini_client.GenerativeModel('gemini-2.5-flash')
241
+ response = model.generate_content(full_prompt)
242
+ essay = response.text.strip()
243
+
244
+ essay = re.sub(r'^#+\s*', '', essay)
245
+ word_count_actual = len(essay.split())
246
+
247
+ return f"""# {essay_type} Essay: {prompt[:50]}{'...' if len(prompt) > 50 else ''}
248
+ {essay}
249
+ ---
250
+ *~{word_count_actual} words | {tone} | Gemini*"""
251
+
252
+ except Exception as e:
253
+ print(f"Essay generation error: {e}")
254
+ return None
255
+
256
+ def generate_essay(prompt, essay_type, word_count, tone):
257
+ if not prompt or len(prompt.strip()) < 10:
258
+ return "Please provide a detailed prompt (at least 10 characters)."
259
+
260
+ if gemini_client and gemini_key:
261
+ gemini_result = generate_essay_with_gemini(prompt, essay_type, word_count, tone)
262
+ if gemini_result:
263
+ return gemini_result
264
+
265
+ return f"""❌ AI generation not available.
266
+ Template Essay: {prompt}
267
+ Introduction:
268
+ {prompt} is an important topic that requires careful consideration. This essay explores its key aspects.
269
+ Body:
270
+ The significance of {prompt} cannot be overstated. Various perspectives exist on this matter, with experts debating the best approaches. Research continues to reveal new insights.
271
+ Conclusion:
272
+ In conclusion, {prompt} represents a complex issue that demands attention.
273
+ ---
274
+ *Template fallback - Gemini SDK issue*
275
+ Check: 1) GEMINI_API_KEY is set 2) google-genai package is installed"""
276
+
277
+ def summarize_text(text, max_length, min_length):
278
+ if len(text.strip()) < 100:
279
+ return "Please provide at least 100 characters to summarize."
280
+
281
+ gemini_result = summarize_with_gemini(text, max_length, min_length)
282
+ if gemini_result:
283
+ return gemini_result
284
+
285
+ summ = load_summarizer()
286
+ if summ:
287
+ try:
288
+ result = summ(text[:3500], max_length=max_length, min_length=min_length, do_sample=False)
289
+ return result[0]['summary_text']
290
+ except Exception as e:
291
+ return f"Error: {str(e)}"
292
+
293
+ return "Error: No summarization available"
294
+
295
+ # ==================== APP 2: QUIZ GENERATOR ====================
296
+
297
+ def extract_sentences(text):
298
+ sentences = re.split(r'[.!?]', text)
299
+ return [s.strip() for s in sentences if len(s.split()) > 6]
300
+
301
+ def create_quiz(text, num_questions):
302
+ sentences = extract_sentences(text)
303
+
304
+ if len(sentences) < num_questions:
305
+ num_questions = len(sentences)
306
+
307
+ selected = random.sample(sentences, num_questions)
308
+
309
+ quiz_data = []
310
+
311
+ for sentence in selected:
312
+ words = sentence.split()
313
+ keyword = random.choice(words[2:-2])
314
+
315
+ question = sentence.replace(keyword, "_____")
316
+
317
+ all_words = list(set(text.split()))
318
+ wrong = random.sample(all_words, 3)
319
+
320
+ options = wrong + [keyword]
321
+ random.shuffle(options)
322
+
323
+ quiz_data.append({
324
+ "question": question,
325
+ "options": options,
326
+ "answer": keyword
327
+ })
328
+
329
+ return quiz_data
330
+
331
+ def start_quiz(text, num_questions, timer_minutes):
332
+ if not text.strip():
333
+ return "⚠️ Please enter study material.", None, None, None, None, None, None, ""
334
+
335
+ quiz = create_quiz(text, num_questions)
336
+
337
+ end_time = time.time() + (timer_minutes * 60)
338
+
339
+ return show_question(quiz, 0, 0, end_time)
340
+
341
+ def show_question(quiz, index, score, end_time):
342
+ if time.time() > end_time:
343
+ return finish_quiz(score, len(quiz))
344
+
345
+ if index >= len(quiz):
346
+ return finish_quiz(score, len(quiz))
347
+
348
+ q = quiz[index]
349
+
350
+ remaining = int(end_time - time.time())
351
+
352
+ timer_display = f"⏳ Time Left: {remaining} seconds"
353
+
354
+ return (
355
+ f"### Question {index+1}:\n\n{q['question']}",
356
+ gr.update(choices=q["options"], value=None),
357
+ f"Score: {score}",
358
+ quiz,
359
+ index,
360
+ score,
361
+ end_time,
362
+ timer_display
363
+ )
364
+
365
+ def submit_answer(selected, quiz, index, score, end_time):
366
+ if selected == quiz[index]["answer"]:
367
+ score += 1
368
+
369
+ index += 1
370
+ return show_question(quiz, index, score, end_time)
371
+
372
+ def finish_quiz(score, total):
373
+ return (
374
+ f"## βœ… Quiz Finished!\n\nFinal Score: **{score}/{total}**",
375
+ gr.update(choices=[]),
376
+ "",
377
+ None,
378
+ None,
379
+ None,
380
+ None,
381
+ ""
382
+ )
383
+
384
+ # ==================== APP 3: URDU TRANSLATOR ====================
385
+
386
+ def translate_to_urdu(text):
387
+ """Translate English text to Urdu using Groq's Llama 3.3 70B"""
388
+ if not text or not text.strip():
389
+ return "Please enter some text to translate."
390
+
391
+ if not groq_client:
392
+ return "❌ Groq API not configured. Please add GROQ_API_KEY."
393
+
394
+ try:
395
+ chat_completion = groq_client.chat.completions.create(
396
+ messages=[
397
+ {
398
+ "role": "system",
399
+ "content": "You are a professional English to Urdu translator. Translate the given text accurately to Urdu (اردو) using natural, conversational language. Respond ONLY with the translation, no explanations."
400
+ },
401
+ {
402
+ "role": "user",
403
+ "content": f"Translate to Urdu:\n\n{text}"
404
+ }
405
+ ],
406
+ model="llama-3.3-70b-versatile",
407
+ temperature=0.3,
408
+ max_completion_tokens=2048,
409
+ )
410
+
411
+ return chat_completion.choices[0].message.content
412
+
413
+ except Exception as e:
414
+ return f"Error: {str(e)}"
415
+
416
+ # ==================== CSS ====================
417
+
418
+ custom_css = """
419
+ .header {
420
+ text-align: center;
421
+ margin-bottom: 2rem;
422
+ padding: 2rem;
423
+ background: linear-gradient(135deg, #059669, #6b7280);
424
+ border-radius: 12px;
425
+ color: white;
426
+ }
427
+ .header h1 {
428
+ font-size: 2.5rem;
429
+ margin-bottom: 0.5rem;
430
+ }
431
+ .status-ok {
432
+ background: #d1fae5;
433
+ border: 2px solid #059669;
434
+ padding: 1rem;
435
+ border-radius: 8px;
436
+ text-align: center;
437
+ color: #065f46;
438
+ font-weight: bold;
439
+ margin-bottom: 1rem;
440
+ }
441
+ .status-warn {
442
+ background: #fef3c7;
443
+ border: 2px solid #f59e0b;
444
+ padding: 1rem;
445
+ border-radius: 8px;
446
+ text-align: center;
447
+ color: #92400e;
448
+ margin-bottom: 1rem;
449
+ }
450
+ .status-error {
451
+ background: #fee2e2;
452
+ border: 2px solid #ef4444;
453
+ padding: 1rem;
454
+ border-radius: 8px;
455
+ text-align: center;
456
+ color: #991b1b;
457
+ margin-bottom: 1rem;
458
+ }
459
+ @import url('https://fonts.googleapis.com/css2?family=Noto+Nastaliq+Urdu&display=swap');
460
+ .urdu-text {
461
+ font-family: 'Noto Nastaliq Urdu', serif;
462
+ font-size: 1.5em;
463
+ line-height: 2;
464
+ direction: rtl;
465
+ text-align: right;
466
+ }
467
+ """
468
+
469
+ # ==================== MAIN UI ====================
470
+
471
+ with gr.Blocks(title="Student AI Suite", css=custom_css) as demo:
472
+
473
+ # Status Display
474
+ status = check_status()
475
+ if "βœ…" in status and "❌" not in status:
476
+ gr.HTML(f'<div class="status-ok">{status}</div>')
477
+ elif "❌" in status:
478
+ gr.HTML(f'<div class="status-error">{status}</div>')
479
+ else:
480
+ gr.HTML(f'<div class="status-warn">{status}</div>')
481
+
482
+ gr.HTML('<div class="header"><h1>πŸŽ“ Student AI Suite</h1><p>Essay Generator β€’ PDF Summarizer β€’ Quiz Generator β€’ Urdu Translator</p></div>')
483
+
484
+ with gr.Tabs():
485
+
486
+ # ==================== TAB 1: PDF & ESSAY ====================
487
+ with gr.TabItem("πŸ“„ Essay & PDF Tools"):
488
+ with gr.Tabs():
489
+ with gr.TabItem("πŸ“‘ PDF Summarizer"):
490
+ pdf_input = gr.File(label="Upload PDF", file_types=[".pdf"], type="binary")
491
+ with gr.Row():
492
+ max_len = gr.Slider(50, 500, 200, step=10, label="Max Length")
493
+ min_len = gr.Slider(20, 200, 50, step=10, label="Min Length")
494
+ summarize_btn = gr.Button("πŸ“ Summarize PDF", variant="primary")
495
+ pdf_output = gr.Textbox(label="Summary", lines=12)
496
+
497
+ gr.Markdown("---")
498
+ text_input = gr.Textbox(label="Or paste text", lines=5)
499
+ text_btn = gr.Button("Summarize Text")
500
+ text_output = gr.Textbox(label="Summary", lines=8)
501
+
502
+ with gr.TabItem("✍️ Essay Generator"):
503
+ prompt_input = gr.Textbox(label="Essay Topic", placeholder="Example: 'The impact of AI on education'", lines=3)
504
+ essay_type = gr.Dropdown(["Argumentative", "Expository", "Descriptive", "Persuasive"], value="Argumentative")
505
+ tone = gr.Dropdown(["Academic", "Formal", "Neutral"], value="Academic")
506
+ words = gr.Slider(200, 1000, 500, step=50, label="Word Count")
507
+ gen_btn = gr.Button("✨ Generate Essay", variant="primary")
508
+ essay_output = gr.Textbox(label="Generated Essay", lines=25)
509
+
510
+ # ==================== TAB 2: QUIZ GENERATOR ====================
511
+ with gr.TabItem("🎯 Smart Quiz Generator"):
512
+ gr.Markdown("### Paste your study text β†’ generate quiz β†’ test yourself!")
513
+
514
+ quiz_text_input = gr.Textbox(lines=6, label="Study Material")
515
+
516
+ with gr.Row():
517
+ num_questions = gr.Slider(1, 10, value=5, step=1, label="Number of Questions")
518
+ timer_minutes = gr.Slider(1, 10, value=2, step=1, label="Timer (Minutes)")
519
+
520
+ start_btn = gr.Button("Start Quiz", variant="primary")
521
+
522
+ question_box = gr.Markdown()
523
+ options_radio = gr.Radio(label="Select Answer")
524
+ submit_btn = gr.Button("Submit Answer", variant="secondary")
525
+ score_display = gr.Markdown()
526
+ timer_display = gr.Markdown()
527
+
528
+ # Hidden states for quiz
529
+ quiz_state = gr.State()
530
+ index_state = gr.State()
531
+ score_state = gr.State()
532
+ endtime_state = gr.State()
533
+
534
+ # ==================== TAB 3: URDU TRANSLATOR ====================
535
+ with gr.TabItem("🌍 English to Urdu"):
536
+ gr.Markdown("### Powered by Groq AI")
537
+
538
+ with gr.Row():
539
+ with gr.Column():
540
+ input_text = gr.Textbox(
541
+ label="English Text",
542
+ placeholder="Enter text to translate...",
543
+ lines=4
544
+ )
545
+ translate_btn = gr.Button("Translate", variant="primary")
546
+
547
+ with gr.Column():
548
+ output_text = gr.Textbox(
549
+ label="Urdu Translation (اردو)",
550
+ lines=4,
551
+ elem_classes=["urdu-text"],
552
+ interactive=False
553
+ )
554
+
555
+ examples = [
556
+ "Hello, how are you?",
557
+ "I love Pakistan.",
558
+ "The weather is beautiful today."
559
+ ]
560
+ gr.Examples(examples=examples, inputs=input_text)
561
+
562
+ # ==================== EVENT HANDLERS ====================
563
+
564
+ # PDF & Essay handlers
565
+ summarize_btn.click(summarize_pdf, [pdf_input, max_len, min_len], pdf_output)
566
+ text_btn.click(summarize_text, [text_input, max_len, min_len], text_output)
567
+ gen_btn.click(generate_essay, [prompt_input, essay_type, words, tone], essay_output)
568
+
569
+ # Quiz handlers
570
+ start_btn.click(
571
+ start_quiz,
572
+ inputs=[quiz_text_input, num_questions, timer_minutes],
573
+ outputs=[
574
+ question_box,
575
+ options_radio,
576
+ score_display,
577
+ quiz_state,
578
+ index_state,
579
+ score_state,
580
+ endtime_state,
581
+ timer_display
582
+ ]
583
+ )
584
+
585
+ submit_btn.click(
586
+ submit_answer,
587
+ inputs=[options_radio, quiz_state, index_state, score_state, endtime_state],
588
+ outputs=[
589
+ question_box,
590
+ options_radio,
591
+ score_display,
592
+ quiz_state,
593
+ index_state,
594
+ score_state,
595
+ endtime_state,
596
+ timer_display
597
+ ]
598
+ )
599
+
600
+ # Urdu translator handlers
601
+ translate_btn.click(fn=translate_to_urdu, inputs=input_text, outputs=output_text)
602
+ input_text.submit(fn=translate_to_urdu, inputs=input_text, outputs=output_text)
603
+
604
+ if __name__ == "__main__":
605
+ demo.launch(server_name="0.0.0.0", server_port=7860)