mikaelJ46 commited on
Commit
ce4e117
Β·
verified Β·
1 Parent(s): 2383f44

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -82
app.py CHANGED
@@ -18,18 +18,18 @@ try:
18
  provider="novita",
19
  api_key=os.environ.get("HF_TOKEN"),
20
  )
21
- print("βœ… Z.ai GLM-4.6 initialized successfully")
22
  except Exception as e:
23
- print(f"⚠️ Error initializing Z.ai: {e}")
24
  zai_client = None
25
 
26
  # Cohere (Secondary)
27
  try:
28
  import cohere
29
  cohere_client = cohere.Client(os.getenv("COHERE_API_KEY"))
30
- print("βœ… Cohere initialized successfully")
31
  except Exception as e:
32
- print(f"⚠️ Error initializing Cohere: {e}")
33
  cohere_client = None
34
 
35
  # MiniMax (Tertiary)
@@ -38,9 +38,9 @@ try:
38
  provider="novita",
39
  api_key=os.environ.get("HF_TOKEN"),
40
  )
41
- print("βœ… MiniMax AI initialized successfully")
42
  except Exception as e:
43
- print(f"⚠️ Error initializing MiniMax: {e}")
44
  minimax_client = None
45
 
46
  # Gemini (Final Fallback)
@@ -48,9 +48,9 @@ try:
48
  import google.generativeai as genai
49
  genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
50
  gemini_model = genai.GenerativeModel('gemini-pro')
51
- print("βœ… Gemini AI initialized successfully")
52
  except Exception as e:
53
- print(f"⚠️ Error initializing Gemini: {e}")
54
  gemini_model = None
55
 
56
  # ---------- 2. Unified AI Function with Smart Fallback ----------
@@ -73,7 +73,7 @@ def ask_ai(prompt, temperature=0.7, max_retries=2):
73
  return completion.choices[0].message.content, "zai"
74
  except Exception as e:
75
  last_error = e
76
- print(f"⚠️ Z.ai attempt {attempt+1} failed: {str(e)}")
77
  if attempt < max_retries - 1:
78
  time.sleep(1)
79
 
@@ -89,7 +89,7 @@ def ask_ai(prompt, temperature=0.7, max_retries=2):
89
  return response.text, "cohere"
90
  except Exception as e:
91
  last_error = e
92
- print(f"⚠️ Cohere attempt {attempt+1} failed: {str(e)}")
93
  if attempt < max_retries - 1:
94
  time.sleep(1)
95
 
@@ -105,7 +105,7 @@ def ask_ai(prompt, temperature=0.7, max_retries=2):
105
  return completion.choices[0].message.content, "minimax"
106
  except Exception as e:
107
  last_error = e
108
- print(f"⚠️ MiniMax attempt {attempt+1} failed: {str(e)}")
109
  if attempt < max_retries - 1:
110
  time.sleep(1)
111
 
@@ -121,10 +121,10 @@ def ask_ai(prompt, temperature=0.7, max_retries=2):
121
  return response.text, "gemini"
122
  except Exception as e:
123
  last_error = e
124
- print(f"⚠️ Gemini fallback failed: {str(e)}")
125
 
126
  # All failed
127
- error_msg = f"⚠️ Error: All AI services failed. Last error: {str(last_error)}"
128
  return error_msg, "error"
129
 
130
  # ---------- 3. Global storage ----------
@@ -194,11 +194,11 @@ Use a friendly, supportive tone to help students learn effectively."""
194
 
195
  # Add source indicator if not from Z.ai
196
  if source == "cohere":
197
- bot_response = f"πŸ”΅ [Cohere] {bot_response}"
198
  elif source == "minimax":
199
- bot_response = f"🟣 [MiniMax] {bot_response}"
200
  elif source == "gemini":
201
- bot_response = f"🟒 [Gemini] {bot_response}"
202
  elif source == "error":
203
  pass # Error already formatted
204
 
@@ -304,15 +304,15 @@ Return JSON (no markdown):
304
  try:
305
  clean_txt = response.replace("```json", "").replace("```", "").strip()
306
  fb = json.loads(clean_txt)
307
- result = f"""βœ… Score: {fb['score']}%
308
 
