AMdevIA/HFlearningPathAgent
0
1from smolagents import Tool2from typing import Dict, List3import tools.search_hf_ressources as search_module4 5class GenerateLearningPathTool(Tool):6 def __init__(self):7 8 self.name="generate_learning_path"9 self.description="Generates a personalized learning path based on Hugging Face ressources"10 self.inputs = {11 'domain': {12 'type': 'string', 13 'description': 'Domain of interest (nlp, computer vision, etc.)'14 },15 'level': {16 'type': 'string', 17 'description': 'User\'s level (beginner, intermediate, advanced)'18 },19 'goals': {20 'type': 'array',21 'items': {22 'type': 'string'23 },24 'description': 'List of learning goals'25 },26 'time_available': {27 'type': 'string', 28 'description': 'Available time (short, medium, long)'29 }30 }31 self.output_type="any"32 33 super().__init__()34 35 36 def forward(self, domain: str, level: str, goals: List[str], time_available: str) -> Dict:37 # Search for relevant resources38 keywords = " ".join(goals)39 search_tool = search_module.SearchHfRessourcesTool()40 ressources = search_tool.forward(domain, keywords)41 42 # Create course according to level43 learning_path = {44 "title": f"Learning path {domain.capitalize()}",45 "level": level,46 "estimated_duration": self._calculate_duration(time_available),47 "modules": []48 }49 50 # MODULE 1: Fundamentals51 fundamentals_module = {52 "title": "Fundamentals",53 "description": f"Acquire the essential basics in {domain}",54 "ressources": []55 }56 57 # Add relevant resources with level58 if level == "beginner":59 # for beginner, basic courses and simple tutorials60 fundamentals_module["ressources"] = self._select_ressources(ressources["courses"], 2, "beginner") + \61 self._select_ressources(ressources["tutorials"], 2, "beginner")62 elif level == "intermediate":63 # mix of basic and intermediate64 fundamentals_module["ressources"] = self._select_ressources(ressources["courses"], 1, "beginner") + \65 self._select_ressources(ressources["courses"], 1, "intermediate") + \66 self._select_ressources(ressources["tutorials"], 1, "intermediate")67 else: #advanced68 fundamentals_module["ressources"] = self._select_ressources(ressources["courses"], 1, "intermediate") + \69 self._select_ressources(ressources["courses"], 1, "advanced") + \70 self._select_ressources(ressources["tutorials"], 1, "advanced")71 72 learning_path["modules"].append(fundamentals_module)73 74 # MODULE 2: Practical applications75 practical_module = {76 "title": "Practical applications",77 "description": f"Putting acquired knowledge into practice",78 "ressources": []79 }80 81 # add relevant model and space82 practical_module["ressources"] = self._select_ressources(ressources["models"], 2) + self._select_ressources(ressources["spaces"], 1)83 84 learning_path["modules"].append(practical_module)85 86 # MODULE 3: Personal project (for intermediate or advanced)87 if level in ["intermediate", "advanced"]:88 project_module = {89 "title": "Personal project",90 "description": f"Developing a complete {domain} project",91 "ressources": [92 {93 "title": f"Custom {domain} project",94 "type": "project",95 "description": f"Develop a complete project using Hugging Face's {domain} templates and techniques",96 "suggested_steps": [97 "Define the problem to be solved",98 "Select appropriate models",99 "Develop the solution",100 "Evaluate results",101 "Document and share on Hugging Face Spaces"102 ],103 "estimated_time": "1-2 weeks"104 }105 ]106 }107 108 # Add advanced resources for inspiration109 if ressources["datasets"]:110 project_module["ressources"].append({111 "title": "Recommended datasets",112 "type": "ressource_list",113 "items": [dataset.get("title") for dataset in ressources["datasets"][:3]],114 "estimated_time": "N/A"115 })116 117 learning_path["modules"].append(project_module)118 119 # And ensure all resources are properly formatted120 for module in learning_path["modules"]:121 # Make sure it's always "resources", not "ressources"122 module["resources"] = module.pop("ressources", module.get("resources", []))123 124 for resource in module["resources"]:125 # Fix any tuple for estimated_time126 if "estimated_time" in resource and isinstance(resource["estimated_time"], tuple):127 resource["estimated_time"] = resource["estimated_time"][0]128 129 return learning_path130 131 def _select_ressources(self, ressources, count, level=None):132 "Selects a specific number of ressources, possibly filtered by level"133 selected = []134 135 for ressource in ressources[:count]:136 ressource_copy = ressource.copy()137 138 # add additional information139 if "estimated_time" not in ressource_copy:140 if ressource_copy.get("type") == "course":141 ressource_copy["estimated_time"] = "4-6 hours",142 elif ressource_copy.get("type") == "tutorial":143 ressource_copy["estimated_time"] = "1-2 hours"144 else:145 ressource_copy["estimated_time"] = "2-3 hours"146 147 # estimate level if not include148 if "level" not in ressource_copy:149 if any(word in ressource_copy.get("title", "").lower() + " " + ressource_copy.get("description", "").lower()150 for word in ["basic", "introduction", "getting started", "beginner"]):151 ressource_copy["level"] = "beginner"152 elif any(word in ressource_copy.get("title", "").lower() + " " + ressource_copy.get("description", "").lower()153 for word in ["advanced", "expert", "specialized"]):154 ressource_copy["level"] = "advanced"155 else:156 ressource_copy["level"] = "intermediate"157 158 # level filter159 if level is None or ressource_copy.get("level") == level:160 selected.append(ressource_copy)161 162 if len(selected) >= count:163 break164 165 # If no resource with the specified level has been found, use the first available.166 if not selected and ressources:167 for ressource in ressources[:count]:168 ressource_copy = ressource.copy()169 ressource_copy["level"] = level or "intermediate"170 ressource_copy["estimated_time"] = "2-3 hours"171 selected.append(ressource_copy)172 173 return selected174 175 def _calculate_duration(self, time_available):176 """Calculates estimated total duration based on time available"""177 if time_available == "short":178 return "1-2 weeks"179 elif time_available == "medium":180 return "3-4 weeks"181 else:182 return "6-8 weeks"