mikaelJ46 commited on
Commit
b305764
·
verified ·
1 Parent(s): 5021c06

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +247 -56
app.py CHANGED
@@ -350,34 +350,108 @@ Include all questions, preserve exact numbering, identify topics clearly."""
350
  # ============================================================================
351
 
352
  def generate_lesson_notes(subject, topic, detail_level="comprehensive"):
353
- """Generate comprehensive teaching notes"""
354
 
355
- prompt = f"""Generate {detail_level} teaching notes for IGCSE {subject} - Topic: {topic}
356
 
357
- Structure:
358
- 1. LEARNING OBJECTIVES (3-5 clear objectives)
359
- 2. KEY CONCEPTS (with explanations)
360
- 3. DETAILED CONTENT
361
- - Introduction
362
- - Main points with explanations
363
- - Examples
364
- - Common misconceptions
365
- 4. TEACHING TIPS
366
- 5. STUDENT ACTIVITIES (3-5 activities)
367
- 6. ASSESSMENT IDEAS
368
- 7. HOMEWORK SUGGESTIONS
369
- 8. RESOURCES NEEDED
370
- 9. DIFFERENTIATION STRATEGIES
371
 
372
- Make it practical, clear, and ready to use in class."""
 
 
373
 
374
- response, source = ask_ai(prompt, temperature=0.6)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
 
376
  if source != "gemini":
377
  response = f"[Generated using {source.title()}]\n\n{response}"
378
 
379
  return response
380
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  # ============================================================================
382
  # ASSESSMENT GENERATOR
383
  # ============================================================================
@@ -419,11 +493,11 @@ Mix question types (knowledge, application, analysis). Include mark schemes."""
419
  return []
420
 
421
  # ============================================================================
422
- # EXAM PAPER GENERATOR
423
  # ============================================================================
424
 
425
- def generate_exam_paper(selected_questions, exam_title, include_answers=True):
426
- """Generate professional exam paper PDF"""
427
 
428
  buffer = BytesIO()
429
  doc = SimpleDocTemplate(buffer, pagesize=A4, topMargin=72, bottomMargin=36)
@@ -451,13 +525,15 @@ def generate_exam_paper(selected_questions, exam_title, include_answers=True):
451
 
452
  # Title
453
  story.append(Paragraph(exam_title, title_style))
 
454
  story.append(Spacer(1, 12))
455
 
456
  # Instructions