309
- πŸ“ Detailed Feedback:
310
  {fb['feedback']}
311
 
312
- πŸ’ͺ Your Strengths:
313
  {fb.get('strengths', 'Good effort!')}
314
 
315
- 🎯 How to Improve:
316
  {fb['improvements']}"""
317
 
318
  if source in ["cohere", "minimax", "gemini"]:
@@ -325,12 +325,12 @@ Return JSON (no markdown):
325
  # ---------- 10. Admin – Past Papers ----------
326
  def verify_admin_password(password):
327
  if password == ADMIN_PASSWORD:
328
- return gr.update(visible=True), gr.update(visible=False), "βœ… Access granted!"
329
- return gr.update(visible=False), gr.update(visible=True), "❌ Incorrect password!"
330
 
331
  def upload_paper(title, subject, level, content, pdf_file):
332
  if not all([title, subject, level, content]):
333
- return "❌ Please fill all required fields!", get_papers_list()
334
 
335
  paper_id = len(papers_storage) + 1
336
 
@@ -339,7 +339,7 @@ def upload_paper(title, subject, level, content, pdf_file):
339
  pdf_text = extract_text_from_pdf(pdf_file)
340
  if pdf_text and not pdf_text.startswith("Error"):
341
  pdf_content_storage[paper_id] = pdf_text
342
- content += f"\n\n[πŸ“„ PDF extracted: {len(pdf_text)} characters]"
343
 
344
  papers_storage.append({
345
  "id": paper_id,
@@ -350,7 +350,7 @@ def upload_paper(title, subject, level, content, pdf_file):
350
  "has_pdf": bool(pdf_text and not pdf_text.startswith("Error")),
351
  "uploaded_at": datetime.now().strftime("%Y-%m-%d %H:%M")
352
  })
353
- return "βœ… Paper uploaded!", get_papers_list()
354
 
355
  def get_papers_list():
356
  if not papers_storage:
@@ -364,25 +364,24 @@ def view_papers_student(subject, level):
364
  filtered = [p for p in papers_storage
365
  if p["subject"] == subject.lower() and p["level"] == level]
366
  if not filtered:
367
- return f"πŸ“­ No {subject} {level} papers available."
368
  return "\n".join(
369
- f"**{p['title']}** {'πŸ“„ PDF' if p.get('has_pdf') else ''}\nπŸ“… {p['uploaded_at']}\n\n{p['content']}\n\n{'═'*60}"
370
  for p in filtered
371
  )
372
 
373
  # ---------- 11. Gradio UI ----------
374
  with gr.Blocks(theme=gr.themes.Soft(), title="IGCSE/GCSE Platform") as app:
375
  gr.Markdown("""
