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."
            }