chatbot2 / app.py
markobinario's picture
Update app.py
81da528 verified
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
)