376
- # πŸŽ“ IGCSE/GCSE Language Learning Platform
377
- ### Multi-AI System: Z.ai (Primary) β†’ Cohere β†’ MiniMax β†’ Gemini
378
- 🌟 AI Tutor | πŸ”„ Translator | πŸ“– Dictionary | πŸ“š Past Papers
379
  """)
380
 
381
  with gr.Tabs():
382
  # ───── STUDENT ─────
383
- with gr.Tab("πŸ“š Student Portal"):
384
  with gr.Tabs():
385
- with gr.Tab("πŸ€– AI Tutor"):
386
  gr.Markdown("### Chat with Your AI Tutor\n*Powered by Z.ai with automatic fallback*")
387
  with gr.Row():
388
  subj = gr.Radio(["French", "EFL"], label="Subject", value="French")
@@ -396,26 +395,26 @@ with gr.Blocks(theme=gr.themes.Soft(), title="IGCSE/GCSE Platform") as app:
396
  chat = gr.Chatbot(height=450, show_label=False)
397
  txt = gr.Textbox(placeholder="Ask anything... e.g., 'Explain the passΓ© composΓ©'", label="Message")
398
  with gr.Row():
399
- send = gr.Button("Send πŸ“€", variant="primary")
400
- clr = gr.Button("Clear πŸ—‘οΈ")
401
  send.click(ai_tutor_chat, [txt, chat, subj, topc, lvl], chat)
402
  txt.submit(ai_tutor_chat, [txt, chat, subj, topc, lvl], chat)
403
  clr.click(clear_chat, outputs=chat)
404
 
405
- with gr.Tab("πŸ”„ Translator"):
406
  gr.Markdown("### English ⟷ French Translation")
407
  dir_ = gr.Radio(["English β†’ French", "French β†’ English"], label="Direction", value="English β†’ French")
408
  inp = gr.Textbox(lines=6, label="Input Text", placeholder="Enter text...")
409
  out = gr.Textbox(lines=6, label="Translation")
410
- gr.Button("Translate πŸ”„", variant="primary").click(translate_text, [inp, dir_], out)
411
 
412
- with gr.Tab("πŸ“– Dictionary"):
413
  gr.Markdown("### French Dictionary")
414
  w = gr.Textbox(placeholder="Enter French word...", label="Word")
415
  o = gr.Textbox(lines=16, label="Definition")
416
- gr.Button("Look Up πŸ”", variant="primary").click(dictionary_lookup, w, o)
417
 
418
- with gr.Tab("✍️ Practice"):
419
  gr.Markdown("### Generate & Practice Exam Questions")
420
  with gr.Row():
421
  ps = gr.Radio(["French", "EFL"], label="Subject", value="French")
@@ -423,34 +422,34 @@ with gr.Blocks(theme=gr.themes.Soft(), title="IGCSE/GCSE Platform") as app:
423
  pt = gr.Dropdown(french_topics, label="Topic")
424
  ps.change(upd_topics, ps, pt)
425
 
426
- q = gr.Textbox(label="πŸ“ Question", lines=5, interactive=False)
427
  exp = gr.Textbox(label="Expected", lines=2, visible=False)
428
- mark = gr.Textbox(label="πŸ“Š Mark Scheme", lines=3, interactive=False)
429
- ans = gr.Textbox(lines=8, label="✍️ Your Answer", placeholder="Type your answer...")
430
- fb = gr.Textbox(lines=12, label="πŸ“‹ Feedback", interactive=False)
431
 
432
  with gr.Row():
433
- gr.Button("🎲 Generate", variant="primary").click(generate_question, [ps, pt, pl], [q, exp, mark])
434
- gr.Button("βœ… Check", variant="secondary").click(check_answer, [q, exp, ans, ps, pl], fb)
435
 
436
- with gr.Tab("πŸ“„ Past Papers"):
437
  gr.Markdown("### Browse Past Papers")
438
  with gr.Row():
439
  psb = gr.Radio(["French", "EFL"], label="Subject", value="French")
440
  plb = gr.Radio(["IGCSE", "GCSE"], label="Level", value="IGCSE")
441
  pd = gr.Textbox(lines=22, label="Papers", interactive=False)
442
- gr.Button("πŸ“š Show", variant="primary").click(view_papers_student, [psb, plb], pd)
443
 
444
  # ───── ADMIN ─────
445
- with gr.Tab("πŸ” Admin Panel"):
446
  with gr.Column() as login_section:
447
- gr.Markdown("### πŸ”’ Admin Login")
448
  pwd = gr.Textbox(label="Password", type="password", placeholder="Enter password")
449
- login_btn = gr.Button("πŸ”“ Login", variant="primary")
450
  login_status = gr.Textbox(label="Status", interactive=False)
451
 
452
  with gr.Column(visible=False) as admin_section:
453
- gr.Markdown("### πŸ“€ Upload Past Papers")
454
  with gr.Row():
455
  with gr.Column():
456
  t = gr.Textbox(label="Title", placeholder="e.g., Paper 1 - June 2023")
@@ -458,8 +457,8 @@ with gr.Blocks(theme=gr.themes.Soft(), title="IGCSE/GCSE Platform") as app:
458
  s = gr.Radio(["French", "EFL"], label="Subject", value="French")
459
  lv = gr.Radio(["IGCSE", "GCSE"], label="Level", value="IGCSE")
460
  c = gr.Textbox(lines=6, label="Description")
461
- pdf = gr.File(label="πŸ“Ž PDF (optional)", file_types=[".pdf"])
462
- up = gr.Button("πŸ“€ Upload", variant="primary")
463
  st = gr.Textbox(label="Status")
464
  with gr.Column():
465
  lst = gr.Textbox(lines=24, label="All Papers", value=get_papers_list(), interactive=False)
@@ -467,33 +466,4 @@ with gr.Blocks(theme=gr.themes.Soft(), title="IGCSE/GCSE Platform") as app:
467
 
468
  login_btn.click(verify_admin_password, [pwd], [admin_section, login_section, login_status])
469
 
470
- gr.Markdown("""
471
- ---
472
- ### πŸš€ Multi-AI System Setup:
473
-
474
- **Required API Keys (add in Secrets):**
475
- 1. `HF_TOKEN` - Hugging Face token (for Z.ai & MiniMax)
476
- 2. `COHERE_API_KEY` - Cohere API key
477
- 3. `GEMINI_API_KEY` - Google Gemini API key
478
-
479
- **How It Works:**
480
- - πŸ”΅ **Z.ai GLM-4.6** tries first (best for education)
481
- - 🟠 **Cohere** kicks in if Z.ai fails
482
- - 🟣 **MiniMax** as third option
483
- - 🟒 **Gemini** as final fallback
484
-
485
- **Requirements:**
486
- ```
487
- gradio>=4.0.0
488
- PyPDF2>=3.0.0
489
- huggingface_hub>=0.19.0
490
- cohere>=4.0.0
491
- google-generativeai>=0.3.0
492
- ```
493
-
494
- **Admin Password:** `@mikaelJ46`
495
-
496
- *Reliable, multi-model AI system ensures 99.9% uptime!* πŸš€
497
- """)
498
-
499
  app.launch()
 
18
  provider="novita",
19
  api_key=os.environ.get("HF_TOKEN"),
20
  )
21
+ print(" Z.ai GLM-4.6 initialized successfully")
22
  except Exception as e:
23
+ print(f" Error initializing Z.ai: {e}")
24
  zai_client = None
25
 
26
  # Cohere (Secondary)
27
  try:
28
  import cohere
29
  cohere_client = cohere.Client(os.getenv("COHERE_API_KEY"))
30
+ print(" Cohere initialized successfully")
31
  except Exception as e:
32
+ print(f" Error initializing Cohere: {e}")
33
  cohere_client = None
34
 
35
  # MiniMax (Tertiary)
 
38
  provider="novita",
39
  api_key=os.environ.get("HF_TOKEN"),
40
  )
41
+ print(" MiniMax AI initialized successfully")
42
  except Exception as e:
43
+ print(f" Error initializing MiniMax: {e}")
44
  minimax_client = None
45
 
46
  # Gemini (Final Fallback)
 
48
  import google.generativeai as genai
49
  genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
50
  gemini_model = genai.GenerativeModel('gemini-pro')
51
+ print(" Gemini AI initialized successfully")
52
  except Exception as e:
53
+ print(f" Error initializing Gemini: {e}")
54
  gemini_model = None
55
 
56
  # ---------- 2. Unified AI Function with Smart Fallback ----------
 
73
  return completion.choices[0].message.content, "zai"
74
  except Exception as e:
75
  last_error = e
76
+ print(f" Z.ai attempt {attempt+1} failed: {str(e)}")
77
  if attempt < max_retries - 1:
78
  time.sleep(1)
79
 
 
89
  return response.text, "cohere"
90
  except Exception as e:
91
  last_error = e
92
+ print(f" Cohere attempt {attempt+1} failed: {str(e)}")
93
  if attempt < max_retries - 1:
94
  time.sleep(1)
95
 
 
105
  return completion.choices[0].message.content, "minimax"
106
  except Exception as e:
107
  last_error = e
108
+ print(f" MiniMax attempt {attempt+1} failed: {str(e)}")
109
  if attempt < max_retries - 1:
110
  time.sleep(1)
111
 
 
121
  return response.text, "gemini"
122
  except Exception as e:
123
  last_error = e
124
+ print(f" Gemini fallback failed: {str(e)}")
125
 
126
  # All failed
127
+ error_msg = f" Error: All AI services failed. Last error: {str(last_error)}"
128
  return error_msg, "error"
129
 
130
  # ---------- 3. Global storage ----------
 
194
 
195
  # Add source indicator if not from Z.ai
196
  if source == "cohere":
197
+ bot_response = f" {bot_response}"
198
  elif source == "minimax":
199
+ bot_response = f" {bot_response}"
200
  elif source == "gemini":
201
+ bot_response = f" {bot_response}"
202
  elif source == "error":
203
  pass # Error already formatted
204
 
 
304
  try:
305
  clean_txt = response.replace("```json", "").replace("```", "").strip()
306
  fb = json.loads(clean_txt)
307
+ result = f""" Score: {fb['score']}%
308
 
