suryanshupaul commited on
Commit
3e0126e
·
verified ·
1 Parent(s): b3aff39

Upload 5 files

Browse files
Files changed (5) hide show
  1. .env +1 -0
  2. Coursera.csv +0 -0
  3. app.py +949 -0
  4. requirements.txt +10 -0
  5. teachers.json +0 -0
.env ADDED
@@ -0,0 +1 @@
 
 
1
+ OPENAI_API_KEY=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
Coursera.csv ADDED
The diff for this file is too large to render. See raw diff
 
app.py ADDED
@@ -0,0 +1,949 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ import json
4
+ from typing import Dict, List, Optional, Union, Any
5
+ import os
6
+ import requests
7
+ from dotenv import load_dotenv
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+ from rich.panel import Panel
11
+ from rich.tree import Tree
12
+ from rich import box
13
+ import time
14
+ from tqdm import tqdm
15
+ import openai
16
+ import gradio as gr
17
+ from huggingface_hub import HfApi, HfFolder
18
+
19
+ # Load environment variables from .env file
20
+ load_dotenv()
21
+
22
+ class BaseRecommender:
23
+ def __init__(self):
24
+ self.console = Console()
25
+
26
+ # Initialize OpenAI client
27
+ api_key = os.getenv("OPENAI_API_KEY")
28
+ self.ai_enabled = bool(api_key)
29
+ if self.ai_enabled:
30
+ self.openai_client = openai.OpenAI(api_key=api_key)
31
+ else:
32
+ self.console.print("[yellow]Warning: OpenAI API key not found. AI-enhanced features will be disabled.[/yellow]")
33
+
34
+ class CourseRecommender(BaseRecommender):
35
+ def __init__(self, dataframe: pd.DataFrame):
36
+ """
37
+ Initialize the course recommender with course data
38
+ """
39
+ super().__init__()
40
+ self.courses = dataframe.drop(columns=['Unnamed: 1', 'Unnamed: 5'], errors='ignore')
41
+ self._preprocess_data()
42
+
43
+ def _preprocess_data(self):
44
+ """
45
+ Preprocess the course data for better recommendations
46
+ """
47
+ # Convert text columns to lowercase
48
+ text_columns = ['Course Name', 'Description', 'Skills', 'Difficulty Level']
49
+ for col in text_columns:
50
+ if col in self.courses.columns:
51
+ self.courses[col] = self.courses[col].astype(str).str.lower()
52
+
53
+ # Handle numeric values
54
+ self.courses['Course Rating'] = pd.to_numeric(self.courses['Course Rating'], errors='coerce').fillna(0)
55
+ self.courses['keyword_match_score'] = 0
56
+
57
+ # Add course ID for easy reference
58
+ self.courses['Course ID'] = range(1, len(self.courses) + 1)
59
+
60
+ def recommend_courses(self, topic: Optional[str] = None, skill_level: Optional[str] = None,
61
+ top_n: int = 5, personalized: bool = False, user_goals: Optional[str] = None) -> pd.DataFrame:
62
+ """
63
+ Recommend courses based on topic, skill level, and optional user goals
64
+ """
65
+ filtered_courses = self.courses.copy()
66
+
67
+ # Show processing indicator
68
+ with self.console.status("[bold green]Finding the best courses for you...", spinner="dots"):
69
+ time.sleep(1) # Simulate processing time
70
+
71
+ # Filter by topic if provided
72
+ if topic:
73
+ topic = topic.lower()
74
+ # Calculate keyword match score
75
+ filtered_courses['keyword_match_score'] = (
76
+ filtered_courses['Course Name'].str.contains(topic).astype(int) * 3 +
77
+ filtered_courses['Description'].str.contains(topic).astype(int) * 2 +
78
+ filtered_courses['Skills'].str.contains(topic).astype(int)
79
+ )
80
+ filtered_courses = filtered_courses[filtered_courses['keyword_match_score'] > 0]
81
+
82
+ # Filter by skill level if provided
83
+ if skill_level:
84
+ skill_level = skill_level.lower()
85
+ difficulty_map = {
86
+ 'beginner': ['beginner', 'intro', 'basic', 'level 1', 'fundamentals'],
87
+ 'intermediate': ['intermediate', 'mid-level', 'level 2', 'advanced beginner'],
88
+ 'advanced': ['advanced', 'expert', 'professional', 'level 3', 'master']
89
+ }
90
+ filtered_courses = filtered_courses[
91
+ filtered_courses['Difficulty Level'].apply(
92
+ lambda x: any(diff in str(x) for diff in difficulty_map.get(skill_level, [skill_level]))
93
+ )
94
+ ]
95
+
96
+ # Add AI relevance scoring if enabled
97
+ filtered_courses['ai_relevance_score'] = 0
98
+ if personalized and user_goals and self.ai_enabled:
99
+ for idx, course in filtered_courses.iterrows():
100
+ relevance_score = self._get_ai_relevance_score(course, topic, user_goals)
101
+ filtered_courses.at[idx, 'ai_relevance_score'] = relevance_score
102
+
103
+ # Calculate final recommendation score
104
+ if not filtered_courses.empty:
105
+ filtered_courses['recommendation_score'] = (
106
+ filtered_courses['Course Rating'] * 0.4 +
107
+ filtered_courses['keyword_match_score'] * 0.3 +
108
+ filtered_courses['ai_relevance_score'] * 0.2 +
109
+ np.random.rand(len(filtered_courses)) * 0.1
110
+ )
111
+ filtered_courses = filtered_courses.sort_values('recommendation_score', ascending=False)
112
+
113
+ return filtered_courses.head(top_n)
114
+
115
+ def _get_ai_relevance_score(self, course: pd.Series, topic: str, user_goals: str) -> float:
116
+ """
117
+ Use AI to determine how relevant a course is to user's specific goals
118
+ """
119
+ if not self.ai_enabled:
120
+ return 0.5
121
+
122
+ try:
123
+ prompt = f"""
124
+ Rate how relevant this course is to a learner with these goals on a scale of 0-10:
125
+
126
+ Topic of interest: {topic}
127
+ User's learning goals: {user_goals}
128
+
129
+ Course details:
130
+ - Name: {course['Course Name']}
131
+ - Description: {course['Description']}
132
+ - Skills taught: {course['Skills']}
133
+ - Difficulty: {course['Difficulty Level']}
134
+
135
+ Return only a number from 0-10.
136
+ """
137
+
138
+ response = self.openai_client.chat.completions.create(
139
+ model="gpt-3.5-turbo",
140
+ messages=[
141
+ {"role": "system", "content": "You are an educational advisor helping match courses to learner goals."},
142
+ {"role": "user", "content": prompt}
143
+ ],
144
+ max_tokens=10,
145
+ temperature=0.3
146
+ )
147
+
148
+ try:
149
+ score = float(response.choices[0].message.content.strip())
150
+ return min(max(score, 0), 10) / 10 # Normalize to 0-1 range
151
+ except ValueError:
152
+ return 0.5 # Default value if parsing fails
153
+
154
+ except Exception as e:
155
+ self.console.print(f"[red]Error getting AI relevance score: {e}[/red]")
156
+ return 0.5
157
+
158
+ def generate_roadmap(self, topic: str, skill_level: Optional[str] = None,
159
+ user_goals: Optional[str] = None, detailed: bool = False) -> Dict:
160
+ """
161
+ Generate a personalized learning roadmap based on the topic and user goals
162
+ """
163
+ self.console.print(Panel(f"[bold cyan]Generating your personalized learning roadmap for [green]{topic}[/green]...[/bold cyan]"))
164
+
165
+ # Display a progress bar for visual effect
166
+ for _ in tqdm(range(5), desc="Processing roadmap data"):
167
+ time.sleep(0.3)
168
+
169
+ # Generate roadmap using AI if enabled and requested, otherwise use default
170
+ if detailed and self.ai_enabled and user_goals:
171
+ return self._generate_ai_roadmap(topic, skill_level, user_goals)
172
+ else:
173
+ return self._generate_default_roadmap(topic)
174
+
175
+ def _generate_ai_roadmap(self, topic: str, skill_level: str, user_goals: str) -> Dict:
176
+ """
177
+ Use AI to generate a personalized and detailed learning roadmap
178
+ """
179
+ try:
180
+ # Enhanced prompt with specific structure and guidance
181
+ prompt = f"""
182
+ Create a comprehensive learning roadmap for someone wanting to master {topic}.
183
+
184
+ Learner information:
185
+ - Current skill level: {skill_level}
186
+ - Learning goals: {user_goals}
187
+
188
+ The roadmap should be detailed, actionable, and specifically tailored to the learner's
189
+ skill level and goals. Provide a clear progression path that breaks down the journey
190
+ into logical stages with specific concepts to learn at each stage.
191
+
192
+ Format the response as a JSON object with exactly this structure:
193
+ {{
194
+ "learningPath": [
195
+ {{
196
+ "step": "Step name (be specific)",
197
+ "difficulty": "Beginner/Intermediate/Advanced",
198
+ "description": "Detailed description of this learning stage (2-3 sentences)",
199
+ "time_estimate": "Estimated completion time (weeks/months)",
200
+ "key_concepts": ["Specific concept 1", "Specific concept 2", "Specific concept 3"],
201
+ "milestones": ["Practical milestone 1", "Practical milestone 2"],
202
+ "practice_activities": ["Activity 1", "Activity 2"]
203
+ }},
204
+ // 3-5 steps total, progressing from fundamentals to mastery
205
+ ],
206
+ "projectSuggestions": [
207
+ {{
208
+ "name": "Project name (be specific to {topic})",
209
+ "description": "Detailed project description (2-3 sentences)",
210
+ "complexity": "Low/Medium/High",
211
+ "skills_practiced": ["Skill 1", "Skill 2", "Skill 3"],
212
+ "resources": ["Specific resource 1", "Specific resource 2"],
213
+ "estimated_time": "Project completion time estimate"
214
+ }},
215
+ // 3-4 projects of increasing complexity
216
+ ],
217
+ "resources": {{
218
+ "books": ["Specific book title 1", "Specific book title 2", "Specific book title 3"],
219
+ "online_courses": ["Specific course 1", "Specific course 2"],
220
+ "communities": ["Specific community 1", "Specific community 2"],
221
+ "tools": ["Specific tool 1", "Specific tool 2", "Specific tool 3"],
222
+ "practice_platforms": ["Specific platform 1", "Specific platform 2"]
223
+ }},
224
+ "career_insights": [
225
+ "Specific insight about {topic} career opportunities",
226
+ "Skill demand information",
227
+ "Industry application of {topic} skills"
228
+ ]
229
+ }}
230
+
231
+ Ensure all content is specific to {topic} (not generic) and appropriate for a {skill_level}
232
+ with these goals: {user_goals}. Focus on practical, actionable advice.
233
+ """
234
+
235
+ response = self.openai_client.chat.completions.create(
236
+ model="gpt-4",
237
+ messages=[
238
+ {"role": "system", "content": "You are an expert educational curriculum designer with deep knowledge across technical and non-technical subjects. You create detailed, actionable learning plans that are practical and tailored to individual needs."},
239
+ {"role": "user", "content": prompt}
240
+ ],
241
+ max_tokens=2500,
242
+ temperature=0.5,
243
+ response_format={"type": "json_object"} # Enforce JSON response
244
+ )
245
+
246
+ try:
247
+ roadmap_text = response.choices[0].message.content
248
+ return json.loads(roadmap_text)
249
+ except json.JSONDecodeError as e:
250
+ self.console.print(f"[yellow]Warning: Could not parse AI response as JSON: {e}. Using default roadmap.[/yellow]")
251
+ return self._generate_default_roadmap(topic)
252
+
253
+ except Exception as e:
254
+ self.console.print(f"[red]Error generating AI roadmap: {e}[/red]")
255
+ return self._generate_default_roadmap(topic)
256
+
257
+ def _generate_default_roadmap(self, topic: str) -> Dict:
258
+ """
259
+ Generate a default roadmap when AI generation fails or is not available
260
+ """
261
+ return {
262
+ "learningPath": [
263
+ {
264
+ "step": f"Foundations of {topic}",
265
+ "difficulty": "Beginner",
266
+ "description": f"Build core knowledge and fundamental skills in {topic}. Focus on understanding basic principles and becoming familiar with essential tools.",
267
+ "time_estimate": "4-6 weeks",
268
+ "key_concepts": [f"{topic} basics", "Core principles", "Fundamental tools and techniques"],
269
+ "milestones": [f"Complete first {topic} exercise", f"Build simple {topic} project"],
270
+ "practice_activities": [f"Daily {topic} exercises", "Follow beginner tutorials"]
271
+ },
272
+ {
273
+ "step": f"{topic} Skill Development",
274
+ "difficulty": "Intermediate",
275
+ "description": f"Deepen understanding of {topic} and apply more advanced concepts. Focus on building practical skills through hands-on projects and implementation.",
276
+ "time_estimate": "8-12 weeks",
277
+ "key_concepts": [f"Advanced {topic} techniques", "Applied projects", "Specialized tools"],
278
+ "milestones": [f"Complete medium complexity {topic} project", "Solve real-world problems"],
279
+ "practice_activities": ["Implement sample projects", "Participate in forums/discussions"]
280
+ },
281
+ {
282
+ "step": f"{topic} Mastery & Specialization",
283
+ "difficulty": "Advanced",
284
+ "description": f"Develop expert-level skills in {topic} with focus on real-world application. Specialize in specific areas and build a professional portfolio.",
285
+ "time_estimate": "12-16 weeks",
286
+ "key_concepts": ["Industry best practices", "Complex problem-solving", "Portfolio development"],
287
+ "milestones": ["Create capstone project", "Contribute to community"],
288
+ "practice_activities": ["Build complex projects", "Mentor beginners"]
289
+ }
290
+ ],
291
+ "projectSuggestions": [
292
+ {
293
+ "name": f"Beginner Project: {topic} Fundamentals Application",
294
+ "description": f"Apply basic {topic} concepts in a simple project to practice fundamentals and gain confidence.",
295
+ "complexity": "Low",
296
+ "skills_practiced": [f"Basic {topic} principles", "Problem-solving", "Tool familiarity"],
297
+ "resources": ["Online tutorials", "Documentation", "Starter templates"],
298
+ "estimated_time": "1-2 weeks"
299
+ },
300
+ {
301
+ "name": f"Intermediate Project: Interactive {topic} Application",
302
+ "description": f"Create a more complex application using intermediate {topic} skills with greater functionality and sophistication.",
303
+ "complexity": "Medium",
304
+ "skills_practiced": [f"Intermediate {topic} techniques", "Code organization", "Testing"],
305
+ "resources": ["GitHub repositories", "Online coding platforms", "Community forums"],
306
+ "estimated_time": "3-4 weeks"
307
+ },
308
+ {
309
+ "name": f"Capstone Project: Advanced {topic} Implementation",
310
+ "description": f"Apply all learned skills in a comprehensive {topic} project that showcases mastery and solves a real-world problem.",
311
+ "complexity": "High",
312
+ "skills_practiced": [f"Advanced {topic} mastery", "System design", "Optimization"],
313
+ "resources": ["Industry case studies", "Research papers", "Expert communities"],
314
+ "estimated_time": "6-8 weeks"
315
+ }
316
+ ],
317
+ "resources": {
318
+ "books": [f"Introduction to {topic}", f"Advanced {topic} Techniques", f"Mastering {topic}"],
319
+ "online_courses": [f"{topic} for Beginners", f"Professional {topic} Masterclass"],
320
+ "communities": ["Stack Overflow", "Reddit", f"{topic} Discord Servers"],
321
+ "tools": [f"{topic} Development Environment", "Version Control", "Testing Frameworks"],
322
+ "practice_platforms": ["Codecademy", "Exercism", "LeetCode"]
323
+ },
324
+ "career_insights": [
325
+ f"Proficiency in {topic} is valuable for roles in software development, data science, and IT operations",
326
+ f"Entry-level {topic} positions typically require demonstrated project experience",
327
+ f"{topic} specialists can pursue careers in consulting, education, or product development"
328
+ ]
329
+ }
330
+
331
+ def get_course_details(self, course: pd.Series) -> Dict[str, str]:
332
+ """
333
+ Get detailed course information
334
+ """
335
+ return {
336
+ "name": course.get('Course Name', 'N/A'),
337
+ "difficulty": course.get('Difficulty Level', 'N/A'),
338
+ "rating": str(course.get('Course Rating', 'N/A')),
339
+ "url": course.get('Course URL', '#'),
340
+ "skills": course.get('Skills', 'N/A'),
341
+ "description": course.get('Description', 'No description available'),
342
+ "id": str(course.get('Course ID', '0'))
343
+ }
344
+
345
+ def display_roadmap(self, roadmap: Dict):
346
+ """
347
+ Display the learning roadmap in a beautiful format using rich
348
+ """
349
+ self.console.print("\n")
350
+ self.console.print(Panel("[bold cyan]YOUR PERSONALIZED LEARNING JOURNEY[/bold cyan]",
351
+ box=box.DOUBLE, expand=False))
352
+
353
+ # Create a tree for learning path
354
+ learning_tree = Tree("[bold yellow]Learning Path[/bold yellow]")
355
+ for stage in roadmap["learningPath"]:
356
+ stage_node = learning_tree.add(f"[bold green]{stage['step']}[/bold green] ({stage['difficulty']}) - {stage['time_estimate']}")
357
+ stage_node.add(f"[italic]{stage['description']}[/italic]")
358
+
359
+ concepts_node = stage_node.add("[bold blue]Key Concepts:[/bold blue]")
360
+ for concept in stage.get("key_concepts", []):
361
+ concepts_node.add(concept)
362
+
363
+ if "milestones" in stage:
364
+ milestones_node = stage_node.add("[bold magenta]Milestones:[/bold magenta]")
365
+ for milestone in stage["milestones"]:
366
+ milestones_node.add(milestone)
367
+
368
+ if "practice_activities" in stage:
369
+ activities_node = stage_node.add("[bold cyan]Practice Activities:[/bold cyan]")
370
+ for activity in stage["practice_activities"]:
371
+ activities_node.add(activity)
372
+
373
+ self.console.print(learning_tree)
374
+ self.console.print("\n")
375
+
376
+ # Project suggestions table
377
+ project_table = Table(title="Recommended Projects", box=box.ROUNDED)
378
+ project_table.add_column("Project Name", style="cyan", no_wrap=True)
379
+ project_table.add_column("Description", style="white")
380
+ project_table.add_column("Complexity", style="magenta")
381
+ project_table.add_column("Est. Time", style="yellow")
382
+
383
+ for project in roadmap["projectSuggestions"]:
384
+ project_table.add_row(
385
+ project["name"],
386
+ project["description"],
387
+ project["complexity"],
388
+ project.get("estimated_time", "N/A")
389
+ )
390
+
391
+ self.console.print(project_table)
392
+ self.console.print("\n")
393
+
394
+ # Resources panel
395
+ resources = roadmap.get("resources", {})
396
+ resources_text = ""
397
+
398
+ resource_categories = {
399
+ "books": "Recommended Books",
400
+ "online_courses": "Online Courses",
401
+ "communities": "Communities",
402
+ "tools": "Essential Tools",
403
+ "practice_platforms": "Practice Platforms"
404
+ }
405
+
406
+ for category, title in resource_categories.items():
407
+ if category in resources and resources[category]:
408
+ resources_text += f"[bold yellow]{title}:[/bold yellow]\n"
409
+ for item in resources[category]:
410
+ resources_text += f"• {item}\n"
411
+ resources_text += "\n"
412
+
413
+ self.console.print(Panel(resources_text, title="[bold cyan]Learning Resources[/bold cyan]",
414
+ box=box.ROUNDED, expand=False))
415
+
416
+ # Career insights
417
+ if "career_insights" in roadmap and roadmap["career_insights"]:
418
+ career_text = "[bold yellow]Career Insights:[/bold yellow]\n"
419
+ for insight in roadmap["career_insights"]:
420
+ career_text += f"• {insight}\n"
421
+
422
+ self.console.print(Panel(career_text, title="[bold cyan]Career Opportunities[/bold cyan]",
423
+ box=box.ROUNDED, expand=False))
424
+
425
+ def display_recommended_courses(self, courses: pd.DataFrame):
426
+ """
427
+ Display recommended courses in a beautiful format
428
+ """
429
+ if courses.empty:
430
+ self.console.print("[yellow]No courses match your criteria. Try broader search terms.[/yellow]")
431
+ return
432
+
433
+ table = Table(title="Recommended Courses", box=box.ROUNDED)
434
+ table.add_column("ID", style="dim")
435
+ table.add_column("Course Name", style="cyan")
436
+ table.add_column("Rating", style="yellow")
437
+ table.add_column("Difficulty", style="green")
438
+
439
+ for _, course in courses.iterrows():
440
+ table.add_row(
441
+ str(course.get('Course ID', 'N/A')),
442
+ course.get('Course Name', 'N/A').title(),
443
+ f"{course.get('Course Rating', 0):.1f} ★",
444
+ course.get('Difficulty Level', 'N/A').title()
445
+ )
446
+
447
+ self.console.print(table)
448
+ self.console.print("\n[dim]Use the course ID to get more details about a specific course.[/dim]")
449
+
450
+ def roadmap_to_markdown(self, roadmap: Dict, topic: str, skill_level: str) -> str:
451
+ """
452
+ Convert a roadmap to markdown format for export or display
453
+ """
454
+ markdown = f"# Personalized Learning Roadmap: {topic.title()}\n\n"
455
+ markdown += f"*Skill Level: {skill_level.title()}*\n\n"
456
+
457
+ # Learning Path
458
+ markdown += "## Learning Path\n\n"
459
+ for i, stage in enumerate(roadmap["learningPath"]):
460
+ markdown += f"### {i+1}. {stage['step']} ({stage['difficulty']}) - {stage['time_estimate']}\n\n"
461
+ markdown += f"{stage['description']}\n\n"
462
+
463
+ markdown += "**Key Concepts:**\n"
464
+ for concept in stage.get("key_concepts", []):
465
+ markdown += f"- {concept}\n"
466
+ markdown += "\n"
467
+
468
+ if "milestones" in stage:
469
+ markdown += "**Milestones:**\n"
470
+ for milestone in stage["milestones"]:
471
+ markdown += f"- {milestone}\n"
472
+ markdown += "\n"
473
+
474
+ if "practice_activities" in stage:
475
+ markdown += "**Practice Activities:**\n"
476
+ for activity in stage["practice_activities"]:
477
+ markdown += f"- {activity}\n"
478
+ markdown += "\n"
479
+
480
+ # Project Suggestions
481
+ markdown += "## Recommended Projects\n\n"
482
+ for i, project in enumerate(roadmap["projectSuggestions"]):
483
+ markdown += f"### {i+1}. {project['name']} ({project['complexity']})\n\n"
484
+ markdown += f"{project['description']}\n\n"
485
+
486
+ if "skills_practiced" in project:
487
+ markdown += "**Skills Practiced:**\n"
488
+ for skill in project["skills_practiced"]:
489
+ markdown += f"- {skill}\n"
490
+ markdown += "\n"
491
+
492
+ markdown += "**Resources:**\n"
493
+ for resource in project.get("resources", []):
494
+ markdown += f"- {resource}\n"
495
+ markdown += "\n"
496
+
497
+ if "estimated_time" in project:
498
+ markdown += f"**Estimated Time:** {project['estimated_time']}\n\n"
499
+
500
+ # Resources
501
+ markdown += "## Learning Resources\n\n"
502
+ resources = roadmap.get("resources", {})
503
+
504
+ resource_categories = {
505
+ "books": "Recommended Books",
506
+ "online_courses": "Online Courses",
507
+ "communities": "Communities",
508
+ "tools": "Essential Tools",
509
+ "practice_platforms": "Practice Platforms"
510
+ }
511
+
512
+ for category, title in resource_categories.items():
513
+ if category in resources and resources[category]:
514
+ markdown += f"### {title}\n"
515
+ for item in resources[category]:
516
+ markdown += f"- {item}\n"
517
+ markdown += "\n"
518
+
519
+ # Career Insights
520
+ if "career_insights" in roadmap and roadmap["career_insights"]:
521
+ markdown += "## Career Opportunities\n\n"
522
+ for insight in roadmap["career_insights"]:
523
+ markdown += f"- {insight}\n"
524
+
525
+ return markdown
526
+
527
+ class TeacherRecommender(BaseRecommender):
528
+ def __init__(self, teachers_data: List[Dict[str, Any]]):
529
+ """
530
+ Initialize the teacher recommender with teacher data
531
+ """
532
+ super().__init__()
533
+ self.teachers = pd.DataFrame(teachers_data)
534
+ self._preprocess_data()
535
+
536
+ def _preprocess_data(self):
537
+ """
538
+ Preprocess the teacher data for better recommendations
539
+ """
540
+ # Convert text columns to lowercase for easier matching
541
+ text_columns = ['name', 'location', 'subject', 'description', 'preferredMode']
542
+ for col in text_columns:
543
+ if col in self.teachers.columns:
544
+ self.teachers[col] = self.teachers[col].astype(str).str.lower()
545
+
546
+ # Ensure numeric columns are properly formatted
547
+ self.teachers['rating'] = pd.to_numeric(self.teachers['rating'], errors='coerce').fillna(0)
548
+ self.teachers['fees'] = pd.to_numeric(self.teachers['fees'], errors='coerce').fillna(0)
549
+ self.teachers['experience'] = pd.to_numeric(self.teachers['experience'], errors='coerce').fillna(0)
550
+
551
+ # Add teacher ID for easy reference
552
+ self.teachers['Teacher ID'] = range(1, len(self.teachers) + 1)
553
+
554
+ def recommend_teachers(self,
555
+ subject: Optional[str] = None,
556
+ location: Optional[str] = None,
557
+ preferred_mode: Optional[str] = None,
558
+ max_fees: Optional[float] = None,
559
+ min_experience: Optional[int] = None,
560
+ min_rating: Optional[float] = None,
561
+ top_n: int = 5) -> pd.DataFrame:
562
+ """
563
+ Recommend teachers based on criteria
564
+ """
565
+ filtered_teachers = self.teachers.copy()
566
+
567
+ # Show processing indicator
568
+ with self.console.status("[bold green]Finding the best teachers for you...", spinner="dots"):
569
+ # Filter by subject if provided
570
+ if subject:
571
+ subject = subject.lower()
572
+ # Calculate keyword match score for subject
573
+ filtered_teachers['subject_match'] = filtered_teachers['subject'].str.contains(subject).astype(int)
574
+ filtered_teachers = filtered_teachers[filtered_teachers['subject_match'] > 0]
575
+
576
+ # Filter by location if provided
577
+ if location and not filtered_teachers.empty:
578
+ location = location.lower()
579
+ filtered_teachers = filtered_teachers[filtered_teachers['location'].str.contains(location)]
580
+
581
+ # Filter by preferred mode if provided
582
+ if preferred_mode and not filtered_teachers.empty:
583
+ preferred_mode = preferred_mode.lower()
584
+ filtered_teachers = filtered_teachers[filtered_teachers['preferredMode'] == preferred_mode]
585
+
586
+ # Filter by maximum fees if provided
587
+ if max_fees is not None and not filtered_teachers.empty:
588
+ filtered_teachers = filtered_teachers[filtered_teachers['fees'] <= max_fees]
589
+
590
+ # Filter by minimum experience if provided
591
+ if min_experience is not None and not filtered_teachers.empty:
592
+ filtered_teachers = filtered_teachers[filtered_teachers['experience'] >= min_experience]
593
+
594
+ # Filter by minimum rating if provided
595
+ if min_rating is not None and not filtered_teachers.empty:
596
+ filtered_teachers = filtered_teachers[filtered_teachers['rating'] >= min_rating]
597
+
598
+ # Calculate recommendation score
599
+ if not filtered_teachers.empty:
600
+ filtered_teachers['recommendation_score'] = (
601
+ filtered_teachers['rating'] * 0.4 +
602
+ filtered_teachers['experience'] * 0.3 -
603
+ (filtered_teachers['fees'] / 1000) * 0.2 # Normalize fees impact
604
+ )
605
+
606
+ # Sort by recommendation score
607
+ filtered_teachers = filtered_teachers.sort_values('recommendation_score', ascending=False)
608
+
609
+ return filtered_teachers.head(top_n)
610
+
611
+ def get_teacher_details(self, teacher: pd.Series) -> Dict[str, str]:
612
+ """
613
+ Get detailed teacher information
614
+ """
615
+ return {
616
+ "name": teacher.get('name', 'N/A').title(),
617
+ "email": teacher.get('email', 'N/A'),
618
+ "location": teacher.get('location', 'N/A').title(),
619
+ "subject": teacher.get('subject', 'N/A').title(),
620
+ "rating": str(teacher.get('rating', 'N/A')),
621
+ "preferredMode": teacher.get('preferredMode', 'N/A').title(),
622
+ "fees": str(teacher.get('fees', 'N/A')),
623
+ "description": teacher.get('description', 'No description available'),
624
+ "experience": str(teacher.get('experience', 'N/A')),
625
+ "id": str(teacher.get('Teacher ID', '0'))
626
+ }
627
+
628
+ def display_recommended_teachers(self, teachers: pd.DataFrame):
629
+ """
630
+ Display recommended teachers in a beautiful format
631
+ """
632
+ if teachers.empty:
633
+ self.console.print("[yellow]No teachers match your criteria. Try broader search terms.[/yellow]")
634
+ return
635
+
636
+ table = Table(title="Recommended Teachers", box=box.ROUNDED)
637
+ table.add_column("ID", style="dim")
638
+ table.add_column("Name", style="cyan")
639
+ table.add_column("Subject", style="green")
640
+ table.add_column("Rating", style="yellow")
641
+ table.add_column("Experience", style="magenta")
642
+ table.add_column("Fees", style="blue")
643
+ table.add_column("Mode", style="cyan")
644
+
645
+ for _, teacher in teachers.iterrows():
646
+ table.add_row(
647
+ str(teacher.get('Teacher ID', 'N/A')),
648
+ teacher.get('name', 'N/A').title(),
649
+ teacher.get('subject', 'N/A').title(),
650
+ f"{teacher.get('rating', 0):.1f} ★",
651
+ f"{teacher.get('experience', 0)} years",
652
+ f"${teacher.get('fees', 0):.2f}",
653
+ teacher.get('preferredMode', 'N/A').title()
654
+ )
655
+
656
+ self.console.print(table)
657
+ self.console.print("\n[dim]Use the teacher ID to get more details about a specific teacher.[/dim]")
658
+
659
+ def teachers_to_markdown(self, recommended_teachers: pd.DataFrame) -> str:
660
+ """
661
+ Format teacher recommendations as markdown
662
+ """
663
+ teachers_md = "# Recommended Teachers\n\n"
664
+ for i, (_, teacher) in enumerate(recommended_teachers.iterrows()):
665
+ teachers_md += f"## {i+1}. {teacher.get('name', 'N/A').title()}\n\n"
666
+ teachers_md += f"**Subject:** {teacher.get('subject', 'N/A').title()}\n\n"
667
+ teachers_md += f"**Rating:** {teacher.get('rating', 0):.1f} ★\n\n"
668
+ teachers_md += f"**Experience:** {teacher.get('experience', 0)} years\n\n"
669
+ teachers_md += f"**Location:** {teacher.get('location', 'N/A').title()}\n\n"
670
+ teachers_md += f"**Preferred Mode:** {teacher.get('preferredMode', 'N/A').title()}\n\n"
671
+ teachers_md += f"**Fees:** ${teacher.get('fees', 0):.2f}\n\n"
672
+ teachers_md += f"**Description:**\n{teacher.get('description', 'No description available')}\n\n"
673
+ teachers_md += f"**Contact:** {teacher.get('email', 'N/A')}\n\n"
674
+ teachers_md += "---\n\n"
675
+ return teachers_md
676
+
677
+ def load_courses(file_path: str = 'Coursera.csv') -> Optional[CourseRecommender]:
678
+ """
679
+ Load courses from CSV and create a CourseRecommender instance
680
+ """
681
+ console = Console()
682
+
683
+ try:
684
+ with console.status("[bold green]Loading course data...", spinner="dots"):
685
+ df = pd.read_csv(file_path)
686
+ time.sleep(1) # Simulate loading time for visual effect
687
+ console.print(f"[green]Successfully loaded {len(df)} courses![/green]")
688
+ return CourseRecommender(df)
689
+ except FileNotFoundError:
690
+ console.print(f"[red]Error: {file_path} file not found.[/red]")
691
+ return None
692
+ except Exception as e:
693
+ console.print(f"[red]An error occurred while reading the CSV: {e}[/red]")
694
+ return None
695
+
696
+ def load_teachers(file_path: str = 'teachers.json') -> Optional[TeacherRecommender]:
697
+ """
698
+ Load teachers from JSON and create a TeacherRecommender instance
699
+ """
700
+ console = Console()
701
+
702
+ try:
703
+ with console.status("[bold green]Loading teacher data...", spinner="dots"):
704
+ with open(file_path, 'r') as f:
705
+ teachers_data = json.load(f)
706
+
707
+ # Check if it's a list of teachers or a single teacher
708
+ if not isinstance(teachers_data, list):
709
+ teachers_data = [teachers_data]
710
+
711
+ console.print(f"[green]Successfully loaded {len(teachers_data)} teachers![/green]")
712
+ return TeacherRecommender(teachers_data)
713
+ except FileNotFoundError:
714
+ console.print(f"[red]Error: {file_path} file not found.[/red]")
715
+ return None
716
+ except Exception as e:
717
+ console.print(f"[red]An error occurred while reading the JSON: {e}[/red]")
718
+ return None
719
+
720
+ def format_courses_as_markdown(recommended_courses: pd.DataFrame) -> str:
721
+ """
722
+ Format course recommendations as markdown
723
+ """
724
+ courses_md = "# Recommended Courses\n\n"
725
+ for i, (_, course) in enumerate(recommended_courses.iterrows()):
726
+ courses_md += f"## {i+1}. {course.get('Course Name', 'N/A').title()}\n\n"
727
+ courses_md += f"**Rating:** {course.get('Course Rating', 0):.1f} ★\n\n"
728
+ courses_md += f"**Difficulty:** {course.get('Difficulty Level', 'N/A').title()}\n\n"
729
+ courses_md += f"**Skills:** {course.get('Skills', 'N/A').title()}\n\n"
730
+ courses_md += f"**Description:**\n{course.get('Description', 'No description available')}\n\n"
731
+ if 'Course URL' in course and course['Course URL'] != '#':
732
+ courses_md += f"[View Course]({course['Course URL']})\n\n"
733
+ courses_md += "---\n\n"
734
+ return courses_md
735
+
736
+ def main():
737
+ console = Console()
738
+
739
+ # Print welcome message
740
+ console.print(Panel.fit(
741
+ "[bold cyan]Enhanced Learning Platform[/bold cyan]\n"
742
+ "[yellow]Find the perfect courses, create your learning journey, and connect with expert teachers[/yellow]",
743
+ box=box.DOUBLE))
744
+
745
+ # Load both course and teacher data
746
+ course_recommender = load_courses()
747
+ teacher_recommender = load_teachers()
748
+
749
+ if not course_recommender or not teacher_recommender:
750
+ return
751
+
752
+ console.print("[bold]Let's find the perfect learning path for you![/bold]\n")
753
+
754
+ topic = console.input("[bold green]Enter the topic you want to learn about: [/bold green]")
755
+ skill_level = console.input("[bold green]Enter your skill level (Beginner, Intermediate, Advanced): [/bold green]")
756
+
757
+ use_ai = False
758
+ user_goals = None
759
+
760
+ if course_recommender.ai_enabled:
761
+ use_ai = console.input("[bold green]Would you like AI-enhanced personalized recommendations? (y/n): [/bold green]").lower() == 'y'
762
+ if use_ai:
763
+ user_goals = console.input("[bold green]What are your learning goals or career objectives with this topic? [/bold green]")
764
+
765
+ # Generate and display roadmap
766
+ roadmap = course_recommender.generate_roadmap(topic, skill_level, user_goals, detailed=use_ai)
767
+ course_recommender.display_roadmap(roadmap)
768
+
769
+ # Option to export roadmap
770
+ export = console.input("\n[bold green]Would you like to export this roadmap to a markdown file? (y/n): [/bold green]").lower() == 'y'
771
+ if export:
772
+ markdown = course_recommender.roadmap_to_markdown(roadmap, topic, skill_level)
773
+ filename = f"{topic.lower().replace(' ', '_')}_roadmap.md"
774
+ with open(filename, "w") as f:
775
+ f.write(markdown)
776
+ console.print(f"[green]Roadmap exported to {filename}[/green]")
777
+
778
+ console.print("\n[bold]Press Enter to see recommended courses...[/bold]")
779
+ input()
780
+
781
+ # Get and display recommended courses
782
+ recommended_courses = course_recommender.recommend_courses(topic, skill_level, personalized=use_ai, user_goals=user_goals)
783
+ course_recommender.display_recommended_courses(recommended_courses)
784
+
785
+ # Now offer teacher recommendations
786
+ find_teachers = console.input("\n[bold green]Would you like to find teachers for this subject? (y/n): [/bold green]").lower() == 'y'
787
+
788
+ if find_teachers:
789
+ console.print("\n[bold cyan]Finding teachers for your learning journey...[/bold cyan]")
790
+
791
+ # Get additional teacher filtering criteria
792
+ location = console.input("[bold green]Preferred location (or press Enter to skip): [/bold green]")
793
+ preferred_mode = console.input("[bold green]Preferred teaching mode (online/in-person, or press Enter to skip): [/bold green]")
794
+
795
+ max_fees_str = console.input("[bold green]Maximum budget for teacher fees (or press Enter to skip): [/bold green]")
796
+ max_fees = float(max_fees_str) if max_fees_str else None
797
+
798
+ min_experience_str = console.input("[bold green]Minimum years of experience (or press Enter to skip): [/bold green]")
799
+ min_experience = int(min_experience_str) if min_experience_str else None
800
+
801
+ min_rating_str = console.input("[bold green]Minimum teacher rating (1-5, or press Enter to skip): [/bold green]")
802
+ min_rating = float(min_rating_str) if min_rating_str else None
803
+
804
+ # Get teacher recommendations
805
+ recommended_teachers = teacher_recommender.recommend_teachers(
806
+ subject=topic,
807
+ location=location if location else None,
808
+ preferred_mode=preferred_mode if preferred_mode else None,
809
+ max_fees=max_fees,
810
+ min_experience=min_experience,
811
+ min_rating=min_rating
812
+ )
813
+
814
+ # Display teacher recommendations
815
+ teacher_recommender.display_recommended_teachers(recommended_teachers)
816
+
817
+ # Allow user to view detailed teacher info
818
+ while True:
819
+ teacher_id = console.input("\n[bold green]Enter a teacher ID for more details (or 'q' to quit): [/bold green]")
820
+ if teacher_id.lower() == 'q':
821
+ break
822
+
823
+ try:
824
+ teacher_id = int(teacher_id)
825
+ teacher = recommended_teachers[recommended_teachers['Teacher ID'] == teacher_id]
826
+ if not teacher.empty:
827
+ details = teacher_recommender.get_teacher_details(teacher.iloc[0])
828
+
829
+ console.print(Panel(
830
+ f"[bold cyan]{details['name']}[/bold cyan]\n\n"
831
+ f"[yellow]Subject:[/yellow] {details['subject']}\n"
832
+ f"[yellow]Rating:[/yellow] {details['rating']} ★\n"
833
+ f"[yellow]Experience:[/yellow] {details['experience']} years\n"
834
+ f"[yellow]Location:[/yellow] {details['location']}\n"
835
+ f"[yellow]Preferred Mode:[/yellow] {details['preferredMode']}\n"
836
+ f"[yellow]Fees:[/yellow] ${details['fees']}\n\n"
837
+ f"[yellow]Description:[/yellow]\n{details['description']}\n\n"
838
+ f"[yellow]Contact:[/yellow] {details['email']}",
839
+ title="Teacher Details", box=box.ROUNDED, width=100
840
+ ))
841
+ else:
842
+ console.print("[yellow]Teacher ID not found. Please try again.[/yellow]")
843
+ except ValueError:
844
+ console.print("[yellow]Please enter a valid teacher ID.[/yellow]")
845
+
846
+ console.print(Panel("[bold cyan]Thank you for using our Enhanced Learning Platform![/bold cyan]", box=box.ROUNDED))
847
+
848
+ def create_gradio_interface(course_recommender: CourseRecommender, teacher_recommender: TeacherRecommender):
849
+ """
850
+ Create a Gradio interface that includes both course and teacher recommendations
851
+ """
852
+ def recommend_all(topic, skill_level, goals, use_ai, location, preferred_mode, max_fees, min_experience, min_rating):
853
+ try:
854
+ # Generate roadmap
855
+ roadmap = course_recommender.generate_roadmap(
856
+ topic=topic,
857
+ skill_level=skill_level,
858
+ user_goals=goals if goals else None,
859
+ detailed=use_ai
860
+ )
861
+
862
+ # Get course recommendations
863
+ recommended_courses = course_recommender.recommend_courses(
864
+ topic=topic,
865
+ skill_level=skill_level,
866
+ personalized=use_ai,
867
+ user_goals=goals if goals else None
868
+ )
869
+
870
+ # Get teacher recommendations
871
+ recommended_teachers = teacher_recommender.recommend_teachers(
872
+ subject=topic,
873
+ location=location if location else None,
874
+ preferred_mode=preferred_mode if preferred_mode else None,
875
+ max_fees=float(max_fees) if max_fees else None,
876
+ min_experience=int(min_experience) if min_experience else None,
877
+ min_rating=float(min_rating) if min_rating else None
878
+ )
879
+
880
+ # Convert roadmap to markdown
881
+ roadmap_md = course_recommender.roadmap_to_markdown(roadmap, topic, skill_level)
882
+
883
+ # Format course recommendations as markdown
884
+ courses_md = format_courses_as_markdown(recommended_courses)
885
+
886
+ # Format teacher recommendations as markdown
887
+ teachers_md = teacher_recommender.teachers_to_markdown(recommended_teachers)
888
+
889
+ return roadmap_md, courses_md, teachers_md
890
+ except Exception as e:
891
+ return f"Error: {str(e)}", "Could not generate recommendations", "Could not generate teacher recommendations"
892
+
893
+ with gr.Blocks(title="Complete Learning Platform") as demo:
894
+ gr.Markdown("# 🎓 Complete Learning Platform")
895
+ gr.Markdown("Generate a personalized learning roadmap, course recommendations, and find expert teachers.")
896
+
897
+ with gr.Tabs():
898
+ with gr.TabItem("Learning Journey"):
899
+ with gr.Row():
900
+ with gr.Column():
901
+ topic_input = gr.Textbox(label="Topic you want to learn", placeholder="e.g. Python, Data Science, Machine Learning")
902
+ skill_level = gr.Dropdown(
903
+ ["Beginner", "Intermediate", "Advanced"],
904
+ label="Your current skill level"
905
+ )
906
+ goals_input = gr.Textbox(
907
+ label="Your learning goals (optional)",
908
+ placeholder="e.g. Career change, specific project, skill enhancement",
909
+ lines=3
910
+ )
911
+ use_ai = gr.Checkbox(label="Use AI-enhanced personalization")
912
+
913
+ with gr.Column():
914
+ location_input = gr.Textbox(label="Preferred location (optional)", placeholder="e.g. Bangalore, Remote")
915
+ mode_input = gr.Radio(["online", "in-person", "both"], label="Preferred teaching mode", value="both")
916
+ max_fees_input = gr.Number(label="Maximum budget for teacher fees (optional)")
917
+ min_exp_input = gr.Number(label="Minimum years of experience (optional)", precision=0)
918
+ min_rating_input = gr.Slider(minimum=1, maximum=5, value=3, step=0.5, label="Minimum teacher rating")
919
+
920
+ generate_btn = gr.Button("Generate Complete Learning Plan")
921
+
922
+ with gr.TabItem("Results"):
923
+ roadmap_output = gr.Markdown(label="Your Personalized Learning Roadmap")
924
+ courses_output = gr.Markdown(label="Recommended Courses")
925
+ teachers_output = gr.Markdown(label="Recommended Teachers")
926
+
927
+ generate_btn.click(
928
+ recommend_all,
929
+ inputs=[topic_input, skill_level, goals_input, use_ai,
930
+ location_input, mode_input, max_fees_input, min_exp_input, min_rating_input],
931
+ outputs=[roadmap_output, courses_output, teachers_output]
932
+ )
933
+
934
+ return demo
935
+
936
+ if __name__ == "__main__":
937
+ # Check if being run on Hugging Face Spaces
938
+ if os.getenv("SPACE_ID"):
939
+ # Initialize with the data files that should be included in the Space
940
+ course_recommender = load_courses("Coursera.csv")
941
+ teacher_recommender = load_teachers("teachers.json")
942
+
943
+ if course_recommender and teacher_recommender:
944
+ # Deploy as a Gradio app
945
+ app = create_gradio_interface(course_recommender, teacher_recommender)
946
+ app.launch()
947
+ else:
948
+ # Run as CLI application
949
+ main()
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ pandas
2
+ numpy
3
+ json5 # JSON is built-in, but some cases require json5
4
+ requests
5
+ python-dotenv
6
+ rich
7
+ tqdm
8
+ openai
9
+ gradio
10
+ huggingface_hub
teachers.json ADDED
The diff for this file is too large to render. See raw diff