""" Teaching Agent for autonomous learning Handles teaching and learning path creation """ from typing import List, Dict, Any, Optional from datetime import datetime import json from .base_agent import BaseAgent from .research_agent import ResearchAgent class TeachingAgent(BaseAgent): """ Specialized agent for teaching and learning path creation """ def __init__(self, api_key: Optional[str] = None): super().__init__(api_key) self.learning_paths = [] self.teaching_style = "adaptive" self.current_lesson = None def execute_task(self, task: Dict[str, Any]) -> Dict[str, Any]: """ Execute a teaching task Args: task: Task description and parameters Returns: Teaching results """ task_type = task.get("type", "create_path") if task_type == "create_path": return self.create_learning_path(task) elif task_type == "adapt_path": return self.adapt_learning_path(task) elif task_type == "generate_lesson": return self.generate_lesson(task) else: return { "success": False, "message": f"Unknown task type: {task_type}" } def create_learning_path(self, task: Dict[str, Any]) -> Dict[str, Any]: """ Create a personalized learning path Args: task: Learning path creation parameters Returns: Created learning path """ topic = task.get("topic") expertise_level = task.get("expertise_level", "beginner") learning_style = task.get("learning_style", "visual") time_commitment = task.get("time_commitment", "moderate") if not topic: return { "success": False, "message": "Topic is required for learning path creation" } # Get relevant research research_result = { "success": True, "findings": ["Sample research finding 1", "Sample research finding 2"] } # Temporarily disabled actual research to fix circular import # research_agent = ResearchAgent(self.api_key) # research_result = research_agent.conduct_research({ # "topic": topic, # "depth": "deep" # }) # # if not research_result["success"]: # return research_result # Create teaching prompt prompt = f""" Create a personalized learning path for: {topic} User preferences: - Expertise level: {expertise_level} - Learning style: {learning_style} - Time commitment: {time_commitment} Research findings: {json.dumps(research_result["findings"])} Create a structured learning path with: 1. Learning objectives 2. Milestones 3. Resources 4. Assessment points 5. Adaptation points """ # Generate learning path path = json.loads(self.model_orchestrator.generate_structured_response( prompt=prompt, output_schema=""" { "title": "string", "description": "string", "objectives": ["string"], "milestones": [ { "title": "string", "description": "string", "resources": ["string"], "assessment": "string", "adaptation_points": ["string"] } ], "total_duration": "string", "prerequisites": ["string"] } """ )) # Store learning path self.learning_paths.append({ "path": path, "created_at": datetime.now().isoformat(), "topic": topic, "expertise_level": expertise_level }) # Add to memory self.add_to_memory(f"Created learning path for {topic}: {json.dumps(path)}") return { "success": True, "learning_path": path, "message": f"Successfully created learning path for {topic}" } def adapt_learning_path(self, task: Dict[str, Any]) -> Dict[str, Any]: """ Adapt an existing learning path based on user progress Args: task: Adaptation parameters Returns: Adapted learning path """ path_id = task.get("path_id") user_progress = task.get("user_progress") feedback = task.get("feedback", []) if not path_id or not user_progress: return { "success": False, "message": "Path ID and user progress are required for adaptation" } # Find the learning path path = None for p in self.learning_paths: if p.get("id") == path_id: path = p["path"] break if not path: return { "success": False, "message": f"Learning path with ID {path_id} not found" } # Prepare feedback string feedback_str = '\n'.join(feedback) if feedback else 'No feedback provided' # Create adaptation prompt prompt = f""" Adapt this learning path based on user progress and feedback: {json.dumps(path)} User progress: {json.dumps(user_progress)} Feedback: {feedback_str} Suggest specific adaptations for: 1. Content difficulty 2. Resource types 3. Assessment methods 4. Learning pace """ # Generate adaptations adaptations = json.loads(self.model_orchestrator.generate_structured_response( prompt=prompt, output_schema=""" { "content_changes": ["string"], "resource_changes": ["string"], "assessment_changes": ["string"], "pace_changes": ["string"] } """ )) # Apply adaptations for change in adaptations["content_changes"]: self._apply_change(path, change) # Store adaptation self.add_to_memory(f"Adapted learning path {path_id}: {json.dumps(adaptations)}") return { "success": True, "adaptations": adaptations, "updated_path": path, "message": f"Successfully adapted learning path {path_id}" } def generate_lesson(self, task: Dict[str, Any]) -> Dict[str, Any]: """ Generate a specific lesson for a topic Args: task: Lesson generation parameters Returns: Generated lesson """ topic = task.get("topic") lesson_type = task.get("type", "introductory") duration = task.get("duration", "60 minutes") if not topic: return { "success": False, "message": "Topic is required for lesson generation" } # Create lesson prompt prompt = f""" Generate a {lesson_type} lesson on: {topic} Duration: {duration} Include: 1. Key concepts 2. Practical examples 3. Interactive elements 4. Assessment questions 5. Additional resources Format as JSON with clear structure """ # Generate lesson lesson = json.loads(self.model_orchestrator.generate_structured_response( prompt=prompt, output_schema=""" { "title": "string", "description": "string", "sections": [ { "title": "string", "content": "string", "examples": ["string"], "questions": ["string"] } ], "interactive_elements": ["string"], "resources": ["string"] } """ )) # Add to memory self.add_to_memory(f"Generated lesson for {topic}: {json.dumps(lesson)}") return { "success": True, "lesson": lesson, "message": f"Successfully generated lesson for {topic}" } def _apply_change(self, path: Dict[str, Any], change: str) -> None: """ Apply a specific change to the learning path Args: path: Learning path to modify change: Change description """ # Parse change description try: change_type, details = change.split(":", 1) details = details.strip() if change_type == "difficulty": self._adjust_difficulty(path, details) elif change_type == "resources": self._update_resources(path, details) elif change_type == "assessment": self._modify_assessment(path, details) elif change_type == "pace": self._adjust_pace(path, details) except Exception as e: self.add_to_memory(f"Failed to apply change: {str(e)}") def _adjust_difficulty(self, path: Dict[str, Any], details: str) -> None: """ Adjust content difficulty Args: path: Learning path details: Difficulty adjustment details """ # Implementation of difficulty adjustment pass def _update_resources(self, path: Dict[str, Any], details: str) -> None: """ Update learning resources Args: path: Learning path details: Resource update details """ # Implementation of resource updates pass def _modify_assessment(self, path: Dict[str, Any], details: str) -> None: """ Modify assessment methods Args: path: Learning path details: Assessment modification details """ # Implementation of assessment modifications pass def _adjust_pace(self, path: Dict[str, Any], details: str) -> None: """ Adjust learning pace Args: path: Learning path details: Pace adjustment details """ # Implementation of pace adjustments pass