markobinario commited on
Commit
dd55974
·
verified ·
1 Parent(s): 45331b5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -307
app.py CHANGED
@@ -1,322 +1,64 @@
1
- import gradio as gr
2
  import pandas as pd
3
  import numpy as np
4
- from course_recommender import CourseRecommender
5
  from database_connection import DatabaseConnection
6
- import os
7
 
8
- # Initialize the recommender system
9
- recommender = CourseRecommender()
10
- db_connection = DatabaseConnection()
11
-
12
- # Global variables to store current recommendations
13
- current_recommendations = []
14
- current_user_input = {}
15
-
16
- def get_course_recommendations(stanine, gwa, strand, hobbies):
17
- """Get course recommendations based on user input"""
18
- global current_recommendations, current_user_input
19
 
20
- # Validate inputs
21
- if not stanine or not gwa or not strand or not hobbies:
22
- return "Please fill in all fields", "", "", "", "", ""
23
 
24
- try:
25
- stanine = int(stanine)
26
- gwa = float(gwa)
27
-
28
- if stanine < 1 or stanine > 9:
29
- return "Stanine must be between 1-9", "", "", "", "", ""
30
-
31
- if gwa < 75 or gwa > 100:
32
- return "GWA must be between 75-100", "", "", "", "", ""
33
-
34
- # Normalize strand to uppercase for case-insensitive matching
35
- strand = strand.upper()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- if strand not in ["STEM", "ABM", "HUMSS", "GAS", "TVL"]:
38
- return "Strand must be one of: STEM, ABM, HUMSS, GAS, TVL", "", "", "", "", ""
39
 
40
- # Store current user input
41
- current_user_input = {
42
  'stanine': stanine,
43
  'gwa': gwa,
44
  'strand': strand,
45
- 'hobbies': hobbies
46
- }
47
-
48
- # Get recommendations
49
- recommendations = recommender.predict_course(stanine, gwa, strand, hobbies)
50
- current_recommendations = recommendations
51
-
52
- # Format top 3 recommendations
53
- if len(recommendations) >= 3:
54
- course1 = f"{recommendations[0][0]} (Confidence: {recommendations[0][1]*100:.1f}%)"
55
- course2 = f"{recommendations[1][0]} (Confidence: {recommendations[1][1]*100:.1f}%)"
56
- course3 = f"{recommendations[2][0]} (Confidence: {recommendations[2][1]*100:.1f}%)"
57
- elif len(recommendations) == 2:
58
- course1 = f"{recommendations[0][0]} (Confidence: {recommendations[0][1]*100:.1f}%)"
59
- course2 = f"{recommendations[1][0]} (Confidence: {recommendations[1][1]*100:.1f}%)"
60
- course3 = "No third recommendation available"
61
- elif len(recommendations) == 1:
62
- course1 = f"{recommendations[0][0]} (Confidence: {recommendations[0][1]*100:.1f}%)"
63
- course2 = "No second recommendation available"
64
- course3 = "No third recommendation available"
65
- else:
66
- course1 = "No recommendations available"
67
- course2 = ""
68
- course3 = ""
69
-
70
- return course1, course2, course3, None, None, None
71
-
72
- except ValueError as e:
73
- return f"Invalid input: {str(e)}", "", "", None, None, None
74
- except Exception as e:
75
- return f"Error getting recommendations: {str(e)}", "", "", None, None, None
76
-
77
- def submit_all_ratings(course1_rating, course2_rating, course3_rating):
78
- """Submit ratings for all three recommendations"""
79
- global current_recommendations, current_user_input
80
 
81
- if not current_recommendations or not current_user_input:
82
- return "No recommendations to rate. Please get recommendations first."
83
-
84
- try:
85
- results = []
86
- ratings_submitted = 0
87
-
88
- # Rate first recommendation
89
- if course1_rating and len(current_recommendations) >= 1:
90
- rating_value = "like" if course1_rating == "👍 Like" else "dislike"
91
- course = current_recommendations[0][0]
92
- success = recommender.add_feedback_with_learning(
93
- course=course,
94
- stanine=current_user_input['stanine'],
95
- gwa=current_user_input['gwa'],
96
- strand=current_user_input['strand'],
97
- rating=rating_value,
98
- hobbies=current_user_input['hobbies']
99
- )
100
- if success:
101
- results.append(f"✅ Rating for '{course}' recorded")
102
- ratings_submitted += 1
103
- else:
104
- results.append(f"❌ Failed to record rating for '{course}'")
105
-
106
- # Rate second recommendation
107
- if course2_rating and len(current_recommendations) >= 2:
108
- rating_value = "like" if course2_rating == "👍 Like" else "dislike"
109
- course = current_recommendations[1][0]
110
- success = recommender.add_feedback_with_learning(
111
- course=course,
112
- stanine=current_user_input['stanine'],
113
- gwa=current_user_input['gwa'],
114
- strand=current_user_input['strand'],
115
- rating=rating_value,
116
- hobbies=current_user_input['hobbies']
117
- )
118
- if success:
119
- results.append(f"✅ Rating for '{course}' recorded")
120
- ratings_submitted += 1
121
- else:
122
- results.append(f"❌ Failed to record rating for '{course}'")
123
-
124
- # Rate third recommendation
125
- if course3_rating and len(current_recommendations) >= 3:
126
- rating_value = "like" if course3_rating == "👍 Like" else "dislike"
127
- course = current_recommendations[2][0]
128
- success = recommender.add_feedback_with_learning(
129
- course=course,
130
- stanine=current_user_input['stanine'],
131
- gwa=current_user_input['gwa'],
132
- strand=current_user_input['strand'],
133
- rating=rating_value,
134
- hobbies=current_user_input['hobbies']
135
- )
136
- if success:
137
- results.append(f"✅ Rating for '{course}' recorded")
138
- ratings_submitted += 1
139
- else:
140
- results.append(f"❌ Failed to record rating for '{course}'")
141
-
142
- if ratings_submitted > 0:
143
- return f"Thank you! {ratings_submitted} rating(s) submitted successfully.\n\n" + "\n".join(results)
144
- else:
145
- return "Please select at least one rating before submitting."
146
-
147
- except Exception as e:
148
- return f"Error recording feedback: {str(e)}"
149
 