309
+ Detailed Feedback:
310
  {fb['feedback']}
311
 
312
+ Your Strengths:
313
  {fb.get('strengths', 'Good effort!')}
314
 
315
+ How to Improve:
316
  {fb['improvements']}"""
317
 
318
  if source in ["cohere", "minimax", "gemini"]:
 
325
  # ---------- 10. Admin – Past Papers ----------
326
  def verify_admin_password(password):
327
  if password == ADMIN_PASSWORD:
328
+ return gr.update(visible=True), gr.update(visible=False), " Access granted!"
329
+ return gr.update(visible=False), gr.update(visible=True), " Incorrect password!"
330
 
331
  def upload_paper(title, subject, level, content, pdf_file):
332
  if not all([title, subject, level, content]):
333
+ return " Please fill all required fields!", get_papers_list()
334
 
335
  paper_id = len(papers_storage) + 1
336
 
 
339
  pdf_text = extract_text_from_pdf(pdf_file)
340
  if pdf_text and not pdf_text.startswith("Error"):
341
  pdf_content_storage[paper_id] = pdf_text
342
+ content += f"\n\n[ PDF extracted: {len(pdf_text)} characters]"
343
 
344
  papers_storage.append({
345
  "id": paper_id,
 
350
  "has_pdf": bool(pdf_text and not pdf_text.startswith("Error")),
351
  "uploaded_at": datetime.now().strftime("%Y-%m-%d %H:%M")
352
  })
353
+ return " Paper uploaded!", get_papers_list()
354
 
355
  def get_papers_list():
356
  if not papers_storage:
 
364
  filtered = [p for p in papers_storage
365
  if p["subject"] == subject.lower() and p["level"] == level]
366
  if not filtered:
367
+ return f" No {subject} {level} papers available."
368
  return "\n".join(
369
+ f"**{p['title']}** {' PDF' if p.get('has_pdf') else ''}\n {p['uploaded_at']}\n\n{p['content']}\n\n{'═'*60}"
370
  for p in filtered
371
  )
372
 
373
  # ---------- 11. Gradio UI ----------
374
  with gr.Blocks(theme=gr.themes.Soft(), title="IGCSE/GCSE Platform") as app:
375
  gr.Markdown("""
