Said Lfagrouche commited on
Commit
c13c6ef
·
1 Parent(s): ed78072

Fix model artifacts copying in Dockerfile and add fallback functionality for missing models

Browse files
Files changed (2) hide show
  1. Dockerfile +3 -0
  2. api_mental_health.py +99 -43
Dockerfile CHANGED
@@ -31,6 +31,9 @@ COPY .env.example .env
31
  COPY api_mental_health.py .
32
  COPY run_api.sh .
33
 
 
 
 
34
  # Make the script executable
35
  RUN chmod +x run_api.sh
36
 
 
31
  COPY api_mental_health.py .
32
  COPY run_api.sh .
33
 
34
+ # Copy model artifacts directory
35
+ COPY mental_health_model_artifacts/ mental_health_model_artifacts/
36
+
37
  # Make the script executable
38
  RUN chmod +x run_api.sh
39
 
api_mental_health.py CHANGED
@@ -81,20 +81,23 @@ async def startup_event():
81
 
82
  # Check environment variables
83
  if not os.environ.get("OPENAI_API_KEY"):
84
- logger.error("OPENAI_API_KEY not set in .env file")
85
- raise HTTPException(status_code=500, detail="OPENAI_API_KEY not set in .env file")
86
  if not os.environ.get("LANGCHAIN_API_KEY"):
87
- logger.error("LANGCHAIN_API_KEY not set in .env file")
88
- raise HTTPException(status_code=500, detail="LANGCHAIN_API_KEY not set in .env file")
89
  os.environ["LANGCHAIN_TRACING_V2"] = "true"
90
  os.environ["LANGCHAIN_PROJECT"] = "MentalHealthCounselorPOC"
91
 
92
- # Initialize LangSmith client
93
- logger.info("Initializing LangSmith client")
94
- langsmith_client = Client()
 
 
 
 
95
 
96
- # Load saved components
97
  logger.info("Loading model artifacts")
 
98
  try:
99
  response_clf = joblib.load(f"{output_dir}/response_type_classifier.pkl")
100
  crisis_clf = joblib.load(f"{output_dir}/crisis_classifier.pkl")
@@ -111,47 +114,89 @@ async def startup_event():
111
  # Note: Placeholder is untrained; retrain for accurate results
112
 
113
  except FileNotFoundError as e:
