Turbiling's picture
Update app.py
dfdf429 verified
Raw
History Blame Contribute Delete
22.3 kB
import os
os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
os.environ["HF_HUB_OFFLINE"] = "1"
os.environ["GRADIO_TEMP_DIR"] = "/tmp"
import gradio as gr
from groq import Groq
from docx import Document
from docx.shared import Pt, RGBColor, Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
from datetime import datetime
import re
# Initialize Groq client
try:
client = Groq()
print("Groq client initialized successfully")
except Exception as e:
print(f"Warning: Groq client initialization failed: {e}")
client = None
# ---------------- TOKEN SAFE GENERATION ---------------- #
def safe_generate(messages, max_tokens=400):
"""
Controlled generation to avoid token overflow
"""
try:
response = client.chat.completions.create(
model="openai/gpt-oss-120b",
messages=messages,
temperature=0.7,
max_completion_tokens=max_tokens,
top_p=0.9
)
return response.choices[0].message.content.strip()
except Exception as e:
return f"Error: {str(e)}"
# ---------------- DATA ---------------- #
SUBJECTS_BY_GRADE = {
"Grade 1-5": ["English", "Urdu", "Mathematics", "General Science", "Islamiyat", "Pakistan Studies", "Computer"],
"Grade 6-8": ["English", "Urdu", "Mathematics", "General Science", "Islamiyat", "Pakistan Studies", "Computer"],
"Grade 9-10": ["English", "Urdu", "Mathematics", "Physics", "Chemistry", "Biology", "Islamiyat", "Pakistan Studies", "Computer Science"],
"Grade 11-12": ["English", "Urdu", "Mathematics", "Physics", "Chemistry", "Biology", "Islamiyat", "Pakistan Studies", "Computer Science", "Economics", "Statistics"]
}
DISTRICTS_GB = [
"Gilgit", "Ghizer", "Hunza", "Nagar", "Skardu", "Shigar",
"Kharmang", "Ghanche", "Astore", "Diamer", "Darel", "Tangir",
"Gupis Yasin", "Roundu"
]
TEACHING_METHODS = [
"Lecture Method", "Discussion Method", "Demonstration Method",
"Activity-Based Learning", "Inquiry-Based Learning", "Group Work",
"Project-Based Learning", "Problem-Based Learning", "Hands-on Activities",
"Visual Learning", "Interactive Learning", "Storytelling",
"Cooperative Learning", "Flipped Classroom", "Think-Pair-Share"
]
ASSESSMENT_TYPES = [
"Formative Assessment", "Summative Assessment", "Oral Questions",
"Written Test", "Practical Work", "Class Participation",
"Quiz", "Worksheet", "Group Presentation", "Individual Assignment",
"Peer Assessment", "Self Assessment", "Portfolio Assessment"
# ---------------- URDU TRANSLATIONS ---------------- #
URDU_TRANSLATIONS = {
"English": "انگریزی",
"Urdu": "اردو",
"Mathematics": "ریاضی",
"General Science": "عمومی سائنس",
"Islamiyat": "اسلامیات",
"Pakistan Studies": "پاکستان کی تاریخ و جغرافیہ",
"Computer": "کمپیوٹر",
"Physics": "طبیعیات",
"Chemistry": "کیمیا",
"Biology": "حیاتیات",
"Computer Science": "کمپیوٹر سائنس",
"Economics": "معاشیات",
"Statistics": "شماریات",
"Lecture Method": "لیکچر کا طریقہ",
"Discussion Method": "گفتگو کا طریقہ",
"Demonstration Method": "عملی مظاہرہ",
"Activity-Based Learning": "سرگرمی پر مبنی تعلیم",
"Inquiry-Based Learning": "تحقیقی تعلیم",
"Group Work": "اجتماعی کام",
"Project-Based Learning": "منصوبہ پر مبنی تعلیم",
"Problem-Based Learning": "مسئلہ حل کرنے کی تعلیم",
"Hands-on Activities": "عملی سرگرمیاں",
"Visual Learning": "بصری تعلیم",
"Interactive Learning": "تعاملی تعلیم",
"Storytelling": "کہانی سنانا",
"Cooperative Learning": "باہمی تعاون سے سیکھنا",
"Flipped Classroom": "تبدیل شدہ کلاس روم",
"Think-Pair-Share": "سوچیں، جوڑے بنائیں، شیئر کریں",
"Formative Assessment": "تشکیلی تشخیص",
"Summative Assessment": "اختتامی تشخیص",
"Oral Questions": "زبانی سوالات",
"Written Test": "تحریری امتحان",
"Practical Work": "عملی کام",
"Class Participation": "کلاسی شرکت",
"Quiz": "مختصر امتحان",
"Worksheet": "ورک شیٹ",
"Group Presentation": "اجتماعی پیشکش",
"Individual Assignment": "انفرادی تفویض",
"Peer Assessment": "ہم جماعت کی تشخیص",
"Self Assessment": "خود تشخیص",
"Portfolio Assessment": "پورٹ فولیو کی تشخیص",
"Grade 1": "جماعت اول",
"Grade 2": "جماعت دوم",
"Grade 3": "جماعت سوم",
"Grade 4": "جماعت چہارم",
"Grade 5": "جماعت پنجم",
"Grade 6": "جماعت ششم",
"Grade 7": "جماعت ہفتم",
"Grade 8": "جماعت ہشتم",
"Grade 9": "جماعت نہم",
"Grade 10": "جماعت دہم",
"Grade 11": "جماعت یازدہم",
"Grade 12": "جماعت دوازدہم",
"District": "ضلع",
"School": "تعلیمی ادارہ",
"Teacher": "استاد کا نام",
"Date": "تاریخ",
"Topic": "عنوانِ سبق",
"Duration": "دورانیہ",
"No. of Students": "طلبہ کی تعداد",
"Teaching Method": "تدریسی طریقہ",
"Assessment Type": "تشخیصی طریقہ",
"minutes": "منٹ"
}
# ---------------- HELPERS ---------------- #
def translate_to_urdu(text):
if not text:
return text
if text in URDU_TRANSLATIONS:
return URDU_TRANSLATIONS[text]
words = str(text).split()
return " ".join([URDU_TRANSLATIONS.get(w, w) for w in words])
def update_subjects(grade_range):
if not grade_range:
return gr.Dropdown(choices=[], value=None)
return gr.Dropdown(choices=SUBJECTS_BY_GRADE.get(grade_range, []), value=None)
def validate_inputs(language, grade_range, subject, topic, teacher_name, school_name):
errors = []
if not language:
errors.append("Language is required")
if not grade_range:
errors.append("Grade range is required")
if not subject:
errors.append("Subject is required")
if not topic or len(topic.strip()) < 3:
errors.append("Topic too short")
if not teacher_name:
errors.append("Teacher name required")
if not school_name:
errors.append("School name required")
return errors
# ---------------- DOCX UTILITIES ---------------- #
def add_table_border(table):
tbl = table._tbl
tblPr = tbl.tblPr
if tblPr is None:
tblPr = OxmlElement('w:tblPr')
tbl.insert(0, tblPr)
borders = OxmlElement('w:tblBorders')
for name in ['top', 'left', 'bottom', 'right', 'insideH', 'insideV']:
border = OxmlElement(f'w:{name}')
border.set(qn('w:val'), 'single')
border.set(qn('w:sz'), '4')
border.set(qn('w:color'), '000000')
borders.append(border)
tblPr.append(borders)
def apply_rtl_to_paragraph(para, alignment=WD_ALIGN_PARAGRAPH.RIGHT):
para.alignment = alignment
para.paragraph_format.right_to_left = True
pPr = para._element.get_or_add_pPr()
bidi = OxmlElement('w:bidi')
pPr.append(bidi)
def apply_rtl_to_run(run):
run.font.rtl = True
run.font.name = 'Arial'
def create_rtl_table_cell(cell, text, bold=False):
cell.text = ''
para = cell.paragraphs[0]
run = para.add_run(str(text))
run.font.size = Pt(11)
run.font.name = 'Arial'
run.font.rtl = True
if bold:
run.bold = True
apply_rtl_to_paragraph(para)
def generate_lesson_plan(language, grade_range, grade_specific, subject, topic,
school_name, teacher_name, district, date_input,
students, duration, teaching_method, assessment_type,
include_resources, include_differentiation):
# ---------- VALIDATION ----------
errors = validate_inputs(language, grade_range, subject, topic, teacher_name, school_name)
if errors:
return None, "\n".join(errors)
if client is None:
return None, "Groq API not initialized"
# ---------- DATE ----------
try:
formatted_date = datetime.strptime(date_input, "%Y-%m-%d").strftime("%Y-%m-%d")
except:
formatted_date = datetime.now().strftime("%Y-%m-%d")
# ---------- GRADE ----------
full_grade = grade_specific if grade_specific else grade_range.split('-')[0]
# ---------- URDU PREP ----------
if language == "Urdu":
full_grade_urdu = translate_to_urdu(full_grade)
subject_urdu = translate_to_urdu(subject)
district_urdu = translate_to_urdu(district)
teaching_method_urdu = translate_to_urdu(teaching_method)
assessment_type_urdu = translate_to_urdu(assessment_type)
topic_urdu = topic
# ============================================================
# 🔥 CHUNKED GENERATION STARTS HERE
# ============================================================
print(f"Generating {language} lesson plan (chunked mode)...")
# ---------- ENGLISH VERSION ----------
if language == "English":
# 1️⃣ SLOs
slos = safe_generate([
{"role": "system", "content": "Generate in English only"},
{"role": "user", "content": f"""
Write 3 SMART SLOs:
Grade: {full_grade}
Subject: {subject}
Topic: {topic}
Use:
1 Knowledge
2 Understanding
3 Application
"""}
], max_tokens=250)
# 2️⃣ CONTENT
content = safe_generate([
{"role": "system", "content": "Generate in English only"},
{"role": "user", "content": f"""
Write CONTENT KNOWLEDGE for:
{topic} (Grade {full_grade})
Include:
- Key concepts
- Definitions
- Examples (Pakistan context)
{"- Resources" if include_resources else ""}
{"- Differentiation" if include_differentiation else ""}
No teaching steps.
"""}
], max_tokens=600)
# 3️⃣ ASSIGNMENT
assignment = safe_generate([
{"role": "system", "content": "Generate in English only"},
{"role": "user", "content": f"""
Create HOME ASSIGNMENT:
Topic: {topic}
Grade: {full_grade}
3-5 questions.
"""}
], max_tokens=250)
lesson_text = f"""
SMART STUDENT LEARNING OUTCOMES
{slos}
CONTENT KNOWLEDGE
{content}
HOME ASSIGNMENT
{assignment}
"""
# ---------- URDU VERSION ----------
else:
slos = safe_generate([
{"role": "system", "content": "صرف اردو میں لکھیں"},
{"role": "user", "content": f"""
3 اسمارٹ نتائج لکھیں:
جماعت: {full_grade_urdu}
مضمون: {subject_urdu}
عنوان: {topic_urdu}
"""}
], max_tokens=250)
content = safe_generate([
{"role": "system", "content": "صرف اردو میں لکھیں"},
{"role": "user", "content": f"""
علمی مواد لکھیں:
{topic_urdu} (جماعت {full_grade_urdu})
شامل کریں:
- بنیادی تصورات
- تعریفات
- مثالیں
{"- وسائل" if include_resources else ""}
{"- مختلف طلبہ کے لیے حکمت عملی" if include_differentiation else ""}
"""}
], max_tokens=600)
assignment = safe_generate([
{"role": "system", "content": "صرف اردو میں لکھیں"},
{"role": "user", "content": f"""
گھر کا کام بنائیں:
{topic_urdu}
3-5 سوالات شامل کریں۔
"""}
], max_tokens=250)
lesson_text = f"""
اسمارٹ طلبہ سیکھنے کے نتائج
{slos}
علمی مواد
{content}
گھر کی تفویض
{assignment}
"""
# Clean extra noise
lesson_text = lesson_text.strip()
# ============================================================
# ✅ RETURN TEXT FOR DOC GENERATION (PART 4)
# ============================================================
return lesson_text, {
"formatted_date": formatted_date,
"full_grade": full_grade,
"topic": topic,
"subject": subject,
"district": district,
"students": students,
"duration": duration,
"teacher_name": teacher_name,
"school_name": school_name,
"teaching_method": teaching_method,
"assessment_type": assessment_type,
"language": language,
"topic_urdu": topic if language == "Urdu" else None
}
def build_docx(lesson_text, meta):
"""
DOCX builder using already generated safe text (NO API CALLS HERE)
"""
language = meta["language"]
topic = meta["topic"]
subject = meta["subject"]
district = meta["district"]
teacher_name = meta["teacher_name"]
school_name = meta["school_name"]
full_grade = meta["full_grade"]
students = meta["students"]
duration = meta["duration"]
teaching_method = meta["teaching_method"]
assessment_type = meta["assessment_type"]
formatted_date = meta["formatted_date"]
doc = Document()
# ============================================================
# ===================== ENGLISH DOC ==========================
# ============================================================
if language == "English":
section = doc.sections[0]
section.top_margin = Inches(0.75)
section.bottom_margin = Inches(0.75)
section.left_margin = Inches(0.75)
section.right_margin = Inches(0.75)
# Header
header = doc.add_paragraph()
run = header.add_run("Government of Gilgit-Baltistan\nSchool Education Department")
run.bold = True
run.font.size = Pt(13)
header.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Title
title = doc.add_paragraph()
run = title.add_run("SMART LESSON PLAN")
run.bold = True
run.font.size = Pt(14)
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
doc.add_paragraph()
# Table
table = doc.add_table(rows=6, cols=4)
add_table_border(table)
def cell(r, c, text, bold=False):
cell = table.rows[r].cells[c]
cell.text = str(text)
if bold:
for p in cell.paragraphs:
for run in p.runs:
run.bold = True
cell(0, 0, "Grade", True)
cell(0, 1, full_grade)
cell(0, 2, "Subject", True)
cell(0, 3, subject)
cell(1, 0, "Topic", True)
cell(1, 1, topic)
cell(1, 2, "Duration", True)
cell(1, 3, f"{duration} min")
cell(2, 0, "Teacher", True)
cell(2, 1, teacher_name)
cell(2, 2, "Date", True)
cell(2, 3, formatted_date)
cell(3, 0, "School", True)
cell(3, 1, school_name)
cell(3, 2, "District", True)
cell(3, 3, district)
cell(4, 0, "Students", True)
cell(4, 1, students)
cell(4, 2, "Method", True)
cell(4, 3, teaching_method)
cell(5, 0, "Assessment", True)
table.rows[5].cells[1].merge(table.rows[5].cells[3])
cell(5, 1, assessment_type)
doc.add_paragraph()
# Content sections (SAFE TEXT ONLY)
for line in lesson_text.split("\n"):
if line.strip():
para = doc.add_paragraph(line.strip())
para.alignment = WD_ALIGN_PARAGRAPH.LEFT
file_path = f"/tmp/LP_{subject}_{topic[:20]}_{formatted_date}.docx"
doc.save(file_path)
return file_path, "English Lesson Plan Generated Successfully"
# ============================================================
# ======================= URDU DOC ===========================
# ============================================================
else:
section = doc.sections[0]
section.top_margin = Inches(0.75)
section.bottom_margin = Inches(0.75)
section.left_margin = Inches(0.75)
section.right_margin = Inches(1)
# Header
header = doc.add_paragraph()
run = header.add_run("حکومتِ گلگت بلتستان\nمحکمہ تعلیم")
run.bold = True
run.font.size = Pt(13)
apply_rtl_to_paragraph(header)
# Title
title = doc.add_paragraph()
run = title.add_run("اسمارٹ سبق کا منصوبہ")
run.bold = True
run.font.size = Pt(14)
apply_rtl_to_paragraph(title)
doc.add_paragraph()
# Table (simplified safe version)
table = doc.add_table(rows=6, cols=4)
add_table_border(table)
def urdu_cell(r, c, text, bold=False):
cell = table.rows[r].cells[c]
cell.text = str(text)
para = cell.paragraphs[0]
apply_rtl_to_paragraph(para)
urdu_cell(0, 0, translate_to_urdu(subject))
urdu_cell(0, 1, translate_to_urdu("Subject"), True)
urdu_cell(0, 2, translate_to_urdu(full_grade))
urdu_cell(0, 3, translate_to_urdu("Grade"), True)
urdu_cell(1, 0, topic)
urdu_cell(1, 1, translate_to_urdu("Topic"), True)
urdu_cell(1, 2, f"{duration} {translate_to_urdu('minutes')}")
urdu_cell(1, 3, translate_to_urdu("Duration"), True)
urdu_cell(2, 0, teacher_name)
urdu_cell(2, 1, translate_to_urdu("Teacher"), True)
urdu_cell(2, 2, formatted_date)
urdu_cell(2, 3, translate_to_urdu("Date"), True)
urdu_cell(3, 0, district)
urdu_cell(3, 1, translate_to_urdu("District"), True)
urdu_cell(3, 2, school_name)
urdu_cell(3, 3, translate_to_urdu("School"), True)
urdu_cell(4, 0, students)
urdu_cell(4, 1, translate_to_urdu("Students"), True)
urdu_cell(4, 2, teaching_method)
urdu_cell(4, 3, translate_to_urdu("Method"), True)
urdu_cell(5, 0, assessment_type)
table.rows[5].cells[0].merge(table.rows[5].cells[3])
doc.add_paragraph()
# Content (SAFE TEXT ONLY)
for line in lesson_text.split("\n"):
if line.strip():
para = doc.add_paragraph(line.strip())
apply_rtl_to_paragraph(para)
file_path = f"/tmp/LP_Urdu_{topic[:20]}_{formatted_date}.docx"
doc.save(file_path)
return file_path, "اردو سبق کا منصوبہ تیار ہو گیا"
# ============================================================
# ================= GRADIO INTERFACE =========================
# ============================================================
custom_css = """
.gradio-container {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
}
.main-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 2rem;
border-radius: 10px;
color: white;
margin-bottom: 2rem;
}
.section-header {
background-color: #f8f9fa;
padding: 1rem;
border-left: 4px solid #667eea;
margin: 1.5rem 0 1rem 0;
border-radius: 5px;
}
"""
with gr.Blocks(theme=gr.themes.Soft(), css=custom_css,
title="SMART Lesson Plan Generator") as demo:
gr.HTML("""
<div class="main-header">
<h1 style="margin:0;">SMART Lesson Plan Generator</h1>
<p>AI Powered Lesson Planning System (Pakistan Curriculum)</p>
</div>
""")
# ---------------- INPUTS ---------------- #
language = gr.Dropdown(["English", "Urdu"], value="English", label="Language")
grade_range = gr.Dropdown(
["Grade 1-5", "Grade 6-8", "Grade 9-10", "Grade 11-12"],
label="Grade Range"
)
grade_specific = gr.Dropdown(
[f"Grade {i}" for i in range(1, 13)],
label="Specific Grade (Optional)"
)
subject = gr.Dropdown([], label="Subject")
topic = gr.Textbox(label="Topic")
school_name = gr.Textbox(label="School Name")
teacher_name = gr.Textbox(label="Teacher Name")
district = gr.Dropdown(DISTRICTS_GB, label="District")
date_input = gr.Textbox(label="Date", value=datetime.now().strftime("%Y-%m-%d"))
students = gr.Number(label="Students", value=30)
duration = gr.Number(label="Duration (minutes)", value=40)
teaching_method = gr.Dropdown(TEACHING_METHODS, label="Teaching Method")
assessment_type = gr.Dropdown(ASSESSMENT_TYPES, label="Assessment Type")
include_resources = gr.Checkbox(label="Include Resources", value=True)
include_differentiation = gr.Checkbox(label="Include Differentiation", value=True)
# ---------------- OUTPUT ---------------- #
file_output = gr.File(label="Download Lesson Plan")
status_output = gr.Textbox(label="Status")
# ============================================================
# ===================== EVENT PIPELINE =======================
# ============================================================
def pipeline(*inputs):
"""
FULL FIXED PIPELINE:
1. Generate chunked lesson text
2. Build DOCX
"""
lesson_text, meta = generate_lesson_plan(*inputs)
file_path, status = build_docx(lesson_text, meta)
return file_path, status
# Grade → Subject update
grade_range.change(update_subjects, grade_range, subject)
# Generate button
gr.Button("Generate Lesson Plan", variant="primary").click(
pipeline,
inputs=[
language,
grade_range,
grade_specific,
subject,
topic,
school_name,
teacher_name,
district,
date_input,
students,
duration,
teaching_method,
assessment_type,
include_resources,
include_differentiation
],
outputs=[file_output, status_output]
)
# ============================================================
# ===================== LAUNCH APP ============================
# ============================================================
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True,
allowed_paths=["/tmp"]
)