shanmukavenkat commited on
Commit
afa9567
Β·
1 Parent(s): f81e375
Files changed (5) hide show
  1. .env +1 -0
  2. Coursera.csv +0 -0
  3. README.md +7 -5
  4. app.py +714 -0
  5. requirements.txt +10 -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
 
README.md CHANGED
@@ -1,12 +1,14 @@
1
  ---
2
- title: Ascend
3
- emoji: πŸ“ˆ
4
- colorFrom: yellow
5
- colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 5.23.2
8
  app_file: app.py
9
  pinned: false
 
 
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: CourseRecommendation
3
+ emoji: πŸ”₯
4
+ colorFrom: gray
5
+ colorTo: green
6
  sdk: gradio
7
+ sdk_version: 5.23.1
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
+ short_description: Course Recommendation & Roadmap generator
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,714 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 CourseRecommender:
23
+ def __init__(self, dataframe: pd.DataFrame):
24
+ """
25
+ Initialize the course recommender with course data
26
+ """
27
+ self.courses = dataframe.drop(columns=['Unnamed: 1', 'Unnamed: 5'], errors='ignore')
28
+ self._preprocess_data()
29
+ self.console = Console()
30
+
31
+ # Initialize OpenAI client
32
+ api_key = os.getenv("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")
33
+ self.ai_enabled = bool(api_key)
34
+ if self.ai_enabled:
35
+ self.openai_client = openai.OpenAI(api_key=api_key)
36
+ else:
37
+ self.console.print("[yellow]Warning: OpenAI API key not found. AI-enhanced features will be disabled.[/yellow]")
38
+
39
+ def _preprocess_data(self):
40
+ """
41
+ Preprocess the course data for better recommendations
42
+ """
43
+ # Convert text columns to lowercase
44
+ text_columns = ['Course Name', 'Description', 'Skills', 'Difficulty Level']
45
+ for col in text_columns:
46
+ if col in self.courses.columns:
47
+ self.courses[col] = self.courses[col].astype(str).str.lower()
48
+
49
+ # Handle numeric values
50
+ self.courses['Course Rating'] = pd.to_numeric(self.courses['Course Rating'], errors='coerce').fillna(0)
51
+ self.courses['keyword_match_score'] = 0
52
+
53
+ # Add course ID for easy reference
54
+ self.courses['Course ID'] = range(1, len(self.courses) + 1)
55
+
56
+ def recommend_courses(self, topic: Optional[str] = None, skill_level: Optional[str] = None,
57
+ top_n: int = 5, personalized: bool = False, user_goals: Optional[str] = None) -> pd.DataFrame:
58
+ """
59
+ Recommend courses based on topic, skill level, and optional user goals
60
+ """
61
+ filtered_courses = self.courses.copy()
62
+
63
+ # Show processing indicator
64
+ with self.console.status("[bold green]Finding the best courses for you...", spinner="dots"):
65
+ time.sleep(1) # Simulate processing time
66
+
67
+ # Filter by topic if provided
68
+ if topic:
69
+ topic = topic.lower()
70
+ # Calculate keyword match score
71
+ filtered_courses['keyword_match_score'] = (
72
+ filtered_courses['Course Name'].str.contains(topic).astype(int) * 3 +
73
+ filtered_courses['Description'].str.contains(topic).astype(int) * 2 +
74
+ filtered_courses['Skills'].str.contains(topic).astype(int)
75
+ )
76
+ filtered_courses = filtered_courses[filtered_courses['keyword_match_score'] > 0]
77
+
78
+ # Filter by skill level if provided
79
+ if skill_level:
80
+ skill_level = skill_level.lower()
81
+ difficulty_map = {
82
+ 'beginner': ['beginner', 'intro', 'basic', 'level 1', 'fundamentals'],
83
+ 'intermediate': ['intermediate', 'mid-level', 'level 2', 'advanced beginner'],
84
+ 'advanced': ['advanced', 'expert', 'professional', 'level 3', 'master']
85
+ }
86
+ filtered_courses = filtered_courses[
87
+ filtered_courses['Difficulty Level'].apply(
88
+ lambda x: any(diff in str(x) for diff in difficulty_map.get(skill_level, [skill_level]))
89
+ )
90
+ ]
91
+
92
+ # Add AI relevance scoring if enabled
93
+ filtered_courses['ai_relevance_score'] = 0
94
+ if personalized and user_goals and self.ai_enabled:
95
+ for idx, course in filtered_courses.iterrows():
96
+ relevance_score = self._get_ai_relevance_score(course, topic, user_goals)
97
+ filtered_courses.at[idx, 'ai_relevance_score'] = relevance_score
98
+
99
+ # Calculate final recommendation score
100
+ if not filtered_courses.empty:
101
+ filtered_courses['recommendation_score'] = (
102
+ filtered_courses['Course Rating'] * 0.4 +
103
+ filtered_courses['keyword_match_score'] * 0.3 +
104
+ filtered_courses['ai_relevance_score'] * 0.2 +
105
+ np.random.rand(len(filtered_courses)) * 0.1
106
+ )
107
+ filtered_courses = filtered_courses.sort_values('recommendation_score', ascending=False)
108
+
109
+ return filtered_courses.head(top_n)
110
+
111
+ def _get_ai_relevance_score(self, course: pd.Series, topic: str, user_goals: str) -> float:
112
+ """
113
+ Use AI to determine how relevant a course is to user's specific goals
114
+ """
115
+ if not self.ai_enabled:
116
+ return 0.5
117
+
118
+ try:
119
+ prompt = f"""
120
+ Rate how relevant this course is to a learner with these goals on a scale of 0-10:
121
+
122
+ Topic of interest: {topic}
123
+ User's learning goals: {user_goals}
124
+
125
+ Course details:
126
+ - Name: {course['Course Name']}
127
+ - Description: {course['Description']}
128
+ - Skills taught: {course['Skills']}
129
+ - Difficulty: {course['Difficulty Level']}
130
+
131
+ Return only a number from 0-10.
132
+ """
133
+
134
+ response = self.openai_client.chat.completions.create(
135
+ model="gpt-3.5-turbo",
136
+ messages=[
137
+ {"role": "system", "content": "You are an educational advisor helping match courses to learner goals."},
138
+ {"role": "user", "content": prompt}
139
+ ],
140
+ max_tokens=10,
141
+ temperature=0.3
142
+ )
143
+
144
+ try:
145
+ score = float(response.choices[0].message.content.strip())
146
+ return min(max(score, 0), 10) / 10 # Normalize to 0-1 range
147
+ except ValueError:
148
+ return 0.5 # Default value if parsing fails
149
+
150
+ except Exception as e:
151
+ self.console.print(f"[red]Error getting AI relevance score: {e}[/red]")
152
+ return 0.5
153
+
154
+ def generate_roadmap(self, topic: str, skill_level: Optional[str] = None,
155
+ user_goals: Optional[str] = None, detailed: bool = False) -> Dict:
156
+ """
157
+ Generate a personalized learning roadmap based on the topic and user goals
158
+ """
159
+ self.console.print(Panel(f"[bold cyan]Generating your personalized learning roadmap for [green]{topic}[/green]...[/bold cyan]"))
160
+
161
+ # Display a progress bar for visual effect
162
+ for _ in tqdm(range(5), desc="Processing roadmap data"):
163
+ time.sleep(0.3)
164
+
165
+ # Generate roadmap using AI if enabled and requested, otherwise use default
166
+ if detailed and self.ai_enabled and user_goals:
167
+ return self._generate_ai_roadmap(topic, skill_level, user_goals)
168
+ else:
169
+ return self._generate_default_roadmap(topic)
170
+
171
+ def _generate_ai_roadmap(self, topic: str, skill_level: str, user_goals: str) -> Dict:
172
+ """
173
+ Use AI to generate a personalized and detailed learning roadmap
174
+ """
175
+ try:
176
+ # Enhanced prompt with specific structure and guidance
177
+ prompt = f"""
178
+ Create a comprehensive learning roadmap for someone wanting to master {topic}.
179
+
180
+ Learner information:
181
+ - Current skill level: {skill_level}
182
+ - Learning goals: {user_goals}
183
+
184
+ The roadmap should be detailed, actionable, and specifically tailored to the learner's
185
+ skill level and goals. Provide a clear progression path that breaks down the journey
186
+ into logical stages with specific concepts to learn at each stage.
187
+
188
+ Format the response as a JSON object with exactly this structure:
189
+ {{
190
+ "learningPath": [
191
+ {{
192
+ "step": "Step name (be specific)",
193
+ "difficulty": "Beginner/Intermediate/Advanced",
194
+ "description": "Detailed description of this learning stage (2-3 sentences)",
195
+ "time_estimate": "Estimated completion time (weeks/months)",
196
+ "key_concepts": ["Specific concept 1", "Specific concept 2", "Specific concept 3"],
197
+ "milestones": ["Practical milestone 1", "Practical milestone 2"],
198
+ "practice_activities": ["Activity 1", "Activity 2"]
199
+ }},
200
+ // 3-5 steps total, progressing from fundamentals to mastery
201
+ ],
202
+ "projectSuggestions": [
203
+ {{
204
+ "name": "Project name (be specific to {topic})",
205
+ "description": "Detailed project description (2-3 sentences)",
206
+ "complexity": "Low/Medium/High",
207
+ "skills_practiced": ["Skill 1", "Skill 2", "Skill 3"],
208
+ "resources": ["Specific resource 1", "Specific resource 2"],
209
+ "estimated_time": "Project completion time estimate"
210
+ }},
211
+ // 3-4 projects of increasing complexity
212
+ ],
213
+ "resources": {{
214
+ "books": ["Specific book title 1", "Specific book title 2", "Specific book title 3"],
215
+ "online_courses": ["Specific course 1", "Specific course 2"],
216
+ "communities": ["Specific community 1", "Specific community 2"],
217
+ "tools": ["Specific tool 1", "Specific tool 2", "Specific tool 3"],
218
+ "practice_platforms": ["Specific platform 1", "Specific platform 2"]
219
+ }},
220
+ "career_insights": [
221
+ "Specific insight about {topic} career opportunities",
222
+ "Skill demand information",
223
+ "Industry application of {topic} skills"
224
+ ]
225
+ }}
226
+
227
+ Ensure all content is specific to {topic} (not generic) and appropriate for a {skill_level}
228
+ with these goals: {user_goals}. Focus on practical, actionable advice.
229
+ """
230
+
231
+ response = self.openai_client.chat.completions.create(
232
+ model="gpt-4o", # Using more capable model for better roadmaps
233
+ messages=[
234
+ {"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."},
235
+ {"role": "user", "content": prompt}
236
+ ],
237
+ max_tokens=2500,
238
+ temperature=0.5,
239
+ response_format={"type": "json_object"} # Enforce JSON response
240
+ )
241
+
242
+ try:
243
+ roadmap_text = response.choices[0].message.content
244
+ return json.loads(roadmap_text)
245
+ except json.JSONDecodeError as e:
246
+ self.console.print(f"[yellow]Warning: Could not parse AI response as JSON: {e}. Using default roadmap.[/yellow]")
247
+ return self._generate_default_roadmap(topic)
248
+
249
+ except Exception as e:
250
+ self.console.print(f"[red]Error generating AI roadmap: {e}[/red]")
251
+ return self._generate_default_roadmap(topic)
252
+
253
+ def _generate_default_roadmap(self, topic: str) -> Dict:
254
+ """
255
+ Generate a default roadmap when AI generation fails or is not available
256
+ """
257
+ return {
258
+ "learningPath": [
259
+ {
260
+ "step": f"Foundations of {topic}",
261
+ "difficulty": "Beginner",
262
+ "description": f"Build core knowledge and fundamental skills in {topic}. Focus on understanding basic principles and becoming familiar with essential tools.",
263
+ "time_estimate": "4-6 weeks",
264
+ "key_concepts": [f"{topic} basics", "Core principles", "Fundamental tools and techniques"],
265
+ "milestones": [f"Complete first {topic} exercise", f"Build simple {topic} project"],
266
+ "practice_activities": [f"Daily {topic} exercises", "Follow beginner tutorials"]
267
+ },
268
+ {
269
+ "step": f"{topic} Skill Development",
270
+ "difficulty": "Intermediate",
271
+ "description": f"Deepen understanding of {topic} and apply more advanced concepts. Focus on building practical skills through hands-on projects and implementation.",
272
+ "time_estimate": "8-12 weeks",
273
+ "key_concepts": [f"Advanced {topic} techniques", "Applied projects", "Specialized tools"],
274
+ "milestones": [f"Complete medium complexity {topic} project", "Solve real-world problems"],
275
+ "practice_activities": ["Implement sample projects", "Participate in forums/discussions"]
276
+ },
277
+ {
278
+ "step": f"{topic} Mastery & Specialization",
279
+ "difficulty": "Advanced",
280
+ "description": f"Develop expert-level skills in {topic} with focus on real-world application. Specialize in specific areas and build a professional portfolio.",
281
+ "time_estimate": "12-16 weeks",
282
+ "key_concepts": ["Industry best practices", "Complex problem-solving", "Portfolio development"],
283
+ "milestones": ["Create capstone project", "Contribute to community"],
284
+ "practice_activities": ["Build complex projects", "Mentor beginners"]
285
+ }
286
+ ],
287
+ "projectSuggestions": [
288
+ {
289
+ "name": f"Beginner Project: {topic} Fundamentals Application",
290
+ "description": f"Apply basic {topic} concepts in a simple project to practice fundamentals and gain confidence.",
291
+ "complexity": "Low",
292
+ "skills_practiced": [f"Basic {topic} principles", "Problem-solving", "Tool familiarity"],
293
+ "resources": ["Online tutorials", "Documentation", "Starter templates"],
294
+ "estimated_time": "1-2 weeks"
295
+ },
296
+ {
297
+ "name": f"Intermediate Project: Interactive {topic} Application",
298
+ "description": f"Create a more complex application using intermediate {topic} skills with greater functionality and sophistication.",
299
+ "complexity": "Medium",
300
+ "skills_practiced": [f"Intermediate {topic} techniques", "Code organization", "Testing"],
301
+ "resources": ["GitHub repositories", "Online coding platforms", "Community forums"],
302
+ "estimated_time": "3-4 weeks"
303
+ },
304
+ {
305
+ "name": f"Capstone Project: Advanced {topic} Implementation",
306
+ "description": f"Apply all learned skills in a comprehensive {topic} project that showcases mastery and solves a real-world problem.",
307
+ "complexity": "High",
308
+ "skills_practiced": [f"Advanced {topic} mastery", "System design", "Optimization"],
309
+ "resources": ["Industry case studies", "Research papers", "Expert communities"],
310
+ "estimated_time": "6-8 weeks"
311
+ }
312
+ ],
313
+ "resources": {
314
+ "books": [f"Introduction to {topic}", f"Advanced {topic} Techniques", f"Mastering {topic}"],
315
+ "online_courses": [f"{topic} for Beginners", f"Professional {topic} Masterclass"],
316
+ "communities": ["Stack Overflow", "Reddit", f"{topic} Discord Servers"],
317
+ "tools": [f"{topic} Development Environment", "Version Control", "Testing Frameworks"],
318
+ "practice_platforms": ["Codecademy", "Exercism", "LeetCode"]
319
+ },
320
+ "career_insights": [
321
+ f"Proficiency in {topic} is valuable for roles in software development, data science, and IT operations",
322
+ f"Entry-level {topic} positions typically require demonstrated project experience",
323
+ f"{topic} specialists can pursue careers in consulting, education, or product development"
324
+ ]
325
+ }
326
+
327
+ def get_course_details(self, course: pd.Series) -> Dict[str, str]:
328
+ """
329
+ Get detailed course information
330
+ """
331
+ return {
332
+ "name": course.get('Course Name', 'N/A'),
333
+ "difficulty": course.get('Difficulty Level', 'N/A'),
334
+ "rating": str(course.get('Course Rating', 'N/A')),
335
+ "url": course.get('Course URL', '#'),
336
+ "skills": course.get('Skills', 'N/A'),
337
+ "description": course.get('Description', 'No description available'),
338
+ "id": str(course.get('Course ID', '0'))
339
+ }
340
+
341
+ def display_roadmap(self, roadmap: Dict):
342
+ """
343
+ Display the learning roadmap in a beautiful format using rich
344
+ """
345
+ self.console.print("\n")
346
+ self.console.print(Panel("[bold cyan]YOUR PERSONALIZED LEARNING JOURNEY[/bold cyan]",
347
+ box=box.DOUBLE, expand=False))
348
+
349
+ # Create a tree for learning path
350
+ learning_tree = Tree("[bold yellow]Learning Path[/bold yellow]")
351
+ for stage in roadmap["learningPath"]:
352
+ stage_node = learning_tree.add(f"[bold green]{stage['step']}[/bold green] ({stage['difficulty']}) - {stage['time_estimate']}")
353
+ stage_node.add(f"[italic]{stage['description']}[/italic]")
354
+
355
+ concepts_node = stage_node.add("[bold blue]Key Concepts:[/bold blue]")
356
+ for concept in stage.get("key_concepts", []):
357
+ concepts_node.add(concept)
358
+
359
+ if "milestones" in stage:
360
+ milestones_node = stage_node.add("[bold magenta]Milestones:[/bold magenta]")
361
+ for milestone in stage["milestones"]:
362
+ milestones_node.add(milestone)
363
+
364
+ if "practice_activities" in stage:
365
+ activities_node = stage_node.add("[bold cyan]Practice Activities:[/bold cyan]")
366
+ for activity in stage["practice_activities"]:
367
+ activities_node.add(activity)
368
+
369
+ self.console.print(learning_tree)
370
+ self.console.print("\n")
371
+
372
+ # Project suggestions table
373
+ project_table = Table(title="Recommended Projects", box=box.ROUNDED)
374
+ project_table.add_column("Project Name", style="cyan", no_wrap=True)
375
+ project_table.add_column("Description", style="white")
376
+ project_table.add_column("Complexity", style="magenta")
377
+ project_table.add_column("Est. Time", style="yellow")
378
+
379
+ for project in roadmap["projectSuggestions"]:
380
+ project_table.add_row(
381
+ project["name"],
382
+ project["description"],
383
+ project["complexity"],
384
+ project.get("estimated_time", "N/A")
385
+ )
386
+
387
+ self.console.print(project_table)
388
+ self.console.print("\n")
389
+
390
+ # Resources panel
391
+ resources = roadmap.get("resources", {})
392
+ resources_text = ""
393
+
394
+ resource_categories = {
395
+ "books": "Recommended Books",
396
+ "online_courses": "Online Courses",
397
+ "communities": "Communities",
398
+ "tools": "Essential Tools",
399
+ "practice_platforms": "Practice Platforms"
400
+ }
401
+
402
+ for category, title in resource_categories.items():
403
+ if category in resources and resources[category]:
404
+ resources_text += f"[bold yellow]{title}:[/bold yellow]\n"
405
+ for item in resources[category]:
406
+ resources_text += f"β€’ {item}\n"
407
+ resources_text += "\n"
408
+
409
+ self.console.print(Panel(resources_text, title="[bold cyan]Learning Resources[/bold cyan]",
410
+ box=box.ROUNDED, expand=False))
411
+
412
+ # Career insights
413
+ if "career_insights" in roadmap and roadmap["career_insights"]:
414
+ career_text = "[bold yellow]Career Insights:[/bold yellow]\n"
415
+ for insight in roadmap["career_insights"]:
416
+ career_text += f"β€’ {insight}\n"
417
+
418
+ self.console.print(Panel(career_text, title="[bold cyan]Career Opportunities[/bold cyan]",
419
+ box=box.ROUNDED, expand=False))
420
+
421
+ def display_recommended_courses(self, courses: pd.DataFrame):
422
+ """
423
+ Display recommended courses in a beautiful format
424
+ """
425
+ if courses.empty:
426
+ self.console.print("[yellow]No courses match your criteria. Try broader search terms.[/yellow]")
427
+ return
428
+
429
+ table = Table(title="Recommended Courses", box=box.ROUNDED)
430
+ table.add_column("ID", style="dim")
431
+ table.add_column("Course Name", style="cyan")
432
+ table.add_column("Rating", style="yellow")
433
+ table.add_column("Difficulty", style="green")
434
+
435
+ for _, course in courses.iterrows():
436
+ table.add_row(
437
+ str(course.get('Course ID', 'N/A')),
438
+ course.get('Course Name', 'N/A').title(),
439
+ f"{course.get('Course Rating', 0):.1f} β˜…",
440
+ course.get('Difficulty Level', 'N/A').title()
441
+ )
442
+
443
+ self.console.print(table)
444
+ self.console.print("\n[dim]Use the course ID to get more details about a specific course.[/dim]")
445
+
446
+ def roadmap_to_markdown(self, roadmap: Dict, topic: str, skill_level: str) -> str:
447
+ """
448
+ Convert a roadmap to markdown format for export or display
449
+ """
450
+ markdown = f"# Personalized Learning Roadmap: {topic.title()}\n\n"
451
+ markdown += f"*Skill Level: {skill_level.title()}*\n\n"
452
+
453
+ # Learning Path
454
+ markdown += "## Learning Path\n\n"
455
+ for i, stage in enumerate(roadmap["learningPath"]):
456
+ markdown += f"### {i+1}. {stage['step']} ({stage['difficulty']}) - {stage['time_estimate']}\n\n"
457
+ markdown += f"{stage['description']}\n\n"
458
+
459
+ markdown += "**Key Concepts:**\n"
460
+ for concept in stage.get("key_concepts", []):
461
+ markdown += f"- {concept}\n"
462
+ markdown += "\n"
463
+
464
+ if "milestones" in stage:
465
+ markdown += "**Milestones:**\n"
466
+ for milestone in stage["milestones"]:
467
+ markdown += f"- {milestone}\n"
468
+ markdown += "\n"
469
+
470
+ if "practice_activities" in stage:
471
+ markdown += "**Practice Activities:**\n"
472
+ for activity in stage["practice_activities"]:
473
+ markdown += f"- {activity}\n"
474
+ markdown += "\n"
475
+
476
+ # Project Suggestions
477
+ markdown += "## Recommended Projects\n\n"
478
+ for i, project in enumerate(roadmap["projectSuggestions"]):
479
+ markdown += f"### {i+1}. {project['name']} ({project['complexity']})\n\n"
480
+ markdown += f"{project['description']}\n\n"
481
+
482
+ if "skills_practiced" in project:
483
+ markdown += "**Skills Practiced:**\n"
484
+ for skill in project["skills_practiced"]:
485
+ markdown += f"- {skill}\n"
486
+ markdown += "\n"
487
+
488
+ markdown += "**Resources:**\n"
489
+ for resource in project.get("resources", []):
490
+ markdown += f"- {resource}\n"
491
+ markdown += "\n"
492
+
493
+ if "estimated_time" in project:
494
+ markdown += f"**Estimated Time:** {project['estimated_time']}\n\n"
495
+
496
+ # Resources
497
+ markdown += "## Learning Resources\n\n"
498
+ resources = roadmap.get("resources", {})
499
+
500
+ resource_categories = {
501
+ "books": "Recommended Books",
502
+ "online_courses": "Online Courses",
503
+ "communities": "Communities",
504
+ "tools": "Essential Tools",
505
+ "practice_platforms": "Practice Platforms"
506
+ }
507
+
508
+ for category, title in resource_categories.items():
509
+ if category in resources and resources[category]:
510
+ markdown += f"### {title}\n"
511
+ for item in resources[category]:
512
+ markdown += f"- {item}\n"
513
+ markdown += "\n"
514
+
515
+ # Career Insights
516
+ if "career_insights" in roadmap and roadmap["career_insights"]:
517
+ markdown += "## Career Opportunities\n\n"
518
+ for insight in roadmap["career_insights"]:
519
+ markdown += f"- {insight}\n"
520
+
521
+ return markdown
522
+
523
+ def load_courses(file_path: str = 'Coursera.csv') -> Optional[CourseRecommender]:
524
+ """
525
+ Load courses from CSV and create a CourseRecommender instance
526
+ """
527
+ console = Console()
528
+
529
+ try:
530
+ with console.status("[bold green]Loading course data...", spinner="dots"):
531
+ df = pd.read_csv(file_path)
532
+ time.sleep(1) # Simulate loading time for visual effect
533
+ console.print(f"[green]Successfully loaded {len(df)} courses![/green]")
534
+ return CourseRecommender(df)
535
+ except FileNotFoundError:
536
+ console.print(f"[red]Error: {file_path} file not found.[/red]")
537
+ return None
538
+ except Exception as e:
539
+ console.print(f"[red]An error occurred while reading the CSV: {e}[/red]")
540
+ return None
541
+
542
+ def format_courses_as_markdown(recommended_courses: pd.DataFrame) -> str:
543
+ """
544
+ Format course recommendations as markdown - extracted common function
545
+ """
546
+ courses_md = "# Recommended Courses\n\n"
547
+ for i, (_, course) in enumerate(recommended_courses.iterrows()):
548
+ courses_md += f"## {i+1}. {course.get('Course Name', 'N/A').title()}\n\n"
549
+ courses_md += f"**Rating:** {course.get('Course Rating', 0):.1f} β˜…\n\n"
550
+ courses_md += f"**Difficulty:** {course.get('Difficulty Level', 'N/A').title()}\n\n"
551
+ courses_md += f"**Skills:** {course.get('Skills', 'N/A').title()}\n\n"
552
+ courses_md += f"**Description:**\n{course.get('Description', 'No description available')}\n\n"
553
+ if 'Course URL' in course and course['Course URL'] != '#':
554
+ courses_md += f"[View Course]({course['Course URL']})\n\n"
555
+ courses_md += "---\n\n"
556
+ return courses_md
557
+
558
+ def main():
559
+ console = Console()
560
+
561
+ # Print welcome message
562
+ console.print(Panel.fit(
563
+ "[bold cyan]Course Recommender & Learning Roadmap Generator[/bold cyan]\n"
564
+ "[yellow]Find the perfect courses and create your personalized learning journey[/yellow]",
565
+ box=box.DOUBLE))
566
+
567
+ recommender = load_courses()
568
+ if recommender:
569
+ console.print("[bold]Let's find the perfect learning path for you![/bold]\n")
570
+
571
+ topic = console.input("[bold green]Enter the topic you want to learn about: [/bold green]")
572
+ skill_level = console.input("[bold green]Enter your skill level (Beginner, Intermediate, Advanced): [/bold green]")
573
+
574
+ use_ai = False
575
+ user_goals = None
576
+
577
+ if recommender.ai_enabled:
578
+ use_ai = console.input("[bold green]Would you like AI-enhanced personalized recommendations? (y/n): [/bold green]").lower() == 'y'
579
+ if use_ai:
580
+ user_goals = console.input("[bold green]What are your learning goals or career objectives with this topic? [/bold green]")
581
+
582
+ # Generate and display roadmap
583
+ roadmap = recommender.generate_roadmap(topic, skill_level, user_goals, detailed=use_ai)
584
+ recommender.display_roadmap(roadmap)
585
+
586
+ # Option to export roadmap
587
+ export = console.input("\n[bold green]Would you like to export this roadmap to a markdown file? (y/n): [/bold green]").lower() == 'y'
588
+ if export:
589
+ markdown = recommender.roadmap_to_markdown(roadmap, topic, skill_level)
590
+ filename = f"{topic.lower().replace(' ', '_')}_roadmap.md"
591
+ with open(filename, "w") as f:
592
+ f.write(markdown)
593
+ console.print(f"[green]Roadmap exported to {filename}[/green]")
594
+
595
+ console.print("\n[bold]Press Enter to see recommended courses...[/bold]")
596
+ input()
597
+
598
+ # Get and display recommended courses
599
+ recommended_courses = recommender.recommend_courses(topic, skill_level, personalized=use_ai, user_goals=user_goals)
600
+ recommender.display_recommended_courses(recommended_courses)
601
+
602
+ # Allow user to view detailed course info
603
+ while True:
604
+ course_id = console.input("\n[bold green]Enter a course ID for more details (or 'q' to quit): [/bold green]")
605
+ if course_id.lower() == 'q':
606
+ break
607
+
608
+ try:
609
+ course_id = int(course_id)
610
+ course = recommended_courses[recommended_courses['Course ID'] == course_id]
611
+ if not course.empty:
612
+ details = recommender.get_course_details(course.iloc[0])
613
+
614
+ console.print(Panel(
615
+ f"[bold cyan]{details['name'].title()}[/bold cyan]\n\n"
616
+ f"[yellow]Rating:[/yellow] {details['rating']} β˜…\n"
617
+ f"[yellow]Difficulty:[/yellow] {details['difficulty'].title()}\n\n"
618
+ f"[yellow]Skills:[/yellow] {details['skills'].title()}\n\n"
619
+ f"[yellow]Description:[/yellow]\n{details['description']}\n\n"
620
+ f"[link={details['url']}]View Course[/link]",
621
+ title="Course Details", box=box.ROUNDED, width=100
622
+ ))
623
+ else:
624
+ console.print("[yellow]Course ID not found. Please try again.[/yellow]")
625
+ except ValueError:
626
+ console.print("[yellow]Please enter a valid course ID.[/yellow]")
627
+
628
+ console.print(Panel("[bold cyan]Thank you for using the Course Recommender![/bold cyan]", box=box.ROUNDED))
629
+
630
+ # Gradio interface for Hugging Face deployment
631
+ def create_gradio_interface(recommender: CourseRecommender):
632
+ """
633
+ Create a Gradio interface for the course recommender
634
+ """
635
+ def recommend_and_generate(topic, skill_level, goals, use_ai):
636
+ try:
637
+ # Generate roadmap
638
+ roadmap = recommender.generate_roadmap(
639
+ topic=topic,
640
+ skill_level=skill_level,
641
+ user_goals=goals if goals else None,
642
+ detailed=use_ai
643
+ )
644
+
645
+ # Get course recommendations
646
+ recommended_courses = recommender.recommend_courses(
647
+ topic=topic,
648
+ skill_level=skill_level,
649
+ personalized=use_ai,
650
+ user_goals=goals if goals else None
651
+ )
652
+
653
+ # Convert roadmap to markdown
654
+ roadmap_md = recommender.roadmap_to_markdown(roadmap, topic, skill_level)
655
+
656
+ # Format course recommendations as markdown
657
+ courses_md = format_courses_as_markdown(recommended_courses)
658
+
659
+ return roadmap_md, courses_md
660
+ except Exception as e:
661
+ return f"Error: {str(e)}", "Could not generate course recommendations"
662
+
663
+ with gr.Blocks(css="""
664
+ body, p, h1, h2, h3, h4, h5, h6, li, ul, a, span,em,strong, .gradio-container {
665
+ background-color: #f9f9f9 !important;
666
+ color: #000000 !important;
667
+ }
668
+ .gr-button, .gr-textbox, .gr-input, .gr-output, .gr-dropdown, .gr-checkbox, .gr-markdown, .gr-output, .gr-textbox-output {
669
+ color: #000000 !important;
670
+ }
671
+ """) as demo: # Custom CSS for background and text color
672
+ gr.Markdown("# πŸŽ“ Learning Roadmap & Course Recommender ASCEND ")
673
+ gr.Markdown("Generate a personalized learning roadmap and course recommendations.")
674
+
675
+ with gr.Row():
676
+ with gr.Column():
677
+ topic_input = gr.Textbox(label="Topic you want to learn", placeholder="e.g. Python, Data Science, Machine Learning")
678
+ skill_level = gr.Dropdown(
679
+ ["Beginner", "Intermediate", "Advanced"],
680
+ label="Your current skill level"
681
+ )
682
+ goals_input = gr.Textbox(
683
+ label="Your learning goals (optional)",
684
+ placeholder="e.g. Career change, specific project, skill enhancement",
685
+ lines=3
686
+ )
687
+ use_ai = gr.Checkbox(label="Use AI-enhanced personalization")
688
+
689
+ generate_btn = gr.Button("Generate Roadmap & Recommendations")
690
+
691
+ with gr.Column():
692
+ roadmap_output = gr.Markdown(label="Your Personalized Learning Roadmap")
693
+ courses_output = gr.Markdown(label="Recommended Courses")
694
+
695
+ generate_btn.click(
696
+ recommend_and_generate,
697
+ inputs=[topic_input, skill_level, goals_input, use_ai],
698
+ outputs=[roadmap_output, courses_output]
699
+ )
700
+
701
+ return demo
702
+
703
+ if __name__ == "__main__":
704
+ # Check if being run on Hugging Face Spaces
705
+ if os.getenv("SPACE_ID"):
706
+ # Initialize with the CSV file that should be included in the Space
707
+ recommender = load_courses("Coursera.csv")
708
+ if recommender:
709
+ # Deploy as a Gradio app
710
+ app = create_gradio_interface(recommender)
711
+ app.launch()
712
+ else:
713
+ # Run as CLI application
714
+ 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