150
- def train_model():
151
- """Train the model with current data"""
152
- try:
153
- accuracy = recommender.train_model(use_database=True)
154
- return f" Model trained successfully! Accuracy: {accuracy:.3f}"
155
- except Exception as e:
156
- return f"❌ Error training model: {str(e)}"
157
 
158
- def get_available_courses_info():
159
- """Get information about available courses from database"""
160
- try:
161
- courses = db_connection.get_available_courses()
162
- if courses:
163
- return f"📚 Available courses in database: {len(courses)}\n\n" + "\n".join([f"• {course}" for course in courses[:10]]) + (f"\n... and {len(courses)-10} more" if len(courses) > 10 else "")
164
- else:
165
- return "📚 No courses found in database. Please check the /courses endpoint."
166
- except Exception as e:
167
- return f"❌ Error fetching courses: {str(e)}"
168
-
169
- # Create Gradio interface
170
- def create_interface():
171
- with gr.Blocks(title="Course AI Recommender", theme=gr.themes.Soft()) as demo:
172
- gr.Markdown("""
173
- # 🎓 Course AI Machine Learning Recommender
174
-
175
- Get personalized course recommendations based on your academic profile and interests!
176
- """)
177
-
178
- with gr.Row():
179
- with gr.Column(scale=1):
180
- gr.Markdown("### 📝 Your Profile")
181
-
182
- stanine_input = gr.Textbox(
183
- label="Stanine Score (1-9)",
184
- placeholder="Enter your stanine score (1-9)",
185
- info="Your stanine score from standardized tests"
186
- )
187
-
188
- gwa_input = gr.Textbox(
189
- label="GWA (75-100)",
190
- placeholder="Enter your GWA (75-100)",
191
- info="Your Grade Weighted Average"
192
- )
193
-
194
- strand_input = gr.Dropdown(
195
- choices=["STEM", "ABM", "HUMSS", "GAS", "TVL"],
196
- value="STEM",
197
- label="Academic Strand",
198
- info="Your current academic strand"
199
- )
200
-
201
- hobbies_input = gr.Textbox(
202
- label="Hobbies & Interests",
203
- placeholder="e.g., Programming, Reading, Sports, Music",
204
- info="List your hobbies and interests (comma-separated)"
205
- )
206
-
207
- get_recommendations_btn = gr.Button("🎯 Get Recommendations", variant="primary")
208
-
209
- train_model_btn = gr.Button("🤖 Train Model", variant="secondary")
210
-
211
- show_courses_btn = gr.Button("📚 Show Available Courses", variant="secondary")
212
-
213
- with gr.Column(scale=1):
214
- gr.Markdown("### 🎓 Top 3 Course Recommendations")
215
-
216
- # Display top 3 recommendations
217
- course1_output = gr.Textbox(
218
- label="1st Recommendation",
219
- interactive=False
220
- )
221
-
222
- course1_rating = gr.Radio(
223
- choices=["👍 Like", "👎 Dislike"],
224
- label="Rate 1st Recommendation",
225
- interactive=True
226
- )
227
-
228
- course2_output = gr.Textbox(
229
- label="2nd Recommendation",
230
- interactive=False
231
- )
232
-
233
- course2_rating = gr.Radio(
234
- choices=["👍 Like", "👎 Dislike"],
235
- label="Rate 2nd Recommendation",
236
- interactive=True
237
- )
238
-
239
- course3_output = gr.Textbox(
240
- label="3rd Recommendation",
241
- interactive=False
242
- )
243
-
244
- course3_rating = gr.Radio(
245
- choices=["👍 Like", "👎 Dislike"],
246
- label="Rate 3rd Recommendation",
247
- interactive=True
248
- )
249
-
250
- submit_ratings_btn = gr.Button("Submit All Ratings", variant="primary")
251
-
252
- rating_feedback = gr.Textbox(
253
- label="Rating Feedback",
254
- interactive=False
255
- )
256
-
257
- courses_info = gr.Textbox(
258
- label="Available Courses",
259
- lines=8,
260
- interactive=False
261
- )
262
-
263
- # Event handlers
264
- get_recommendations_btn.click(
265
- fn=get_course_recommendations,
266
- inputs=[stanine_input, gwa_input, strand_input, hobbies_input],
267
- outputs=[course1_output, course2_output, course3_output, course1_rating, course2_rating, course3_rating]
268
- )
269
-
270
- submit_ratings_btn.click(
271
- fn=submit_all_ratings,
272
- inputs=[course1_rating, course2_rating, course3_rating],
273
- outputs=[rating_feedback]
274
- )
275
-
276
- train_model_btn.click(
277
- fn=train_model,
278
- outputs=[gr.Textbox(label="Training Status", interactive=False)]
279
- )
280
-
281
- show_courses_btn.click(
282
- fn=get_available_courses_info,
283
- outputs=[courses_info]
284
- )
285
-
286
- # Add some example inputs
287
- gr.Markdown("""
288
- ### 💡 Example Inputs
289
-
290
- **For STEM students:**
291
- - Stanine: 7-9, GWA: 85-95, Strand: STEM, Hobbies: Programming, Mathematics, Science
292
-
293
- **For ABM students:**
294
- - Stanine: 6-8, GWA: 80-90, Strand: ABM, Hobbies: Business, Leadership, Economics
295
-
296
- **For HUMSS students:**
297
- - Stanine: 5-8, GWA: 78-88, Strand: HUMSS, Hobbies: Literature, History, Writing
298
- """)
299
-
300
- return demo
301
-
302
- # Initialize the interface
303
  if __name__ == "__main__":
