Spaces:
No application file
No application file
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,24 +1,3 @@
|
|
| 1 |
-
import os
|
| 2 |
-
import gradio as gr
|
| 3 |
-
from groq import Groq
|
| 4 |
-
from datetime import datetime
|
| 5 |
-
from docx import Document
|
| 6 |
-
from docx.shared import Pt
|
| 7 |
-
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
| 8 |
-
import re
|
| 9 |
-
import random
|
| 10 |
-
|
| 11 |
-
# Initialize GROQ client
|
| 12 |
-
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
| 13 |
-
client = Groq(api_key=GROQ_API_KEY)
|
| 14 |
-
|
| 15 |
-
grades = [f"Grade {i}" for i in range(1, 13)]
|
| 16 |
-
difficulty_levels = ["Pretest (Beginner)", "Intermediate", "Advanced"]
|
| 17 |
-
min_mcq, max_mcq = 5, 50
|
| 18 |
-
|
| 19 |
-
# -------------------
|
| 20 |
-
# Subjects and chapters by grade (1-12)
|
| 21 |
-
# -------------------
|
| 22 |
chapters_by_subject_and_grade = {
|
| 23 |
"Grade 1": {
|
| 24 |
"Mathematics": ["Counting & Number Recognition", "Basic Addition", "Basic Subtraction", "Shapes & Space", "Measurement (Length, Weight)"],
|
|
@@ -34,116 +13,67 @@ chapters_by_subject_and_grade = {
|
|
| 34 |
"Islamiyat": ["Stories of Prophets", "Good Deeds", "Worship Basics"],
|
| 35 |
"General Knowledge": ["Local Community", "Transportation & Safety", "Plants & Animals"]
|
| 36 |
},
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
"Grade
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
}
|
| 49 |
-
|
| 50 |
-
def generate_mcqs(grade, subject, chapter, difficulty, num_questions):
|
| 51 |
-
system_msg = "You are an educational expert. Generate MCQs strictly aligned with the Pakistani National Curriculum."
|
| 52 |
-
user_msg = f"Create {num_questions} MCQs for {grade} {subject} on the chapter '{chapter}' at '{difficulty}' level. Each question must have 4 options. Provide answer key separately. Do not include any introductory text before MCQ 1."
|
| 53 |
-
|
| 54 |
-
response = client.chat.completions.create(
|
| 55 |
-
messages=[
|
| 56 |
-
{"role": "system", "content": system_msg},
|
| 57 |
-
{"role": "user", "content": user_msg}
|
| 58 |
-
],
|
| 59 |
-
model="llama-3.3-70b-versatile"
|
| 60 |
-
)
|
| 61 |
-
|
| 62 |
-
text = response.choices[0].message.content
|
| 63 |
-
mcqs = re.split(r'\n?\d+\.', text)
|
| 64 |
-
mcqs = [q.strip() for q in mcqs if q.strip()]
|
| 65 |
-
answer_key = [random.choice(["A","B","C","D"]) for _ in mcqs]
|
| 66 |
-
|
| 67 |
-
return mcqs[:num_questions], answer_key[:num_questions]
|
| 68 |
-
|
| 69 |
-
def export_to_word(mcqs, answers, grade, subject, chapter, difficulty, num_questions):
|
| 70 |
-
doc = Document()
|
| 71 |
-
|
| 72 |
-
# Main heading
|
| 73 |
-
heading = doc.add_paragraph("MONTHLY/ WEEKLY TEST")
|
| 74 |
-
heading.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
| 75 |
-
run = heading.runs[0]
|
| 76 |
-
run.bold = True
|
| 77 |
-
run.font.size = Pt(16)
|
| 78 |
-
|
| 79 |
-
# Table at top
|
| 80 |
-
table = doc.add_table(rows=6, cols=2)
|
| 81 |
-
table.style = 'Table Grid'
|
| 82 |
-
info = [
|
| 83 |
-
("Grade", grade),
|
| 84 |
-
("Subject", subject),
|
| 85 |
-
("Chapter", chapter),
|
| 86 |
-
("Difficulty", difficulty),
|
| 87 |
-
("Number of Questions", str(num_questions)),
|
| 88 |
-
("Date", datetime.now().strftime("%d-%m-%Y"))
|
| 89 |
-
]
|
| 90 |
-
for row, (label, value) in zip(table.rows, info):
|
| 91 |
-
row.cells[0].text = label
|
| 92 |
-
row.cells[1].text = value
|
| 93 |
-
row.cells[0].paragraphs[0].runs[0].bold = True
|
| 94 |
-
|
| 95 |
-
# MCQs start directly
|
| 96 |
-
for i, q in enumerate(mcqs, start=1):
|
| 97 |
-
doc.add_paragraph(f"{i}. {q}")
|
| 98 |
-
|
| 99 |
-
# Answer Key Table only
|
| 100 |
-
doc.add_paragraph("\nAnswer Key:")
|
| 101 |
-
ans_table = doc.add_table(rows=num_questions+1, cols=5)
|
| 102 |
-
ans_table.style = 'Table Grid'
|
| 103 |
-
headers = ["Q#", "A", "B", "C", "D"]
|
| 104 |
-
for idx, text in enumerate(headers):
|
| 105 |
-
ans_table.cell(0, idx).text = text
|
| 106 |
-
ans_table.cell(0, idx).paragraphs[0].runs[0].bold = True
|
| 107 |
-
|
| 108 |
-
for r, ans in enumerate(answers, start=1):
|
| 109 |
-
ans_table.cell(r, 0).text = str(r)
|
| 110 |
-
for c, option in enumerate(["A","B","C","D"], start=1):
|
| 111 |
-
ans_table.cell(r, c).text = "✔" if ans==option else ""
|
| 112 |
-
|
| 113 |
-
file_path = f"{grade}_{subject}_{chapter}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.docx"
|
| 114 |
-
doc.save(file_path)
|
| 115 |
-
return file_path
|
| 116 |
-
|
| 117 |
-
def on_generate(grade, subject, chapter, difficulty, num_questions):
|
| 118 |
-
mcqs, answers = generate_mcqs(grade, subject, chapter, difficulty, num_questions)
|
| 119 |
-
file_path = export_to_word(mcqs, answers, grade, subject, chapter, difficulty, num_questions)
|
| 120 |
-
return f"Test ready: {file_path}", file_path
|
| 121 |
-
|
| 122 |
-
# Gradio UI
|
| 123 |
-
with gr.Blocks() as demo:
|
| 124 |
-
gr.Markdown("### **MCQ Test Generator - Developer: Najaf Ali Sharqi**")
|
| 125 |
-
with gr.Row():
|
| 126 |
-
grade_dropdown = gr.Dropdown(choices=grades, label="Select Grade")
|
| 127 |
-
subject_dropdown = gr.Dropdown(choices=[], label="Select Subject")
|
| 128 |
-
chapter_dropdown = gr.Dropdown(choices=[], label="Select Chapter")
|
| 129 |
-
with gr.Row():
|
| 130 |
-
difficulty_dropdown = gr.Dropdown(choices=difficulty_levels, label="Select Difficulty")
|
| 131 |
-
num_mcq_slider = gr.Slider(minimum=min_mcq, maximum=max_mcq, value=20, step=1, label="Number of MCQs")
|
| 132 |
-
generate_btn = gr.Button("Generate Test")
|
| 133 |
-
output_text = gr.Textbox(label="Status")
|
| 134 |
-
output_file = gr.File(label="Download Test")
|
| 135 |
-
|
| 136 |
-
# Fix dropdown population
|
| 137 |
-
def update_subjects(grade):
|
| 138 |
-
return gr.update(choices=list(chapters_by_subject_and_grade.get(grade, {}).keys()), value=None)
|
| 139 |
-
|
| 140 |
-
def update_chapters(subject, grade):
|
| 141 |
-
return gr.update(choices=chapters_by_subject_and_grade.get(grade, {}).get(subject, []), value=None)
|
| 142 |
-
|
| 143 |
-
grade_dropdown.change(update_subjects, grade_dropdown, subject_dropdown)
|
| 144 |
-
subject_dropdown.change(update_chapters, [subject_dropdown, grade_dropdown], chapter_dropdown)
|
| 145 |
-
|
| 146 |
-
generate_btn.click(on_generate, inputs=[grade_dropdown, subject_dropdown, chapter_dropdown, difficulty_dropdown, num_mcq_slider], outputs=[output_text, output_file])
|
| 147 |
-
|
| 148 |
-
demo.launch()
|
| 149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
chapters_by_subject_and_grade = {
|
| 2 |
"Grade 1": {
|
| 3 |
"Mathematics": ["Counting & Number Recognition", "Basic Addition", "Basic Subtraction", "Shapes & Space", "Measurement (Length, Weight)"],
|
|
|
|
| 13 |
"Islamiyat": ["Stories of Prophets", "Good Deeds", "Worship Basics"],
|
| 14 |
"General Knowledge": ["Local Community", "Transportation & Safety", "Plants & Animals"]
|
| 15 |
},
|
| 16 |
+
"Grade 3": {
|
| 17 |
+
"Mathematics": ["Multiplication & Division", "Fractions (intro)", "Geometry Basics", "Measurement", "Patterns"],
|
| 18 |
+
"English": ["Tenses (simple)", "Comprehension Passages", "Vocabulary Development", "Sentence Writing"],
|
| 19 |
+
"Urdu": ["قواعد كا تعارف", "کہیں کہانیاں", "مختصر مضامین"],
|
| 20 |
+
"Science": ["Plants & Animals", "Human Body (basic)", "Materials & Uses"],
|
| 21 |
+
"Islamiyat": ["Seerat Stories & Morals", "Basic Akhlaq"]
|
| 22 |
+
},
|
| 23 |
+
"Grade 4": {
|
| 24 |
+
"Mathematics": ["Fractions & Decimals (intro)", "Geometry (angles, shapes)", "Data & Graphs", "Word Problems"],
|
| 25 |
+
"English": ["Grammar (parts of speech)", "Paragraph Writing", "Comprehension", "Listening & Speaking"],
|
| 26 |
+
"Urdu": ["نظم و نثر کا مطالعہ", "قواعد"],
|
| 27 |
+
"Science": ["Ecosystems", "Forces & Simple Machines", "Heat & Energy"],
|
| 28 |
+
"Islamiyat": ["Pillars of Islam", "Seerah Highlights"],
|
| 29 |
+
"Social Studies": ["Local Geography", "Community & Careers", "Citizenship"]
|
| 30 |
+
},
|
| 31 |
+
"Grade 5": {
|
| 32 |
+
"Mathematics": ["Number Operations", "Percentage & Ratio (intro)", "Geometry & Area", "Statistics (intro)"],
|
| 33 |
+
"English": ["Advanced Comprehension", "Essay & Letter Writing", "Grammar Consolidation"],
|
| 34 |
+
"Urdu": ["ادبی مطالعہ اور تحریر", "قواعد"],
|
| 35 |
+
"Science": ["Cells (intro)", "Matter & its Properties", "Energy & Sound"],
|
| 36 |
+
"Islamiyat": ["Quranic Stories & Morals"],
|
| 37 |
+
"Social Studies": ["History (local & national)", "Map Skills", "Basic Economics"]
|
| 38 |
+
},
|
| 39 |
+
"Grade 6": {
|
| 40 |
+
"Mathematics": ["Number System & Factors", "Algebraic Expressions (intro)", "Geometry Basics", "Data Handling"],
|
| 41 |
+
"English": ["Grammar & Usage", "Comprehension", "Writing Paragraphs", "Poetry & Prose"],
|
| 42 |
+
"Urdu": ["نثر و نظم", "قواعد ِاردو", "تحریر"],
|
| 43 |
+
"Science": ["Atoms & Molecules (intro)", "Human Body Systems", "Plants & Ecology"],
|
| 44 |
+
"Islamiyat": ["Seerah & Ahkam (intro)"],
|
| 45 |
+
"Social Studies": ["Physical Geography", "Early Civilizations", "Citizenship"]
|
| 46 |
+
},
|
| 47 |
+
"Grade 7": {
|
| 48 |
+
"Mathematics": ["Algebra (linear)", "Geometry (polygons, areas)", "Mensuration", "Graphs"],
|
| 49 |
+
"English": ["Advanced Grammar", "Comprehension Passages", "Composition"],
|
| 50 |
+
"Urdu": ["ادبی اور تنقیدی مطالعہ", "قواعد"],
|
| 51 |
+
"Science": ["Cell Biology", "Electricity & Magnetism (basic)", "Properties of Matter"],
|
| 52 |
+
"Islamiyat": ["Islamic History & Ethics"],
|
| 53 |
+
"Social Studies": ["Regional Geography", "Historical Events & Movements"],
|
| 54 |
+
"Computer": ["ICT Basics", "Introductory Coding Concepts"]
|
| 55 |
+
},
|
| 56 |
+
"Grade 8": {
|
| 57 |
+
"Mathematics": ["Linear Equations & Inequalities", "Coordinate Geometry", "Pythagoras & Trigonometry (intro)", "Probability"],
|
| 58 |
+
"English": ["Critical Reading", "Extended Writing", "Grammar Review"],
|
| 59 |
+
"Urdu": ["ادبی تنقید", "تحریر"],
|
| 60 |
+
"Science": ["Forces & Motion", "Heat & Temperature", "Waves & Optics (intro)"],
|
| 61 |
+
"Islamiyat": ["Fiqh Basics & Seerah"],
|
| 62 |
+
"Social Studies": ["Civics & Government", "Economic Concepts"],
|
| 63 |
+
"Computer": ["Algorithms & Flowcharts", "Application Software"]
|
| 64 |
+
},
|
| 65 |
+
"Grade 9": {
|
| 66 |
+
"Mathematics": ["Number Systems & Algebra", "Coordinate Geometry", "Trigonometry", "Graphs"],
|
| 67 |
+
"English": ["Advanced Grammar", "Comprehension", "Writing Skills"],
|
| 68 |
+
"Urdu": ["ادب اور نثر", "نظم", "مضامین"],
|
| 69 |
+
"Biology": ["INTRODUCTION TO BIOLOGY", "SOLVING A BIOLOGICAL PROBLEM", "BIODIVERSITY", "CELLS AND TISSUES", "CELL CYCLE", "ENZYMES", "BIOENERGETICS", "NUTRITION", "TRANSPORT"],
|
| 70 |
+
"Chemistry": ["FUNDAMENTALS OF CHEMISTRY", "STRUCTURE OF ATOMS", "PERIODIC TABLE AND PERIODICITY OF PROPERTIES", "STRUCTURE OF MOLECULES", "PHYSICAL STATES OF MATTER", "SOLUTIONS", "ELECTROCHEMISTRY", "CHEMICAL REACTIVITY"],
|
| 71 |
+
"Physics": ["PHYSICAL QUANTITIES AND MEASUREMENT", "KINEMATICS", "DYNAMICS", "TURNING EFFECT OF FORCES", "GRAVITATION", "WORK AND ENERGY", "PROPERTIES OF MATTER", "THERMAL PROPERTIES OF MATTER", "TRANSFER OF HEAT"],
|
| 72 |
+
"Islamiyat": ["Seerat of Prophet", "Faith & Beliefs", "Worship Practices"],
|
| 73 |
+
"Pakistan Studies": ["IDEOLOGICAL BASIS OF PAKISTAN", "MAKING OF PAKISTAN", "LAND AND ENVIRONMENT", "HISTORY OF PAKISTAN"],
|
| 74 |
+
"Computer": ["Fundamentals of Computing", "ICT Applications"]
|
| 75 |
+
},
|
| 76 |
+
"Grade 10": { ... }, # Add full dictionary like Grade 9
|
| 77 |
+
"Grade 11": { ... }, # Full dictionary with subjects and chapters
|
| 78 |
+
"Grade 12": { ... } # Full dictionary with subjects and chapters
|
| 79 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|