markobinario commited on
Commit
27e2f3a
Β·
verified Β·
1 Parent(s): f8ea354

Update chatbot.py

Browse files
Files changed (1) hide show
  1. chatbot.py +96 -21
chatbot.py CHANGED
@@ -9,11 +9,60 @@ class Chatbot:
9
  def __init__(self):
10
  self.qa_pairs = []
11
  self.question_embeddings = []
12
- self.model = SentenceTransformer('all-MiniLM-L6-v2')
13
  self.database_url = "https://database-46m3.onrender.com"
14
- self.recommender = CourseRecommender()
 
 
15
  self.load_qa_data()
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  def load_qa_data(self):
18
  """Load Q&A pairs from the faqs table in the database"""
19
  try:
@@ -29,10 +78,13 @@ class Chatbot:
29
  # If it's a single object, wrap it in a list
30
  self.qa_pairs = [data]
31
 
32
- # Generate embeddings for all questions
33
  questions = [item.get('question', '') for item in self.qa_pairs]
34
- self.question_embeddings = self.model.encode(questions)
35
- print(f"Loaded {len(self.qa_pairs)} FAQ pairs from database")
 
 
 
36
  else:
37
  print(f"Failed to load data from faqs table. Status code: {response.status_code}")
38
  self._load_fallback_data()
@@ -50,28 +102,48 @@ class Chatbot:
50
  {"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."}
51
  ]
52
  questions = [item['question'] for item in self.qa_pairs]
53
- self.question_embeddings = self.model.encode(questions)
54
- print("Loaded fallback Q&A data")
 
 
 
55
 
56
  def find_best_match(self, user_input, threshold=0.7):
57
- """Find the best matching question using semantic similarity"""
58
  if not self.qa_pairs:
59
  return None, 0
60
 
61
- # Encode the user input
62
- user_embedding = self.model.encode([user_input])
63
-
64
- # Calculate cosine similarity with all questions
65
- similarities = cosine_similarity(user_embedding, self.question_embeddings)[0]
66
-
67
- # Find the best match
68
- best_match_idx = np.argmax(similarities)
69
- best_similarity = similarities[best_match_idx]
70
-
71
- if best_similarity >= threshold:
72
- return self.qa_pairs[best_match_idx], best_similarity
73
  else:
74
- return None, best_similarity
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
  def get_response(self, user_input):
77
  """Get response for user input"""
@@ -115,6 +187,9 @@ class Chatbot:
115
  if not hobbies or not str(hobbies).strip():
116
  return "❌ Please enter your hobbies/interests"
117
 
 
 
 
118
  # Get recommendations
