dhanvanth183 commited on
Commit
560c197
·
verified ·
1 Parent(s): 75e0119

Upload llms_handler.py

Browse files

Improved llm handler with individual llms for duration evaluation, structure, activity selection and lesson plan generation

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