114
- logger.error(f"Missing model artifact: {e}")
115
- raise HTTPException(status_code=500, detail=f"Missing model artifact: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- # Initialize ChromaDB
118
  chroma_db_path = f"{output_dir}/chroma_db"
119
  if not os.path.exists(chroma_db_path):
120
- logger.error(f"ChromaDB not found at {chroma_db_path}. Run create_vector_db.py first.")
121
- raise HTTPException(status_code=500, detail=f"ChromaDB not found at {chroma_db_path}. Run create_vector_db.py first.")
122
-
123
- try:
124
- logger.info("Initializing ChromaDB")
125
- chroma_client = chromadb.PersistentClient(
126
- path=chroma_db_path,
127
- settings=Settings(anonymized_telemetry=False)
128
- )
 
129
 
130
- embeddings = OpenAIEmbeddings(
131
- model="text-embedding-ada-002",
132
- api_key=os.environ["OPENAI_API_KEY"],
133
- disallowed_special=(),
134
- chunk_size=1000
135
- )
136
- global vector_store
137
- vector_store = Chroma(
138
- client=chroma_client,
139
- collection_name="mental_health_conversations",
140
- embedding_function=embeddings
141
- )
142
- except Exception as e:
143
- logger.error(f"Error initializing ChromaDB: {e}")
144
- raise HTTPException(status_code=500, detail=f"Error initializing ChromaDB: {e}")
 
 
 
 
 
 
 
145
 
146
- # Initialize OpenAI client and LLM
147
  logger.info("Initializing OpenAI client and LLM")
148
  global openai_client, llm
149
- openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
150
- llm = ChatOpenAI(
151
- model="gpt-4o-mini",
152
- temperature=0.7,
153
- api_key=os.environ["OPENAI_API_KEY"]
154
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
  # Pydantic model for request
157
  class PatientContext(BaseModel):
@@ -266,6 +311,16 @@ def engineer_features(context, response=""):
266
  # Prediction function
267
  @traceable(run_type="chain", name="Predict Response Type")
268
  def predict_response_type(context):
 
 
 
 
 
 
 
 
 
 
269
  features, feature_cols = engineer_features(context)
270
  selected_features = selector.transform(features[feature_cols])
271
  pred_encoded = response_clf.predict(selected_features)[0]
@@ -285,7 +340,8 @@ def predict_response_type(context):
285
  "response_type": pred_label,
286
  "crisis_flag": crisis_flag,
287
  "confidence": confidence,
288
- "features": features.to_dict()
 
289
  }
290
 
291
  # RAG suggestion function
 
81
 
82
  # Check environment variables
83
  if not os.environ.get("OPENAI_API_KEY"):
84
+ logger.warning("OPENAI_API_KEY not set in .env file. Some functionality will be limited.")
 
85
  if not os.environ.get("LANGCHAIN_API_KEY"):
86
+ logger.warning("LANGCHAIN_API_KEY not set in .env file. Some functionality will be limited.")
 
87
  os.environ["LANGCHAIN_TRACING_V2"] = "true"
88
  os.environ["LANGCHAIN_PROJECT"] = "MentalHealthCounselorPOC"
89
 
90
+ # Initialize LangSmith client if API key is available
91
+ try:
92
+ logger.info("Initializing LangSmith client")
93
+ langsmith_client = Client()
94
+ except Exception as e:
95
+ logger.warning(f"Failed to initialize LangSmith client: {e}")
96
+ langsmith_client = None
97
 
98
+ # Try to load saved components, continue with limited functionality if not available
99
  logger.info("Loading model artifacts")
100
+ models_available = True
101
  try:
102
  response_clf = joblib.load(f"{output_dir}/response_type_classifier.pkl")
103
  crisis_clf = joblib.load(f"{output_dir}/crisis_classifier.pkl")
 
114
  # Note: Placeholder is untrained; retrain for accurate results
115
 
116
  except FileNotFoundError as e:
117
+ logger.warning(f"Missing model artifact: {e}. Running with limited functionality.")
118
+ models_available = False
119
+ # Set placeholder values for models to avoid errors
120
+ from sklearn.ensemble import RandomForestClassifier
121
+ from sklearn.feature_extraction.text import TfidfVectorizer
122
+ from sklearn.feature_selection import SelectKBest
123
+ from sklearn.preprocessing import LabelEncoder
124
+ from sklearn.decomposition import LatentDirichletAllocation
125
+
126
+ response_clf = RandomForestClassifier()
127
+ crisis_clf = RandomForestClassifier()
128
+ vectorizer = TfidfVectorizer()
129
+ le = LabelEncoder()
130
+ selector = SelectKBest()
131
+ lda = LatentDirichletAllocation(n_components=10)
132
 
133
+ # Initialize ChromaDB if possible
134
  chroma_db_path = f"{output_dir}/chroma_db"
135
  if not os.path.exists(chroma_db_path):
136
+ logger.warning(f"ChromaDB not found at {chroma_db_path}. Vector search will be unavailable.")
137
+ vector_store = None
138
+ else:
139
+ try:
140
+ logger.info("Initializing ChromaDB")
141
+ if os.environ.get("OPENAI_API_KEY"):
142
+ chroma_client = chromadb.PersistentClient(
143
+ path=chroma_db_path,
144
+ settings=Settings(anonymized_telemetry=False)
145
+ )
146
 
147
+ embeddings = OpenAIEmbeddings(
148
+ model="text-embedding-ada-002",
149
+ api_key=os.environ["OPENAI_API_KEY"],
150
+ disallowed_special=(),
151
+ chunk_size=1000
152
+ )
153
+ global vector_store
154
+ try:
155
+ vector_store = Chroma(
156
+ client=chroma_client,
157
+ collection_name="mental_health_conversations",
158
+ embedding_function=embeddings
159
+ )
160
+ except Exception as chroma_error:
161
+ logger.warning(f"Error initializing Chroma collection: {chroma_error}")
162
+ vector_store = None
163
+ else:
164
+ logger.warning("Skipping ChromaDB initialization as OPENAI_API_KEY is not set")
165
+ vector_store = None
166
+ except Exception as e:
167
+ logger.warning(f"Error initializing ChromaDB: {e}")
168
+ vector_store = None
169
 
170
+ # Initialize OpenAI client and LLM if API key is available
171
  logger.info("Initializing OpenAI client and LLM")
172
  global openai_client, llm
173
+ if os.environ.get("OPENAI_API_KEY"):
174
+ try:
175
+ openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
176
+ llm = ChatOpenAI(
177
+ model="gpt-4o-mini",
178
+ temperature=0.7,
179
+ api_key=os.environ["OPENAI_API_KEY"]
180
+ )
181
+ except Exception as e:
182
+ logger.warning(f"Error initializing OpenAI client: {e}")
183
+ openai_client = None
184
+ llm = None
185
+ else:
186
+ logger.warning("OpenAI client not initialized as OPENAI_API_KEY is not set")
187
+ openai_client = None
188
+ llm = None
189
+
190
+ # Add route to check model availability
191
+ @app.get("/model-status")
192
+ async def model_status():
193
+ return {
194
+ "models_available": models_available,
195
+ "vector_store_available": vector_store is not None,
196
+ "llm_available": llm is not None,
197
+ "openai_api_key_set": os.environ.get("OPENAI_API_KEY") is not None,
198
+ "langchain_api_key_set": os.environ.get("LANGCHAIN_API_KEY") is not None
199
+ }
200
 
201
  # Pydantic model for request
202
  class PatientContext(BaseModel):
 
311
  # Prediction function
312
  @traceable(run_type="chain", name="Predict Response Type")
313
  def predict_response_type(context):
314
+ if response_clf is None or vectorizer is None or le is None or selector is None or lda is None:
315
+ logger.warning("Models not available, returning dummy prediction")
316
+ return {
317
+ "response_type": "Empathetic Listening",
318
+ "crisis_flag": False,
319
+ "confidence": 0.5,
320
+ "features": {},
321
+ "models_available": False
322
+ }
323
+
324
  features, feature_cols = engineer_features(context)
325
  selected_features = selector.transform(features[feature_cols])
326
  pred_encoded = response_clf.predict(selected_features)[0]
 
340
  "response_type": pred_label,
341
  "crisis_flag": crisis_flag,
342
  "confidence": confidence,
343
+ "features": features.to_dict(),
344
+ "models_available": True
345
  }
346
 
347
  # RAG suggestion function