Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| from course_recommender import CourseRecommender | |
| from database_connection import DatabaseConnection | |
| import os | |
| # Global variables to store current recommendations | |
| current_recommendations = [] | |
| current_user_input = {} | |
| # Initialize components with error handling | |
| recommender = None | |
| db_connection = None | |
| def initialize_components(): | |
| """Initialize the recommender system and database connection with error handling""" | |
| global recommender, db_connection | |
| try: | |
| if recommender is None: | |
| recommender = CourseRecommender() | |
| print("β CourseRecommender initialized") | |
| except Exception as e: | |
| print(f"β οΈ Warning: Could not initialize CourseRecommender: {e}") | |
| # Create a minimal fallback | |
| recommender = None | |
| try: | |
| if db_connection is None: | |
| db_connection = DatabaseConnection() | |
| print("β DatabaseConnection initialized") | |
| except Exception as e: | |
| print(f"β οΈ Warning: Could not initialize DatabaseConnection: {e}") | |
| # Create a minimal fallback | |
| db_connection = None | |
| # Initialize components | |
| initialize_components() | |
| def get_course_recommendations(stanine, gwa, strand, hobbies): | |
| """Get course recommendations based on user input""" | |
| global current_recommendations, current_user_input, recommender | |
| # Check if recommender is initialized | |
| if recommender is None: | |
| return "β System not properly initialized. Please try again.", "", "", "", "", "" | |
| # Validate inputs | |
| if not stanine or not gwa or not strand or not hobbies: | |
| return "Please fill in all fields", "", "", "", "", "" | |
| try: | |
| stanine = int(stanine) | |
| gwa = float(gwa) | |
| if stanine < 1 or stanine > 9: | |
| return "Stanine must be between 1-9", "", "", "", "", "" | |
| if gwa < 75 or gwa > 100: | |
| return "GWA must be between 75-100", "", "", "", "", "" | |
| # Normalize strand to uppercase for case-insensitive matching | |
| strand = strand.upper() | |
| if strand not in ["STEM", "ABM", "HUMSS", "GAS", "TVL"]: | |
| return "Strand must be one of: STEM, ABM, HUMSS, GAS, TVL", "", "", "", "", "" | |
| # Store current user input | |
| current_user_input = { | |
| 'stanine': stanine, | |
| 'gwa': gwa, | |
| 'strand': strand, | |
| 'hobbies': hobbies | |
| } | |
| # Get recommendations | |
| recommendations = recommender.predict_course(stanine, gwa, strand, hobbies) | |
| current_recommendations = recommendations | |
| # Format top 3 recommendations | |
| if len(recommendations) >= 3: | |
| course1 = f"{recommendations[0][0]} (Confidence: {recommendations[0][1]*100:.1f}%)" | |
| course2 = f"{recommendations[1][0]} (Confidence: {recommendations[1][1]*100:.1f}%)" | |
| course3 = f"{recommendations[2][0]} (Confidence: {recommendations[2][1]*100:.1f}%)" | |
| elif len(recommendations) == 2: | |
| course1 = f"{recommendations[0][0]} (Confidence: {recommendations[0][1]*100:.1f}%)" | |
| course2 = f"{recommendations[1][0]} (Confidence: {recommendations[1][1]*100:.1f}%)" | |
| course3 = "No third recommendation available" | |
| elif len(recommendations) == 1: | |
| course1 = f"{recommendations[0][0]} (Confidence: {recommendations[0][1]*100:.1f}%)" | |
| course2 = "No second recommendation available" | |
| course3 = "No third recommendation available" | |
| else: | |
| course1 = "No recommendations available" | |
| course2 = "" | |
| course3 = "" | |
| return course1, course2, course3, None, None, None | |
| except ValueError as e: | |
| return f"Invalid input: {str(e)}", "", "", None, None, None | |
| except Exception as e: | |
| return f"Error getting recommendations: {str(e)}", "", "", None, None, None | |
| def submit_all_ratings(course1_rating, course2_rating, course3_rating): | |
| """Submit ratings for all three recommendations""" | |
| global current_recommendations, current_user_input, recommender | |
| if recommender is None: | |
| return "β System not properly initialized. Please try again." | |
| if not current_recommendations or not current_user_input: | |
| return "No recommendations to rate. Please get recommendations first." | |
| try: | |
| results = [] | |
| ratings_submitted = 0 | |
| # Rate first recommendation | |
| if course1_rating and len(current_recommendations) >= 1: | |
| rating_value = "like" if course1_rating == "π Like" else "dislike" | |
| course = current_recommendations[0][0] | |
| success = recommender.add_feedback_with_learning( | |
| course=course, | |
| stanine=current_user_input['stanine'], | |
| gwa=current_user_input['gwa'], | |
| strand=current_user_input['strand'], | |
| rating=rating_value, | |
| hobbies=current_user_input['hobbies'] | |
| ) | |
| if success: | |
| results.append(f"β Rating for '{course}' recorded") | |
| ratings_submitted += 1 | |
| else: | |
| results.append(f"β Failed to record rating for '{course}'") | |
| # Rate second recommendation | |
| if course2_rating and len(current_recommendations) >= 2: | |
| rating_value = "like" if course2_rating == "π Like" else "dislike" | |
| course = current_recommendations[1][0] | |
| success = recommender.add_feedback_with_learning( | |
| course=course, | |
| stanine=current_user_input['stanine'], | |
| gwa=current_user_input['gwa'], | |
| strand=current_user_input['strand'], | |
| rating=rating_value, | |
| hobbies=current_user_input['hobbies'] | |
| ) | |
| if success: | |
| results.append(f"β Rating for '{course}' recorded") | |
| ratings_submitted += 1 | |
| else: | |
| results.append(f"β Failed to record rating for '{course}'") | |
| # Rate third recommendation | |
| if course3_rating and len(current_recommendations) >= 3: | |
| rating_value = "like" if course3_rating == "π Like" else "dislike" | |
| course = current_recommendations[2][0] | |
| success = recommender.add_feedback_with_learning( | |
| course=course, | |
| stanine=current_user_input['stanine'], | |
| gwa=current_user_input['gwa'], | |
| strand=current_user_input['strand'], | |
| rating=rating_value, | |
| hobbies=current_user_input['hobbies'] | |
| ) | |
| if success: | |
| results.append(f"β Rating for '{course}' recorded") | |
| ratings_submitted += 1 | |
| else: | |
| results.append(f"β Failed to record rating for '{course}'") | |
| if ratings_submitted > 0: | |
| return f"Thank you! {ratings_submitted} rating(s) submitted successfully.\n\n" + "\n".join(results) | |
| else: | |
| return "Please select at least one rating before submitting." | |
| except Exception as e: | |
| return f"Error recording feedback: {str(e)}" | |
| def train_model(): | |
| """Train the model with current data""" | |
| global recommender | |
| if recommender is None: | |
| return "β System not properly initialized. Please try again." | |
| try: | |
| accuracy = recommender.train_model(use_database=True) | |
| return f"β Model trained successfully! Accuracy: {accuracy:.3f}" | |
| except Exception as e: | |
| return f"β Error training model: {str(e)}" | |
| def get_available_courses_info(): | |
| """Get information about available courses from database""" | |
| global db_connection | |
| if db_connection is None: | |
| return "β Database connection not available. Please try again." | |
| try: | |
| courses = db_connection.get_available_courses() | |
| if courses: | |
| 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 "") | |
| else: | |
| return "π No courses found in database. Please check the /courses endpoint." | |
| except Exception as e: | |
| return f"β Error fetching courses: {str(e)}" | |
| # Create Gradio interface | |
| def create_interface(): | |
| with gr.Blocks(title="Course AI Recommender", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown(""" | |
| # π Course AI Machine Learning Recommender | |
| Get personalized course recommendations based on your academic profile and interests! | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Your Profile") | |
| stanine_input = gr.Textbox( | |
| label="Stanine Score (1-9)", | |
| placeholder="Enter your stanine score (1-9)", | |
| info="Your stanine score from standardized tests" | |
| ) | |
| gwa_input = gr.Textbox( | |
| label="GWA (75-100)", | |
| placeholder="Enter your GWA (75-100)", | |
| info="Your Grade Weighted Average" | |
| ) | |
| strand_input = gr.Dropdown( | |
| choices=["STEM", "ABM", "HUMSS", "GAS", "TVL"], | |
| value="STEM", | |
| label="Academic Strand", | |
| info="Your current academic strand" | |
| ) | |
| hobbies_input = gr.Textbox( | |
| label="Hobbies & Interests", | |
| placeholder="e.g., Programming, Reading, Sports, Music", | |
| info="List your hobbies and interests (comma-separated)" | |
| ) | |
| get_recommendations_btn = gr.Button("π― Get Recommendations", variant="primary") | |
| train_model_btn = gr.Button("π€ Train Model", variant="secondary") | |
| show_courses_btn = gr.Button("π Show Available Courses", variant="secondary") | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Top 3 Course Recommendations") | |
| # Display top 3 recommendations | |
| course1_output = gr.Textbox( | |
| label="1st Recommendation", | |
| interactive=False | |
| ) | |
| course1_rating = gr.Radio( | |
| choices=["π Like", "π Dislike"], | |
| label="Rate 1st Recommendation", | |
| interactive=True | |
| ) | |
| course2_output = gr.Textbox( | |
| label="2nd Recommendation", | |
| interactive=False | |
| ) | |
| course2_rating = gr.Radio( | |
| choices=["π Like", "π Dislike"], | |
| label="Rate 2nd Recommendation", | |
| interactive=True | |
| ) | |
| course3_output = gr.Textbox( | |
| label="3rd Recommendation", | |
| interactive=False | |
| ) | |
| course3_rating = gr.Radio( | |
| choices=["π Like", "π Dislike"], | |
| label="Rate 3rd Recommendation", | |
| interactive=True | |
| ) | |
| submit_ratings_btn = gr.Button("Submit All Ratings", variant="primary") | |
| rating_feedback = gr.Textbox( | |
| label="Rating Feedback", | |
| interactive=False | |
| ) | |
| courses_info = gr.Textbox( | |
| label="Available Courses", | |
| lines=8, | |
| interactive=False | |
| ) | |
| # Event handlers | |
| get_recommendations_btn.click( | |
| fn=get_course_recommendations, | |
| inputs=[stanine_input, gwa_input, strand_input, hobbies_input], | |
| outputs=[course1_output, course2_output, course3_output, course1_rating, course2_rating, course3_rating] | |
| ) | |
| submit_ratings_btn.click( | |
| fn=submit_all_ratings, | |
| inputs=[course1_rating, course2_rating, course3_rating], | |
| outputs=[rating_feedback] | |
| ) | |
| train_model_btn.click( | |
| fn=train_model, | |
| outputs=[gr.Textbox(label="Training Status", interactive=False)] | |
| ) | |
| show_courses_btn.click( | |
| fn=get_available_courses_info, | |
| outputs=[courses_info] | |
| ) | |
| # Add some example inputs | |
| gr.Markdown(""" | |
| ### π‘ Example Inputs | |
| **For STEM students:** | |
| - Stanine: 7-9, GWA: 85-95, Strand: STEM, Hobbies: Programming, Mathematics, Science | |
| **For ABM students:** | |
| - Stanine: 6-8, GWA: 80-90, Strand: ABM, Hobbies: Business, Leadership, Economics | |
| **For HUMSS students:** | |
| - Stanine: 5-8, GWA: 78-88, Strand: HUMSS, Hobbies: Literature, History, Writing | |
| """) | |
| return demo | |
| # Initialize the interface | |
| if __name__ == "__main__": | |
| # Try to load existing model if recommender is available | |
| if recommender is not None: | |
| try: | |
| recommender.load_model() | |
| print("β Loaded existing model") | |
| except: | |
| print("β οΈ No existing model found. Training with basic data...") | |
| try: | |
| recommender.train_model(use_database=False) | |
| print("β Model trained with basic data") | |
| except Exception as e: | |
| print(f"β Error training model: {e}") | |
| else: | |
| print("β οΈ Recommender not initialized. App will run with limited functionality.") | |
| # Create and launch interface | |
| demo = create_interface() | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=True | |
| ) | |