File size: 5,752 Bytes
25732fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Teaching Agent - Autonomous content generation and delivery
"""
import json
from .base_agent import BaseAgent
from llm_service import LLMService
from agent_knowledge.rules.teaching_rules import TeachingRuleEngine
from agent_communication.message_bus import AgentMessageBus
from agent_communication.protocols import MessageProtocols
from datetime import datetime
import random


class TeachingAgent(BaseAgent):
    """
    Autonomous agent responsible for:
    - Generating personalized lessons
    - Adapting teaching style
    - Selecting examples based on student performance
    """
    
    def __init__(self):
        super().__init__("TA-001", "TeachingAgent")
        self.llm_service = LLMService()
        self.rule_engine = TeachingRuleEngine()
        self.message_bus = AgentMessageBus()
        self.lessons_generated = 0
        self.knowledge_level = 0.0
        self.learning_style = "visual"
        self.lesson_complexity = "beginner"
        self.current_strategy = {}
        
    def perceive(self, student_state):
        self.update_state("perceiving")
        self.log(f"Perceiving student state for user {student_state.user_id}")
        
        # Update internal state based on student data
        self.user_id = student_state.user_id
        self.knowledge_level = student_state.knowledge_level
        self.learning_style = student_state.learning_style or "visual"
        
        # Determine lesson complexity based on knowledge level
        if self.knowledge_level < 0.3:
            self.lesson_complexity = "beginner"
        elif self.knowledge_level < 0.7:
            self.lesson_complexity = "intermediate"
        else:
            self.lesson_complexity = "advanced"
        
        self.update_state("perceived")
        return self.state
    
    def decide(self):
        self.update_state("deciding")
        
        # Use rule engine to determine strategy
        student_profile = {
            "knowledge_level": self.knowledge_level,
            "learning_style": self.learning_style,
            # Mock recent performance for now, ideally comes from KnowledgeAgent
            "recent_performance": 0.8 
        }
        
        self.current_strategy = self.rule_engine.select_teaching_strategy(student_profile)
        self.log(f"Selected teaching strategy: {self.current_strategy['name']}")
        
        self.update_state("decided")
        return self
    
    def act(self, topic, prompt=None):
        self.update_state("acting")
        self.log(f"Generating lesson for topic: {topic.name} with strategy {self.current_strategy['name']}")
        
        # 1. Request updated profile from KnowledgeAgent (Async/Simulated)
        self.message_bus.send_message(
            self.name, 
            "KnowledgeAgent", 
            MessageProtocols.KNOWLEDGE_REQUEST, 
            MessageProtocols.request_student_profile(self.user_id, topic.id)
        )

        try:
            # 2. Generate Lesson Structure using Rule Engine (No LLM)
            lesson_structure = self.rule_engine.generate_lesson_structure(topic, self.current_strategy)
            
            # 3. Fill in content (Hybrid: Try Templates first, else Fallback to LLM for specific sections)
            # For this MVP, we will use the structure to guide the LLM, reducing its "thinking" time
            # In a full impl, we would pull pre-written content from ContentLibrary
            
            structured_prompt = f"""
            Create a lesson for topic '{topic.name}' ({topic.difficulty}) following this structure:
            
            Strategy: {self.current_strategy['name']} ({self.current_strategy['description']})
            
            Sections:
            """
            
            for section in lesson_structure['sections']:
                structured_prompt += f"\n- {section['title']}: {section['instruction_for_llm']}"
            
            # Fallback to LLM for content generation but with strict structure
            lesson_content = self.llm_service.generate_lesson_with_prompt(
                topic.name,
                topic.difficulty,
                self.knowledge_level,
                custom_prompt=structured_prompt
            )
            
            self.lessons_generated += 1
            self.log(f"Lesson generated successfully using rule-guided structure. (Total: {self.lessons_generated})")
            
            # Store in agent memory
            self.memory.append({
                "action": "lesson_generated",
                "topic": topic.name,
                "strategy": self.current_strategy['name'],
                "complexity": self.lesson_complexity,
                "user_id": self.user_id
            })
            
            self.update_state("completed")
            
            return {
                "content": lesson_content,
                "metadata": {
                    "teaching_style": self.current_strategy.get('name', 'default'),
                    "complexity": self.lesson_complexity,
                    "example_count": self.current_strategy.get('example_count', 3),
                    "agent": self.name,
                    "generated_at": datetime.utcnow().isoformat()
                }
            }
            
        except Exception as e:
            self.log(f"Error generating lesson: {str(e)}", "error")
            self.update_state("error")
            return {"error": str(e)}
    
    def get_statistics(self):
        """Return agent statistics"""
        return {
            "agent": self.name,
            "lessons_generated": self.lessons_generated,
            "current_style": self.current_style,
            "state": self.state,
            "memory_size": len(self.memory)
        }