376
+ # IGCSE/GCSE Language Learning Platform
377
+ AI Tutor | Translator | Dictionary | Past Papers
 
378
  """)
379
 
380
  with gr.Tabs():
381
  # ───── STUDENT ─────
382
+ with gr.Tab(" Student Portal"):
383
  with gr.Tabs():
384
+ with gr.Tab(" AI Tutor"):
385
  gr.Markdown("### Chat with Your AI Tutor\n*Powered by Z.ai with automatic fallback*")
386
  with gr.Row():
387
  subj = gr.Radio(["French", "EFL"], label="Subject", value="French")
 
395
  chat = gr.Chatbot(height=450, show_label=False)
396
  txt = gr.Textbox(placeholder="Ask anything... e.g., 'Explain the passΓ© composΓ©'", label="Message")
397
  with gr.Row():
398
+ send = gr.Button("Send ", variant="primary")
399
+ clr = gr.Button("Clear ")
400
  send.click(ai_tutor_chat, [txt, chat, subj, topc, lvl], chat)
401
  txt.submit(ai_tutor_chat, [txt, chat, subj, topc, lvl], chat)
402
  clr.click(clear_chat, outputs=chat)
403
 
404
+ with gr.Tab(" Translator"):
405
  gr.Markdown("### English ⟷ French Translation")
406
  dir_ = gr.Radio(["English β†’ French", "French β†’ English"], label="Direction", value="English β†’ French")
407
  inp = gr.Textbox(lines=6, label="Input Text", placeholder="Enter text...")
408
  out = gr.Textbox(lines=6, label="Translation")
409
+ gr.Button("Translate ", variant="primary").click(translate_text, [inp, dir_], out)
410
 
411
+ with gr.Tab(" Dictionary"):
412
  gr.Markdown("### French Dictionary")
413
  w = gr.Textbox(placeholder="Enter French word...", label="Word")
414
  o = gr.Textbox(lines=16, label="Definition")
415
+ gr.Button("Look Up ", variant="primary").click(dictionary_lookup, w, o)
416
 
417
+ with gr.Tab(" Practice"):
418
  gr.Markdown("### Generate & Practice Exam Questions")
419
  with gr.Row():
420
  ps = gr.Radio(["French", "EFL"], label="Subject", value="French")
 
422
  pt = gr.Dropdown(french_topics, label="Topic")
423
  ps.change(upd_topics, ps, pt)
424
 
425
+ q = gr.Textbox(label=" Question", lines=5, interactive=False)
426
  exp = gr.Textbox(label="Expected", lines=2, visible=False)
427
+ mark = gr.Textbox(label=" Mark Scheme", lines=3, interactive=False)
428
+ ans = gr.Textbox(lines=8, label=" Your Answer", placeholder="Type your answer...")
429
+ fb = gr.Textbox(lines=12, label=" Feedback", interactive=False)
430
 
431
  with gr.Row():
432
+ gr.Button(" Generate", variant="primary").click(generate_question, [ps, pt, pl], [q, exp, mark])
433
+ gr.Button(" Check", variant="secondary").click(check_answer, [q, exp, ans, ps, pl], fb)
434
 
435
+ with gr.Tab(" Past Papers"):
436
  gr.Markdown("### Browse Past Papers")
437
  with gr.Row():
438
  psb = gr.Radio(["French", "EFL"], label="Subject", value="French")
439
  plb = gr.Radio(["IGCSE", "GCSE"], label="Level", value="IGCSE")
440
  pd = gr.Textbox(lines=22, label="Papers", interactive=False)
441
+ gr.Button(" Show", variant="primary").click(view_papers_student, [psb, plb], pd)
442
 
443
  # ───── ADMIN ─────
444
+ with gr.Tab(" Admin Panel"):
445
  with gr.Column() as login_section:
446
+ gr.Markdown("### Admin Login")
447
  pwd = gr.Textbox(label="Password", type="password", placeholder="Enter password")
448
+ login_btn = gr.Button(" Login", variant="primary")
449
  login_status = gr.Textbox(label="Status", interactive=False)
450
 
451
  with gr.Column(visible=False) as admin_section:
452
+ gr.Markdown("### Upload Past Papers")
453
  with gr.Row():
454
  with gr.Column():
455
  t = gr.Textbox(label="Title", placeholder="e.g., Paper 1 - June 2023")
 
457
  s = gr.Radio(["French", "EFL"], label="Subject", value="French")
458
  lv = gr.Radio(["IGCSE", "GCSE"], label="Level", value="IGCSE")
459
  c = gr.Textbox(lines=6, label="Description")
460
+ pdf = gr.File(label=" PDF (optional)", file_types=[".pdf"])
461
+ up = gr.Button(" Upload", variant="primary")
462
  st = gr.Textbox(label="Status")
463
  with gr.Column():
464
  lst = gr.Textbox(lines=24, label="All Papers", value=get_papers_list(), interactive=False)
 
466
 
467
  login_btn.click(verify_admin_password, [pwd], [admin_section, login_section, login_status])
468
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  app.launch()