457
  instructions = Paragraph(
458
- "<b>Instructions:</b><br/>"
459
  "• Answer all questions<br/>"
460
- "• Show all working<br/>"
 
461
  f"• Total marks: {sum(q.get('marks', 0) for q in selected_questions)}<br/>"
462
  f"• Time allowed: {len(selected_questions) * 2} minutes",
463
  styles['Normal']
@@ -469,18 +545,54 @@ def generate_exam_paper(selected_questions, exam_title, include_answers=True):
469
  for i, q in enumerate(selected_questions, 1):
470
  q_text = f"<b>{i}. {q.get('question_text', '')}</b> [{q.get('marks', 0)} marks]"
471
  story.append(Paragraph(q_text, question_style))
472
- story.append(Spacer(1, 36)) # Space for answer
 
 
 
 
 
 
 
 
 
 
 
 
473
 
474
- # Answer section if requested
475
- if include_answers:
476
- story.append(PageBreak())
477
- story.append(Paragraph("MARK SCHEME", title_style))
478
- story.append(Spacer(1, 24))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
 
480
- for i, q in enumerate(selected_questions, 1):
481
- answer_text = f"<b>{i}. </b>{q.get('model_answer', q.get('mark_scheme', 'Answer not available'))}"
482
- story.append(Paragraph(answer_text, styles['Normal']))
483
- story.append(Spacer(1, 12))
 
 
 
 
 
 
 
484
 
485
  doc.build(story)
486
  buffer.seek(0)
@@ -682,38 +794,117 @@ with gr.Blocks(
682
  # ============================================================
683
  with gr.Tab("Lesson Notes"):
684
  gr.Markdown("### Generate Comprehensive Teaching Notes")
 
685
 
686
  with gr.Row():
687
- notes_subject = gr.Dropdown(
688
- choices=list(IGCSE_SUBJECTS.keys()),
689
- label="Subject",
690
- value="Mathematics (0580)"
691
- )
692
- notes_topic = gr.Dropdown(
693
- choices=IGCSE_SUBJECTS["Mathematics (0580)"]["topics"],
694
- label="Topic"
695
- )
696
-
697
- def update_topics(subject):
698
- topics = IGCSE_SUBJECTS[subject]["topics"]
699
- return gr.Dropdown(choices=topics, value=topics[0] if topics else None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
700
 
701
- notes_subject.change(update_topics, notes_subject, notes_topic)
 
702
 
703
- notes_detail = gr.Radio(
704
- choices=["concise", "comprehensive", "detailed"],
705
- label="Detail Level",
706
- value="comprehensive"
707
- )
708
 
709
- generate_notes_btn = gr.Button("Generate Lesson Notes", variant="primary")
710
- notes_output = gr.Markdown(value="Select topic and click generate")
 
 
 
 
 
 
 
 
 
711
 
712
  generate_notes_btn.click(
713
- generate_lesson_notes,
714
  [notes_subject, notes_topic, notes_detail],
715
- notes_output
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
716
  )
 
 
 
 
 
 
 
 
717
 
718
  # ============================================================
719
  # TAB 4: ASSESSMENT GENERATOR
 
350
  # ============================================================================
351
 
352
  def generate_lesson_notes(subject, topic, detail_level="comprehensive"):
353
+ """Generate comprehensive teaching notes - content focused"""
354
 
355
+ prompt = f"""Generate {detail_level} IGCSE {subject} teaching notes for: {topic}
356
 
357
+ Provide complete, ready-to-teach content:
 
 
 
 
 
 
 
 
 
 
 
 
 
358
 
359
+ 1. KEY CONCEPTS & DEFINITIONS
360
+ - All essential terms with clear explanations
361
+ - Core principles and laws
362
 
363
+ 2. DETAILED CONTENT
364
+ - Comprehensive explanation of all subtopics
365
+ - Step-by-step breakdowns where applicable
366
+ - Important formulas, equations, or processes
367
+ - Worked examples with solutions
368
+
369
+ 3. IMPORTANT POINTS TO EMPHASIZE
370
+ - Critical information students must know
371
+ - Common misconceptions to address
372
+ - Exam-relevant points
373
+
374
+ 4. PRACTICE PROBLEMS/QUESTIONS
375
+ - 5-8 questions with full solutions
376
+ - Range of difficulty levels
377
+
378
+ 5. QUICK REFERENCE SUMMARY
379
+ - Bullet points of key takeaways
380
+ - Memory aids or mnemonics
381
+
382
+ Focus on CONTENT and KNOWLEDGE - provide the actual information to teach, not meta-instructions about teaching."""
383
+
384
+ response, source = ask_ai(prompt, temperature=0.5)
385
 
386
  if source != "gemini":
387
  response = f"[Generated using {source.title()}]\n\n{response}"
388
 
389
  return response
390
 
391
+ def generate_notes_pdf(notes_content, subject, topic):
392
+ """Generate PDF from lesson notes"""
393
+ buffer = BytesIO()
394
+ doc = SimpleDocTemplate(buffer, pagesize=A4, topMargin=72, bottomMargin=72)
395
+ story = []
396
+ styles = getSampleStyleSheet()
397
+
398
+ # Custom styles
399
+ title_style = ParagraphStyle(
400
+ 'CustomTitle',
401
+ parent=styles['Heading1'],
402
+ fontSize=18,
403
+ textColor=colors.HexColor('#1a237e'),
404
+ spaceAfter=20,
405
+ alignment=TA_CENTER,
406
+ fontName='Helvetica-Bold'
407
+ )
408
+
409
+ heading_style = ParagraphStyle(
410
+ 'CustomHeading',
411
+ parent=styles['Heading2'],
412
+ fontSize=14,
413
+ textColor=colors.HexColor('#283593'),
414
+ spaceAfter=12,
415
+ spaceBefore=12,
416
+ fontName='Helvetica-Bold'
417
+ )
418
+
419
+ # Title
420
+ story.append(Paragraph(f"IGCSE {subject}", title_style))
421
+ story.append(Paragraph(f"Topic: {topic}", styles['Heading2']))
422
+ story.append(Spacer(1, 20))
423
+
424
+ # Content - parse markdown-style formatting
425
+ lines = notes_content.split('\n')
426
+ for line in lines:
427
+ line = line.strip()
428
+ if not line:
429
+ story.append(Spacer(1, 6))
430
+ continue
431
+
432
+ # Handle headings
433
+ if line.startswith('###'):
434
+ story.append(Paragraph(line.replace('###', '').strip(), heading_style))
435
+ elif line.startswith('##'):
436
+ story.append(Paragraph(line.replace('##', '').strip(), title_style))
437
+ elif line.startswith('#'):
438
+ story.append(Paragraph(line.replace('#', '').strip(), title_style))
439
+ # Handle bold
440
+ elif line.startswith('**') or '**' in line:
441
+ line = line.replace('**', '<b>').replace('**', '</b>')
442
+ story.append(Paragraph(line, styles['Normal']))
443
+ # Handle lists
444
+ elif line.startswith('-') or line.startswith('•'):
445
+ line = line.lstrip('-•').strip()
446
+ story.append(Paragraph(f" • {line}", styles['Normal']))
447
+ # Regular text
448
+ else:
449
+ story.append(Paragraph(line, styles['Normal']))
450
+
451
+ doc.build(story)
452
+ buffer.seek(0)
453
+ return buffer
454
+
455
  # ============================================================================
456
  # ASSESSMENT GENERATOR
457
  # ============================================================================
 
493
  return []
494
 
495
  # ============================================================================
496
+ # EXAM PAPER GENERATOR - SEPARATE QUESTION AND MARK SCHEME PDFs
497
  # ============================================================================
498
 
499
+ def generate_question_paper_pdf(selected_questions, exam_title):
500
+ """Generate question paper PDF (no answers)"""
501
 
502
  buffer = BytesIO()
503
  doc = SimpleDocTemplate(buffer, pagesize=A4, topMargin=72, bottomMargin=36)
 
525
 
526
  # Title
527
  story.append(Paragraph(exam_title, title_style))
528
+ story.append(Paragraph("QUESTION PAPER", styles['Heading2']))
529
  story.append(Spacer(1, 12))
530
 
531
  # Instructions
532
  instructions = Paragraph(
533
+ "<b>Instructions to Candidates:</b><br/>"
534
  "• Answer all questions<br/>"
535
+ "• Show all working clearly<br/>"
536
+ "• Write your answers in the spaces provided<br/>"
537
  f"• Total marks: {sum(q.get('marks', 0) for q in selected_questions)}<br/>"
538
  f"• Time allowed: {len(selected_questions) * 2} minutes",
539
  styles['Normal']
 
545
  for i, q in enumerate(selected_questions, 1):
546
  q_text = f"<b>{i}. {q.get('question_text', '')}</b> [{q.get('marks', 0)} marks]"
547
  story.append(Paragraph(q_text, question_style))
548
+ story.append(Spacer(1, 48)) # Space for answer
549
+
550
+ doc.build(story)
551
+ buffer.seek(0)
552
+ return buffer
553
+
554
+ def generate_marking_scheme_pdf(selected_questions, exam_title):
555
+ """Generate marking scheme PDF (separate)"""
556
+
557
+ buffer = BytesIO()
558
+ doc = SimpleDocTemplate(buffer, pagesize=A4, topMargin=72, bottomMargin=36)
559
+ story = []
560
+ styles = getSampleStyleSheet()
561
 
562
+ # Custom styles
563
+ title_style = ParagraphStyle(
564
+ 'CustomTitle',
565
+ parent=styles['Heading1'],
566
+ fontSize=16,
567
+ textColor=colors.HexColor('#1a237e'),
568
+ spaceAfter=30,
569
+ alignment=TA_CENTER,
570
+ fontName='Helvetica-Bold'
571
+ )
572
+
573
+ # Title
574
+ story.append(Paragraph(exam_title, title_style))
575
+ story.append(Paragraph("MARKING SCHEME", styles['Heading2']))
576
+ story.append(Spacer(1, 24))
577
+
578
+ # Mark scheme
579
+ for i, q in enumerate(selected_questions, 1):
580
+ # Question number and marks
581
+ q_header = f"<b>Question {i}</b> [{q.get('marks', 0)} marks]"
582
+ story.append(Paragraph(q_header, styles['Heading3']))
583
+ story.append(Spacer(1, 6))
584
 
585
+ # Mark scheme
586
+ mark_scheme = q.get('mark_scheme', 'Mark scheme not available')
587
+ story.append(Paragraph(f"<b>Mark Scheme:</b>", styles['Normal']))
588
+ story.append(Paragraph(mark_scheme, styles['Normal']))
589
+ story.append(Spacer(1, 8))
590
+
591
+ # Model answer
592
+ model_answer = q.get('model_answer', 'Model answer not available')
593
+ story.append(Paragraph(f"<b>Model Answer:</b>", styles['Normal']))
594
+ story.append(Paragraph(model_answer, styles['Normal']))
595
+ story.append(Spacer(1, 20))
596
 
597
  doc.build(story)
598
  buffer.seek(0)
 
794
  # ============================================================
795
  with gr.Tab("Lesson Notes"):
796
  gr.Markdown("### Generate Comprehensive Teaching Notes")
797
+ gr.Markdown("*AI provides complete content and knowledge - ready to teach*")
798
 
799
  with gr.Row():
800
+ with gr.Column(scale=2):
801
+ with gr.Row():
802
+ notes_subject = gr.Dropdown(
803
+ choices=list(IGCSE_SUBJECTS.keys()),
804
+ label="Subject",
805
+ value="Mathematics (0580)"
806
+ )
807
+ notes_topic = gr.Dropdown(
808
+ choices=IGCSE_SUBJECTS["Mathematics (0580)"]["topics"],
809
+ label="Topic"
810
+ )
811
+
812
+ def update_topics(subject):
813
+ topics = IGCSE_SUBJECTS[subject]["topics"]
814
+ return gr.Dropdown(choices=topics, value=topics[0] if topics else None)
815
+
816
+ notes_subject.change(update_topics, notes_subject, notes_topic)
817
+
818
+ notes_detail = gr.Radio(
819
+ choices=["concise", "comprehensive", "detailed"],
820
+ label="Detail Level",
821
+ value="comprehensive"
822
+ )
823
+
824
+ with gr.Row():
825
+ generate_notes_btn = gr.Button("Generate Lesson Notes", variant="primary")
826
+ download_notes_btn = gr.Button("Download as PDF", variant="secondary")
827
+
828
+ notes_pdf_output = gr.File(label="Download Notes PDF")
829
+
830
+ with gr.Column(scale=3):
831
+ notes_output = gr.Markdown(value="Select topic and click generate")
832
 
833
+ # Store generated notes
834
+ generated_notes = gr.State("")
835
 
836
+ def generate_and_store(subject, topic, detail):
837
+ notes = generate_lesson_notes(subject, topic, detail)
838
+ return notes, notes
 
 
839
 
840
+ def create_notes_pdf(notes, subject, topic):
841
+ if not notes:
842
+ return None
843
+ pdf_buffer = generate_notes_pdf(notes, subject, topic)
844
+
845
+ # Save to temporary file
846
+ import tempfile
847
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.pdf')
848
+ temp_file.write(pdf_buffer.read())
849
+ temp_file.close()
850
+ return temp_file.name
851
 
852
  generate_notes_btn.click(
853
+ generate_and_store,
854
  [notes_subject, notes_topic, notes_detail],
855
+ [notes_output, generated_notes]
856
+ )
857
+
858
+ download_notes_btn.click(
859
+ create_notes_pdf,
860
+ [generated_notes, notes_subject, notes_topic],
861
+ notes_pdf_output
862
+ )
863
+
864
+ gr.Markdown("---")
865
+ gr.Markdown("### Ask for Clarification")
866
+ gr.Markdown("*Have questions about the content? Ask the AI for clarification*")
867
+
868
+ clarification_chat = gr.Chatbot(height=300, label="Clarification Chat")
869
+ clarification_input = gr.Textbox(
870
+ placeholder="Ask for clarification on any part of the notes...",
871
+ label="Your Question"
872
+ )
873
+
874
+ with gr.Row():
875
+ clarify_btn = gr.Button("Ask", variant="primary")
876
+ clear_chat_btn = gr.Button("Clear Chat")
877
+
878
+ def handle_clarification(question, history, subject, topic, notes):
879
+ if not question.strip():
880
+ return history
881
+
882
+ context = f"""You are helping a teacher understand IGCSE {subject} content on {topic}.
883
+
884
+ Current notes context:
885
+ {notes[:1000]}...
886
+
887
+ Teacher's question: {question}
888
+
889
+ Provide a clear, direct answer focused on the content and concepts. Be specific and helpful."""
890
+
891
+ response, _ = ask_ai(context, temperature=0.6)
892
+ history.append((question, response))
893
+ return history
894
+
895
+ clarify_btn.click(
896
+ handle_clarification,
897
+ [clarification_input, clarification_chat, notes_subject, notes_topic, generated_notes],
898
+ clarification_chat
899
  )
900
+
901
+ clarification_input.submit(
902
+ handle_clarification,
903
+ [clarification_input, clarification_chat, notes_subject, notes_topic, generated_notes],
904
+ clarification_chat
905
+ )
906
+
907
+ clear_chat_btn.click(lambda: [], outputs=clarification_chat)
908
 
909
  # ============================================================
910
  # TAB 4: ASSESSMENT GENERATOR