Rachel0619 commited on
Commit
ec3c776
·
1 Parent(s): d527b21

Fix HF Space deployment - lazy load chatbot

Browse files
Files changed (4) hide show
  1. Dockerfile +7 -1
  2. app.py +31 -8
  3. requirements.txt +6 -0
  4. templates/base.html +10 -3
Dockerfile CHANGED
@@ -2,6 +2,11 @@ FROM python:3.11-slim
2
 
3
  WORKDIR /app
4
 
 
 
 
 
 
5
  # Copy requirements and install dependencies
6
  COPY requirements.txt .
7
  RUN pip install --no-cache-dir -r requirements.txt
@@ -13,4 +18,5 @@ COPY . .
13
  EXPOSE 7860
14
 
15
  # Run the application with gunicorn
16
- CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--workers", "4", "--timeout", "120", "app:app"]
 
 
2
 
3
  WORKDIR /app
4
 
5
+ # Install system dependencies
6
+ RUN apt-get update && apt-get install -y \
7
+ build-essential \
8
+ && rm -rf /var/lib/apt/lists/*
9
+
10
  # Copy requirements and install dependencies
11
  COPY requirements.txt .
12
  RUN pip install --no-cache-dir -r requirements.txt
 
18
  EXPOSE 7860
19
 
20
  # Run the application with gunicorn
21
+ # Reduced workers to 2 and increased timeout for model loading
22
+ CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--workers", "2", "--timeout", "300", "--preload", "app:app"]
app.py CHANGED
@@ -10,7 +10,6 @@ load_dotenv()
10
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
11
  from recommendation_engine import RecommendationEngine
12
  from recommendation_explainer import RecommendationExplainer
13
- from rag import RAGChatbot
14
 
15
  app = Flask(__name__)
16
  app.secret_key = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-production')
@@ -21,14 +20,29 @@ recommendation_explainer = RecommendationExplainer()
21
 
22
  # Initialize RAG chatbot (lazy initialization on first request)
23
  rag_chatbot = None
 
 
24
 
25
  def get_chatbot():
26
  """Get or initialize the RAG chatbot"""
27
- global rag_chatbot
28
- if rag_chatbot is None:
 
 
 
 
 
 
29
  rag_chatbot = RAGChatbot()
30
  rag_chatbot.initialize()
31
- return rag_chatbot
 
 
 
 
 
 
 
32
 
33
  # Custom Jinja filter for simple markdown rendering
34
  import re
@@ -130,6 +144,13 @@ def chat():
130
 
131
  # Get chatbot and generate response
132
  chatbot = get_chatbot()
 
 
 
 
 
 
 
133
  response = chatbot.chat(query)
134
 
135
  return jsonify({
@@ -137,11 +158,13 @@ def chat():
137
  "status": "success"
138
  })
139
  except Exception as e:
140
- print(f"Error in chat endpoint: {e}")
 
 
141
  return jsonify({
142
- "error": "Sorry, I encountered an error processing your question.",
143
- "status": "error"
144
- }), 500
145
 
146
  if __name__ == '__main__':
147
  app.run(debug=True, host='0.0.0.0', port=5555)
 
10
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
11
  from recommendation_engine import RecommendationEngine
12
  from recommendation_explainer import RecommendationExplainer
 
13
 
14
  app = Flask(__name__)
15
  app.secret_key = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-production')
 
20
 
21
  # Initialize RAG chatbot (lazy initialization on first request)
22
  rag_chatbot = None
23
+ chatbot_initialized = False
24
+ chatbot_error = None
25
 
26
  def get_chatbot():
27
  """Get or initialize the RAG chatbot"""
28
+ global rag_chatbot, chatbot_initialized, chatbot_error
29
+
30
+ if chatbot_initialized:
31
+ return rag_chatbot
32
+
33
+ try:
34
+ print("🤖 Initializing RAG chatbot...")
35
+ from rag import RAGChatbot
36
  rag_chatbot = RAGChatbot()
37
  rag_chatbot.initialize()
38
+ chatbot_initialized = True
39
+ print("✅ RAG chatbot initialized successfully")
40
+ return rag_chatbot
41
+ except Exception as e:
42
+ chatbot_error = str(e)
43
+ chatbot_initialized = True # Mark as initialized to avoid retrying
44
+ print(f"❌ Failed to initialize chatbot: {e}")
45
+ return None
46
 
47
  # Custom Jinja filter for simple markdown rendering
48
  import re
 
144
 
145
  # Get chatbot and generate response
146
  chatbot = get_chatbot()
147
+
148
+ if chatbot is None:
149
+ return jsonify({
150
+ "response": "Sorry, the chatbot is currently unavailable. Please try again later or contact support.",
151
+ "status": "success"
152
+ })
153
+
154
  response = chatbot.chat(query)
155
 
156
  return jsonify({
 
158
  "status": "success"
159
  })
160
  except Exception as e:
161
+ print(f"❌ Error in chat endpoint: {e}")
162
+ import traceback
163
+ traceback.print_exc()
164
  return jsonify({
165
+ "response": "Sorry, I encountered an error processing your question. Please try again.",
166
+ "status": "success"
167
+ })
168
 
169
  if __name__ == '__main__':
170
  app.run(debug=True, host='0.0.0.0', port=5555)
requirements.txt CHANGED
@@ -9,3 +9,9 @@ pandas==2.3.0
9
  plotly==5.24.1
10
  openai>=1.0.0
11
  gunicorn==23.0.0
 
 
 
 
 
 
 
9
  plotly==5.24.1
10
  openai>=1.0.0
11
  gunicorn==23.0.0
12
+ requests>=2.32.0
13
+ python-frontmatter>=1.1.0
14
+ sentence-transformers>=2.2.0
15
+ tqdm>=4.65.0
16
+ numpy>=1.24.0
17
+ minsearch>=0.0.7
templates/base.html CHANGED
@@ -335,21 +335,28 @@
335
  headers: {
336
  'Content-Type': 'application/json',
337
  },
338
- body: JSON.stringify({ message: message })
 
339
  });
340
 
341
  const data = await response.json();
342
  removeTyping();
343
 
344
- if (data.status === 'success') {
345
  addMessage(data.response);
 
 
346
  } else {
347
  addMessage('Sorry, I encountered an error. Please try again.');
348
  }
349
  } catch (error) {
350
  console.error('Chat error:', error);
351
  removeTyping();
352
- addMessage('Sorry, I encountered an error. Please try again.');
 
 
 
 
353
  } finally {
354
  // Re-enable input
355
  chatbotInput.disabled = false;
 
335
  headers: {
336
  'Content-Type': 'application/json',
337
  },
338
+ body: JSON.stringify({ message: message }),
339
+ signal: AbortSignal.timeout(60000) // 60 second timeout
340
  });
341
 
342
  const data = await response.json();
343
  removeTyping();
344
 
345
+ if (data.status === 'success' && data.response) {
346
  addMessage(data.response);
347
+ } else if (data.error) {
348
+ addMessage(data.error);
349
  } else {
350
  addMessage('Sorry, I encountered an error. Please try again.');
351
  }
352
  } catch (error) {
353
  console.error('Chat error:', error);
354
  removeTyping();
355
+ if (error.name === 'TimeoutError') {
356
+ addMessage('Sorry, the request timed out. The chatbot may be initializing. Please try again in a moment.');
357
+ } else {
358
+ addMessage('Sorry, I encountered an error. Please try again later.');
359
+ }
360
  } finally {
361
  // Re-enable input
362
  chatbotInput.disabled = false;