Spaces:
Sleeping
Sleeping
| import requests | |
| import json | |
| from sentence_transformers import SentenceTransformer | |
| import numpy as np | |
| from sklearn.metrics.pairwise import cosine_similarity | |
| from recommender import CourseRecommender | |
| class Chatbot: | |
| def __init__(self): | |
| self.qa_pairs = [] | |
| self.question_embeddings = [] | |
| self.model = SentenceTransformer('all-MiniLM-L6-v2') | |
| self.database_url = "https://database-46m3.onrender.com" | |
| self.recommender = CourseRecommender() | |
| self.load_qa_data() | |
| def load_qa_data(self): | |
| """Load Q&A pairs from the faqs table in the database""" | |
| try: | |
| # Connect to the faqs table endpoint | |
| faqs_url = f"{self.database_url}/faqs" | |
| response = requests.get(faqs_url) | |
| if response.status_code == 200: | |
| data = response.json() | |
| # Assuming the database returns a list of FAQ objects | |
| if isinstance(data, list): | |
| self.qa_pairs = data | |
| else: | |
| # If it's a single object, wrap it in a list | |
| self.qa_pairs = [data] | |
| # Generate embeddings for all questions | |
| questions = [item.get('question', '') for item in self.qa_pairs] | |
| self.question_embeddings = self.model.encode(questions) | |
| print(f"Loaded {len(self.qa_pairs)} FAQ pairs from database") | |
| else: | |
| print(f"Failed to load data from faqs table. Status code: {response.status_code}") | |
| self._load_fallback_data() | |
| except Exception as e: | |
| print(f"Error loading FAQ data: {str(e)}") | |
| self._load_fallback_data() | |
| def _load_fallback_data(self): | |
| """Load fallback data if database is unavailable""" | |
| self.qa_pairs = [ | |
| {"question": "What is artificial intelligence?", "answer": "Artificial Intelligence (AI) is a branch of computer science that aims to create machines capable of intelligent behavior."}, | |
| {"question": "How does machine learning work?", "answer": "Machine learning is a subset of AI that enables computers to learn and improve from experience without being explicitly programmed."}, | |
| {"question": "What is deep learning?", "answer": "Deep learning is a subset of machine learning that uses neural networks with multiple layers to model and understand complex patterns in data."}, | |
| {"question": "What is natural language processing?", "answer": "Natural Language Processing (NLP) is a field of AI that focuses on the interaction between computers and humans through natural language."}, | |
| {"question": "What is a neural network?", "answer": "A neural network is a computing system inspired by biological neural networks that constitute animal brains. It consists of interconnected nodes (neurons) that process information."} | |
| ] | |
| questions = [item['question'] for item in self.qa_pairs] | |
| self.question_embeddings = self.model.encode(questions) | |
| print("Loaded fallback Q&A data") | |
| def find_best_match(self, user_input, threshold=0.7): | |
| """Find the best matching question using semantic similarity""" | |
| if not self.qa_pairs: | |
| return None, 0 | |
| # Encode the user input | |
| user_embedding = self.model.encode([user_input]) | |
| # Calculate cosine similarity with all questions | |
| similarities = cosine_similarity(user_embedding, self.question_embeddings)[0] | |
| # Find the best match | |
| best_match_idx = np.argmax(similarities) | |
| best_similarity = similarities[best_match_idx] | |
| if best_similarity >= threshold: | |
| return self.qa_pairs[best_match_idx], best_similarity | |
| else: | |
| return None, best_similarity | |
| def get_response(self, user_input): | |
| """Get response for user input""" | |
| if not user_input.strip(): | |
| return "Please enter a message." | |
| best_match, similarity = self.find_best_match(user_input) | |
| if best_match: | |
| return { | |
| 'answer': best_match.get('answer', 'No answer found'), | |
| 'confidence': float(similarity), | |
| 'matched_question': best_match.get('question', ''), | |
| 'status': 'success' | |
| } | |
| else: | |
| return { | |
| 'answer': "I'm sorry, I couldn't find a relevant answer to your question. Could you please rephrase it or ask something else?", | |
| 'confidence': float(similarity), | |
| 'matched_question': '', | |
| 'status': 'no_match' | |
| } | |
| def get_qa_count(self): | |
| """Get the number of loaded Q&A pairs""" | |
| return len(self.qa_pairs) | |
| def get_course_recommendations(self, stanine, gwa, strand, hobbies): | |
| """Get course recommendations using the recommender system""" | |
| try: | |
| # Validate inputs | |
| stanine = int(stanine) if isinstance(stanine, str) else stanine | |
| gwa = float(gwa) if isinstance(gwa, str) else gwa | |
| if not (1 <= stanine <= 9): | |
| return "β Stanine score must be between 1 and 9" | |
| if not (75 <= gwa <= 100): | |
| return "β GWA must be between 75 and 100" | |
| if not strand: | |
| return "β Please select a strand" | |
| if not hobbies or not str(hobbies).strip(): | |
| return "β Please enter your hobbies/interests" | |
| # Get recommendations | |
| recommendations = self.recommender.recommend_courses( | |
| stanine=stanine, | |
| gwa=gwa, | |
| strand=strand, | |
| hobbies=str(hobbies) | |
| ) | |
| if not recommendations: | |
| return "No recommendations available at the moment." | |
| # Format response (without confidence scores) | |
| response = f"## π― Course Recommendations for You\n\n" | |
| response += f"**Profile:** Stanine {stanine}, GWA {gwa}, {strand} Strand\n" | |
| response += f"**Interests:** {hobbies}\n\n" | |
| for i, rec in enumerate(recommendations, 1): | |
| response += f"### {i}. {rec['code']} - {rec['name']}\n\n" | |
| return response | |
| except Exception as e: | |
| return f"β Error getting recommendations: {str(e)}" | |