Spaces:
Sleeping
Sleeping
File size: 22,558 Bytes
560c197 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
import os
import json
from openai import OpenAI
from typing import Dict, List, Any, Optional
from dotenv import load_dotenv
class LLMHandler:
def __init__(self):
"""Initialize the LLM handler with OpenAI client."""
load_dotenv()
self.client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))
self.model = "gpt-4o-mini"
def input_extraction_validation(self, user_prompt: str) -> Dict[str, Any]:
"""
Extract and validate key information from user prompt.
Returns a dictionary with extracted information and duration adequacy assessment.
"""
system_prompt = """
You are an expert in language education, specializing in extracting key information from lesson requests.
Your task is to identify and validate crucial parameters for language lesson planning.
"""
user_message = f"""
Extract key information from the following request for a lesson plan:
User Request: {user_prompt}
Extract the following information:
- topic: The main subject of the lesson
- age_group: Target age group (e.g., Elementary (6-11), High School (14-18), Adult)
- proficiency_level: Language proficiency according to CEFR (e.g., A1, A2, B1, B2, C1, C2)
- lesson_duration: Length of the lesson in minutes
- tech_requirements: Any technology needed for the lesson
- output_language: Language in which materials should be produced
- number_of_students: Number of students in the class
- skills_to_focus: Skills to emphasize (e.g., reading, writing, listening, speaking)
Then, evaluate whether the provided duration is sufficient for a structured lesson plan (PPP, ESA, TTT, TBL, or UbD) based on:
- The complexity of the topic
- The proficiency level of the learners
If duration is insufficient: set "duration_adequacy" to "Not sufficient for structured lesson plan"
If duration is sufficient: set "duration_adequacy" to "Sufficient for structured lesson plan"
Return ONLY a JSON object with these fields. No explanations or other text.
"""
try:
response = self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
response_format={"type": "json_object"}
)
# Try to parse the response as JSON
extracted_info = json.loads(response.choices[0].message.content)
# Validate essential fields and set defaults if missing
if not extracted_info.get("topic"):
extracted_info["topic"] = "No context provided"
if not extracted_info.get("lesson_duration"):
extracted_info["lesson_duration"] = "30 minutes"
if not extracted_info.get("proficiency_level"):
extracted_info["proficiency_level"] = "Intermediate [B1, B2]"
if not extracted_info.get("age_group"):
extracted_info["age_group"] = "Elementary (6-11)"
if not extracted_info.get("tech_requirements"):
extracted_info["tech_requirements"] = ["White Board", "Internet Access"]
if not extracted_info.get("output_language"):
extracted_info["output_language"] = "English"
if not extracted_info.get("number_of_students"):
extracted_info["number_of_students"] = "No context provided"
if not extracted_info.get("skills_to_focus"):
extracted_info["skills_to_focus"] = "No context provided"
if not extracted_info.get("duration_adequacy"):
# Fallback if model doesn't assess duration
extracted_info["duration_adequacy"] = "Sufficient for structured lesson plan"
return extracted_info
except Exception as e:
print(f"Error in input_extraction_validation: {str(e)}")
# Return default values
return {
"topic": "General language practice",
"age_group": "Elementary (6-11)",
"proficiency_level": "Intermediate [B1, B2]",
"lesson_duration": "30 minutes",
"tech_requirements": ["White Board", "Internet Access"],
"output_language": "English",
"number_of_students": "No context provided",
"skills_to_focus": "No context provided",
"duration_adequacy": "Sufficient for structured lesson plan"
}
def lesson_plan_structure(self, input_data: Dict[str, Any]) -> Dict[str, str]:
"""
Determine the appropriate lesson plan structure based on the extracted information.
Returns a dictionary with the selected structure and description.
"""
system_prompt = """
You are an expert educator specializing in language lesson planning frameworks.
Your task is to select the most appropriate lesson structure based on given parameters.
"""
user_message = f"""
Based on the following information about a language lesson, determine the most appropriate lesson plan structure:
Topic: {input_data.get('topic', 'No context provided')}
Age Group: {input_data.get('age_group', 'No context provided')}
Proficiency Level: {input_data.get('proficiency_level', 'No context provided')}
Lesson Duration: {input_data.get('lesson_duration', 'No context provided')}
Duration Adequacy: {input_data.get('duration_adequacy', 'No context provided')}
Skills to Focus: {input_data.get('skills_to_focus', 'No context provided')}
If Duration Adequacy is "Not sufficient for structured lesson plan":
- Set output_structure to "Generic"
- Set description to "The given duration is not sufficient to create a fully structured lesson plan. Instead, a simplified activity plan has been provided."
Otherwise, select the most appropriate structure from:
- PPP (Presentation, Practice, Production) - For young learners, basic comprehension, structured activities
- ESA (Engage, Study, Activate) - For young learners needing flexibility (consider Boomerang ESA or Patchwork ESA variants)
- TBL (Task-Based Learning) - For high school, advanced learners, or adults focusing on real-world applications
- TTT (Test, Teach, Test) - For learners with prior knowledge to assess gaps, instruct, and reassess
- UbD (Understanding by Design) - For long-term, curriculum-based instruction
Return your response as a JSON object with these two fields:
- output_structure: The selected structure (PPP, ESA, TBL, TTT, UbD, or Generic)
- description: A brief explanation of why this framework structure was chosen
"""
try:
response = self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
response_format={"type": "json_object"}
)
structure_info = json.loads(response.choices[0].message.content)
# Validate required fields
if not structure_info.get("output_structure"):
structure_info["output_structure"] = "Generic"
if not structure_info.get("description"):
structure_info[
"description"] = "A simplified lesson plan structure was selected based on the available information."
return structure_info
except Exception as e:
print(f"Error in lesson_plan_structure: {str(e)}")
# Fallback if the response is not valid JSON
return {
"output_structure": "Generic",
"description": "A simplified lesson plan structure was selected as a fallback."
}
def activity_template_selection(self, input_data: Dict[str, Any], structure_info: Dict[str, str]) -> Dict[
str, List[str]]:
"""
Select appropriate activity/worksheet templates based on lesson structure, topic, and duration.
Returns a dictionary with a list of selected activity templates.
"""
system_prompt = """
You are an expert language instructor specializing in selecting appropriate activities for lessons.
Your task is to choose the most suitable activity templates based on lesson parameters.
"""
user_message = f"""
Select the top 5 most suitable worksheet and activity templates for a language lesson with the following characteristics:
Lesson Structure: {structure_info.get('output_structure', 'Generic')}
Topic: {input_data.get('topic', 'No context provided')}
Duration: {input_data.get('lesson_duration', '30 minutes')}
Age Group: {input_data.get('age_group', 'Elementary (6-11)')}
Proficiency Level: {input_data.get('proficiency_level', 'Intermediate [B1, B2]')}
Skills to Focus: {input_data.get('skills_to_focus', 'No context provided')}
Choose ONLY from these activity templates:
1. Fill in the blank
2. Picture/Visual
3. Sentence Formation
4. Finding
5. Matching
6. Short Response
7. Long Response
8. Correction
9. Audio as material [suitable for activities to focus on listening tasks]
Selection Guidelines:
Prioritize activities that match the Skills to Focus, proficiency level, lesson structure, topic.
For beginner learners (A1, A2), emphasize simple activities like Matching, Picture/Visual, and Fill in the Blank.
For intermediate/advanced learners (B1, B2), incorporate Finding, Short Response, and Long Response.
Ensure a balance of engagement and difficulty.
Return your selection as a JSON object with this field:
- activity_templates: An array containing 5 selected activity templates from the list above
"""
try:
response = self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
response_format={"type": "json_object"}
)
templates_info = json.loads(response.choices[0].message.content)
# Validate the response contains activity_templates
if not templates_info.get("activity_templates"):
templates_info["activity_templates"] = [
"Fill in the blank",
"Picture/Visual",
"Matching",
"Short Response",
"Correction"
]
# Ensure we have exactly 5 templates
if len(templates_info["activity_templates"]) < 5:
# Add default templates to reach 5
default_templates = [
"Fill in the blank",
"Picture/Visual",
"Matching",
"Short Response",
"Correction"
]
for template in default_templates:
if template not in templates_info["activity_templates"] and len(
templates_info["activity_templates"]) < 5:
templates_info["activity_templates"].append(template)
if len(templates_info["activity_templates"]) > 5:
templates_info["activity_templates"] = templates_info["activity_templates"][:5]
return templates_info
except Exception as e:
print(f"Error in activity_template_selection: {str(e)}")
# Fallback if the response is not valid JSON
return {
"activity_templates": [
"Fill in the blank",
"Picture/Visual",
"Matching",
"Short Response",
"Correction"
]
}
def lesson_plan_generation(
self,
input_data: Dict[str, Any],
structure_info: Dict[str, str],
activity_info: Dict[str, List[str]]
) -> Dict[str, Any]:
"""
Generate a complete lesson plan based on all previous inputs.
Returns a structured JSON lesson plan.
"""
lesson_structure = structure_info.get("output_structure", "Generic")
structure_description = structure_info.get("description", "")
activity_templates = activity_info.get("activity_templates", [])
system_prompt = """
You are an expert language instructor with extensive experience in creating detailed lesson plans.
Your task is to generate a comprehensive, well-structured lesson plan based on provided parameters.
These are the details about the activity templates we are considering:
Fill in the Blanks: This activity assesses students’ ability to apply knowledge learned during the lesson.
Example: Complete the sentences using the correct verb forms.
Picture/Visual: This activity tests students' ability to interpret basic pictorial information, such as icons of fruits, animals, and everyday objects.
Example: Identify and write the names of the fruits and vegetables shown in the images.
Sentence Formation: This activity helps students practice sentence construction using minimal context.
Example: Given the words "your brother, height," form a question: "How tall is your brother?"
Finding: This activity strengthens vocabulary and comprehension by requiring students to identify words based on definitions or clues.
Example: What is the term for a woman on her wedding day? Answer: Bride
Matching: This activity reinforces the relationship between different concepts by having students pair related elements.
Example: Match the illnesses in one column with their appropriate treatments in another.
Short Response: This activity helps students practice forming concise answers to questions.
Example: "Which do you prefer—tea or coffee?" Answer: I prefer coffee over tea.
Long Response: This activity encourages students to construct detailed responses or dialogues.
Example: Write a conversation between you and a friend who has just passed an exam.
Correction: This activity develops students’ ability to identify and correct grammatical or structural errors in sentences.
Example: Identify and correct the mistakes in the given sentences.
Audio: This activity aids students to develop their listening skills.
Example: Listen to the audio of customer speaking to a tech support agent and answer to the below questions.
"""
if lesson_structure == "Generic":
user_message = f"""
Generate a Basic Activity Plan for a language lesson with the following details:
Topic: {input_data.get('topic', 'No context provided')}
Age Group: {input_data.get('age_group', 'Elementary (6-11)')}
Proficiency Level: {input_data.get('proficiency_level', 'Intermediate [B1, B2]')}
Lesson Duration: {input_data.get('lesson_duration', '30 minutes')}
Tech Requirements: {input_data.get('tech_requirements', ['White Board', 'Internet Access'])}
Output Language: {input_data.get('output_language', 'English')}
Number of Students: {input_data.get('number_of_students', 'No context provided')}
Skills to Focus: {input_data.get('skills_to_focus', 'No context provided')}
The plan should focus on selecting 2 or 3 meaningful activity due to time constraints. Include a note stating:
"The given duration is not sufficient to create a fully structured lesson plan. Instead, a simplified activity plan has been provided."
Include only activities that match these templates: {', '.join(activity_templates)}.
You must include the following sections in your JSON response:
- lesson_plan_title
- structure (which should be "Generic")
- structure_explanation (explanation that this is a simplified plan due to time constraints)
- objectives
- learning_outcomes
- materials_and_resources (*Avoid external platforms like Kahoot, Quizlet*)
- activity_plan (with timing, e.g., "Activity [X min]") and detail description explaining the activity and its objective.
- assessment_strategy
Provide your complete response in JSON format.
"""
else:
user_message = f"""
Generate a structured lesson plan using the {lesson_structure} framework for a language lesson with the following details:
Topic: {input_data.get('topic', 'No context provided')}
Age Group: {input_data.get('age_group', 'Elementary (6-11)')}
Proficiency Level: {input_data.get('proficiency_level', 'Intermediate [B1, B2]')}
Lesson Duration: {input_data.get('lesson_duration', '30 minutes')}
Tech Requirements: {input_data.get('tech_requirements', ['White Board', 'Internet Access'])}
Output Language: {input_data.get('output_language', 'English')}
Number of Students: {input_data.get('number_of_students', 'No context provided')}
Skills to Focus: {input_data.get('skills_to_focus', 'No context provided')}
Framework Structure: {lesson_structure}
Framework Explanation: {structure_description}
Include only activities that match these templates: {', '.join(activity_templates)}
You must include the following sections in your JSON response:
- lesson_plan_title
- structure (which should be "{lesson_structure}")
- structure_explanation (brief explanation of why this framework was chosen)
- objectives
- learning_outcomes
- essential_questions (if using UbD)
- materials_and_resources (avoid external platforms like Kahoot, Quizlet)
- lesson_plan_structure - with all appropriate sections for {lesson_structure} framework, each containing:
* key_parts (with time allocations, e.g., "Engage [20 minutes]")
* objective (purpose of this section)
* activityies (with timing, e.g., "Activity [X min]") and detail description explaining the activity and its objective.
- assessment_strategies
- additional_details
Provide your complete response in JSON format.
For time allocations, use brackets format (e.g., "Reflection [5 min]").
Ensure all activities have detailed descriptions.
"""
try:
response = self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
response_format={"type": "json_object"}
)
lesson_plan = json.loads(response.choices[0].message.content)
# Basic validation of the lesson plan
required_fields = ["lesson_plan_title", "structure", "objectives", "learning_outcomes"]
for field in required_fields:
if field not in lesson_plan:
if field == "lesson_plan_title":
lesson_plan[field] = f"Language Lesson: {input_data.get('topic', 'General Practice')}"
elif field == "structure":
lesson_plan[field] = lesson_structure
elif field == "objectives":
lesson_plan[field] = ["Improve language skills"]
elif field == "learning_outcomes":
lesson_plan[field] = ["Students will be able to communicate more effectively"]
return lesson_plan
except Exception as e:
print(f"Error in lesson_plan_generation: {str(e)}")
# Create a minimal fallback lesson plan
return {
"lesson_plan_title": f"Language Lesson: {input_data.get('topic', 'General Practice')}",
"structure": lesson_structure,
"structure_explanation": structure_description or "Basic language practice structure",
"objectives": ["Improve language skills"],
"learning_outcomes": ["Students will be able to communicate more effectively"],
"materials_and_resources": ["Whiteboard", "Handouts"],
"lesson_plan_structure": {
"main_activity": {
"key_parts": "Main Activity [30 minutes]",
"objective": "Practice language skills",
"activities": "Complete worksheet activities"
}
},
"assessment_strategies": ["Informal assessment through observation"],
"note": "This is a fallback lesson plan due to processing limitations."
}
|