304
- # Try to load existing model
305
- try:
306
- recommender.load_model()
307
- print("✅ Loaded existing model")
308
- except:
309
- print("⚠️ No existing model found. Training with basic data...")
310
- try:
311
- recommender.train_model(use_database=False)
312
- print("✅ Model trained with basic data")
313
- except Exception as e:
314
- print(f"❌ Error training model: {e}")
315
-
316
- # Create and launch interface
317
- demo = create_interface()
318
- demo.launch(
319
- server_name="0.0.0.0",
320
- server_port=7860,
321
- share=True
322
- )
 
 
1
  import pandas as pd
2
  import numpy as np
 
3
  from database_connection import DatabaseConnection
 
4
 
5
+ def create_basic_training_data():
6
+ """Create basic training data for the course recommender - DEPRECATED"""
7
+ print("WARNING: Basic training data is deprecated. Use student feedback data instead.")
8
+ raise ValueError("Basic training data is no longer used. Please use student feedback data from /student_feedback_counts endpoint.")
 
 
 
 
 
 
 
9
 
10
+ # Define strands
11
+ strands = ["STEM", "ABM", "HUMSS", "GAS", "TVL"]
 
12
 
13
+ # Define common hobbies
14
+ hobbies_list = [
15
+ "Programming", "Reading", "Sports", "Music", "Art", "Gaming",
16
+ "Photography", "Writing", "Dancing", "Cooking", "Traveling",
17
+ "Mathematics", "Science", "History", "Literature", "Technology"
18
+ ]
19
+
20
+ # Generate synthetic data
21
+ np.random.seed(42) # For reproducible results
22
+ n_samples = 1000
23
+
24
+ data = []
25
+ for _ in range(n_samples):
26
+ # Generate random but realistic data
27
+ stanine = np.random.randint(1, 10)
28
+ gwa = np.random.uniform(75, 100) # GWA between 75-100
29
+ strand = np.random.choice(strands)
30
+ course = np.random.choice(courses)
31
+ hobbies = np.random.choice(hobbies_list, size=np.random.randint(1, 4), replace=False)
32
+ hobbies_str = ", ".join(hobbies)
33
+
34
+ # Generate rating based on some logic
35
+ if stanine >= 7 and gwa >= 85:
36
+ rating = np.random.choice([4, 5], p=[0.3, 0.7])
37
+ elif stanine >= 5 and gwa >= 80:
38
+ rating = np.random.choice([3, 4, 5], p=[0.2, 0.5, 0.3])
39
+ else:
40
+ rating = np.random.choice([1, 2, 3, 4], p=[0.1, 0.3, 0.4, 0.2])
41
 
42
+ count = np.random.randint(1, 10)
 
43
 
44
+ data.append({
45
+ 'course': course,
46
  'stanine': stanine,
47
  'gwa': gwa,
48
  'strand': strand,
49
+ 'rating': rating,
50
+ 'hobbies': hobbies_str,
51
+ 'count': count
52
+ })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
+ return pd.DataFrame(data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
+ def save_basic_data():
57
+ """Save basic training data to CSV"""
58
+ df = create_basic_training_data()
59
+ df.to_csv('basic_training_data.csv', index=False)
60
+ print(f"Basic training data saved with {len(df)} samples")
61
+ return df
 
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  if __name__ == "__main__":
64
+ save_basic_data()