119
  recommendations = self.recommender.recommend_courses(
120
  stanine=stanine,
 
9
  def __init__(self):
10
  self.qa_pairs = []
11
  self.question_embeddings = []
12
+ self.model = None
13
  self.database_url = "https://database-46m3.onrender.com"
14
+ self.recommender = None
15
+ self.load_model()
16
+ self.load_recommender()
17
  self.load_qa_data()
18
 
19
+ def load_model(self):
20
+ """Load the sentence transformer model with error handling"""
21
+ import time
22
+ import os
23
+
24
+ # List of models to try in order of preference
25
+ models_to_try = [
26
+ 'all-MiniLM-L6-v2',
27
+ 'paraphrase-MiniLM-L6-v2',
28
+ 'all-MiniLM-L12-v2'
29
+ ]
30
+
31
+ for model_name in models_to_try:
32
+ try:
33
+ print(f"Loading sentence transformer model: {model_name}...")
34
+
35
+ # Try with cache directory first
36
+ cache_dir = os.path.join(os.getcwd(), 'model_cache')
37
+ os.makedirs(cache_dir, exist_ok=True)
38
+
39
+ self.model = SentenceTransformer(model_name, cache_folder=cache_dir)
40
+ print(f"βœ… Model {model_name} loaded successfully")
41
+ return
42
+
43
+ except Exception as e:
44
+ print(f"❌ Error loading {model_name}: {str(e)}")
45
+ continue
46
+
47
+ # If all models fail, try without cache
48
+ try:
49
+ print("Trying without cache directory...")
50
+ self.model = SentenceTransformer('all-MiniLM-L6-v2')
51
+ print("βœ… Model loaded successfully without cache")
52
+ except Exception as e:
53
+ print(f"❌ Final attempt failed: {str(e)}")
54
+ raise Exception("Could not load any sentence transformer model")
55
+
56
+ def load_recommender(self):
57
+ """Load the course recommender with error handling"""
58
+ try:
59
+ print("Loading course recommender...")
60
+ self.recommender = CourseRecommender()
61
+ print("βœ… Recommender loaded successfully")
62
+ except Exception as e:
63
+ print(f"❌ Error loading recommender: {str(e)}")
64
+ self.recommender = None
65
+
66
  def load_qa_data(self):
67
  """Load Q&A pairs from the faqs table in the database"""
68
  try:
 
78
  # If it's a single object, wrap it in a list
79
  self.qa_pairs = [data]
80
 
81
+ # Generate embeddings for all questions if model is available
82
  questions = [item.get('question', '') for item in self.qa_pairs]
83
+ if self.model is not None:
84
+ self.question_embeddings = self.model.encode(questions)
85
+ print(f"Loaded {len(self.qa_pairs)} FAQ pairs with embeddings from database")
86
+ else:
87
+ print(f"Loaded {len(self.qa_pairs)} FAQ pairs from database (using fallback matching)")
88
  else:
89
  print(f"Failed to load data from faqs table. Status code: {response.status_code}")
90
  self._load_fallback_data()
 
102
  {"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."}
103
  ]
104
  questions = [item['question'] for item in self.qa_pairs]
105
+ if self.model is not None:
106
+ self.question_embeddings = self.model.encode(questions)
107
+ print("Loaded fallback Q&A data with embeddings")
108
+ else:
109
+ print("Loaded fallback Q&A data (using fallback matching)")
110
 
111
  def find_best_match(self, user_input, threshold=0.7):
112
+ """Find the best matching question using semantic similarity or fallback text matching"""
113
  if not self.qa_pairs:
114
  return None, 0
115
 
116
+ if self.model is not None and len(self.question_embeddings) > 0:
117
+ # Use AI model for semantic matching
118
+ user_embedding = self.model.encode([user_input])
119
+ similarities = cosine_similarity(user_embedding, self.question_embeddings)[0]
120
+ best_match_idx = np.argmax(similarities)
121
+ best_similarity = similarities[best_match_idx]
122
+
123
+ if best_similarity >= threshold:
124
+ return self.qa_pairs[best_match_idx], best_similarity
125
+ else:
126
+ return None, best_similarity
 
127
  else:
128
+ # Fallback to simple text matching
129
+ user_input_lower = user_input.lower()
130
+ best_match = None
131
+ best_score = 0
132
+
133
+ for qa_pair in self.qa_pairs:
134
+ question = qa_pair.get('question', '').lower()
135
+ # Simple keyword matching
136
+ common_words = set(user_input_lower.split()) & set(question.split())
137
+ if common_words:
138
+ score = len(common_words) / max(len(user_input_lower.split()), len(question.split()))
139
+ if score > best_score and score >= 0.3: # Lower threshold for fallback
140
+ best_score = score
141
+ best_match = qa_pair
142
+
143
+ if best_match:
144
+ return best_match, best_score
145
+ else:
146
+ return None, 0
147
 
148
  def get_response(self, user_input):
149
  """Get response for user input"""
 
187
  if not hobbies or not str(hobbies).strip():
188
  return "❌ Please enter your hobbies/interests"
189
 
190
+ if self.recommender is None:
191
+ return "❌ Course recommendation system is not available at the moment. Please try again later."
192
+
193
  # Get recommendations
194
  recommendations = self.recommender.recommend_courses(
195
  stanine=stanine,