Quantum9999 commited on
Commit
72cdcc6
Β·
verified Β·
1 Parent(s): 441a49b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +392 -153
app.py CHANGED
@@ -1,184 +1,423 @@
1
  """
2
- DIAGNOSTIC VERSION - Streamlit App for Debugging
3
- This version has extensive logging to find the exact failure point
4
  """
5
 
6
  import streamlit as st
7
- import sys
8
  import os
 
9
 
10
- print("=" * 80, file=sys.stderr)
11
- print("DIAGNOSTIC APP STARTING", file=sys.stderr)
12
- print("=" * 80, file=sys.stderr)
 
13
 
14
- # Test 1: Page Config
15
- try:
16
- print("\n[TEST 1] Setting page config...", file=sys.stderr)
17
- st.set_page_config(
18
- page_title="Engine Predictive Maintenance - DIAGNOSTIC",
19
- page_icon="πŸ”§",
20
- layout="wide"
21
- )
22
- print("βœ“ Page config successful", file=sys.stderr)
23
- except Exception as e:
24
- print(f"βœ— Page config failed: {e}", file=sys.stderr)
25
- import traceback
26
- print(traceback.format_exc(), file=sys.stderr)
27
 
28
- # Test 2: Imports
29
- print("\n[TEST 2] Testing imports...", file=sys.stderr)
30
  try:
31
- print(" Importing pandas...", file=sys.stderr)
32
- import pandas as pd
33
- print(" βœ“ pandas imported", file=sys.stderr)
34
-
35
- print(" Importing huggingface_hub...", file=sys.stderr)
36
  from huggingface_hub import hf_hub_download, login
37
- print(" βœ“ huggingface_hub imported", file=sys.stderr)
38
-
39
- print(" Importing joblib...", file=sys.stderr)
40
  import joblib
41
- print(" βœ“ joblib imported", file=sys.stderr)
42
-
43
  print("βœ“ All imports successful", file=sys.stderr)
44
  except Exception as e:
45
- print(f"βœ— Import failed: {e}", file=sys.stderr)
46
- import traceback
47
- print(traceback.format_exc(), file=sys.stderr)
48
- st.error(f"Import error: {e}")
49
  st.stop()
50
 
51
- # Test 3: Environment Variables
52
- print("\n[TEST 3] Checking environment variables...", file=sys.stderr)
53
- hf_token = os.environ.get("HF_TOKEN")
54
- print(f" HF_TOKEN exists: {hf_token is not None}", file=sys.stderr)
55
- if hf_token:
56
- print(f" HF_TOKEN length: {len(hf_token)}", file=sys.stderr)
57
- print(f" HF_TOKEN starts with: {hf_token[:7]}...", file=sys.stderr)
58
- else:
59
- print(" ⚠ WARNING: HF_TOKEN not found!", file=sys.stderr)
60
-
61
- # Test 4: Hugging Face Authentication
62
- print("\n[TEST 4] Testing Hugging Face authentication...", file=sys.stderr)
63
- if hf_token:
64
- try:
65
- print(" Attempting login...", file=sys.stderr)
66
- login(token=hf_token)
67
- print(" βœ“ Login successful", file=sys.stderr)
68
- except Exception as e:
69
- print(f" βœ— Login failed: {e}", file=sys.stderr)
70
- import traceback
71
- print(traceback.format_exc(), file=sys.stderr)
72
- else:
73
- print(" ⚠ Skipping login (no token)", file=sys.stderr)
74
 
75
- # Test 5: Model Download
76
- print("\n[TEST 5] Testing model download...", file=sys.stderr)
77
- model = None
78
- model_error = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
- try:
81
- print(" Repository: Quantum9999/xgb-predictive-maintenance", file=sys.stderr)
82
- print(" Filename: xgb_tuned_model.joblib", file=sys.stderr)
83
- print(" Cache dir: /tmp/hf_cache", file=sys.stderr)
84
- print(" Starting download...", file=sys.stderr)
85
 
86
- model_path = hf_hub_download(
87
- repo_id="Quantum9999/xgb-predictive-maintenance",
88
- filename="xgb_tuned_model.joblib",
89
- token=hf_token,
90
- cache_dir="/tmp/hf_cache"
91
- )
92
 
93
- print(f" βœ“ Download successful!", file=sys.stderr)
94
- print(f" Model path: {model_path}", file=sys.stderr)
95
 
96
- # Test 6: Model Loading
97
- print("\n[TEST 6] Testing model loading...", file=sys.stderr)
98
- print(" Loading model into memory...", file=sys.stderr)
99
- model = joblib.load(model_path)
100
- print(" βœ“ Model loaded successfully!", file=sys.stderr)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
- # Test 7: Model Properties
103
- print("\n[TEST 7] Checking model properties...", file=sys.stderr)
104
- print(f" Model type: {type(model)}", file=sys.stderr)
105
- if hasattr(model, 'feature_names_in_'):
106
- print(f" Expected features: {model.feature_names_in_}", file=sys.stderr)
107
- if hasattr(model, 'n_features_in_'):
108
- print(f" Number of features: {model.n_features_in_}", file=sys.stderr)
109
 
110
- except Exception as e:
111
- model_error = str(e)
112
- print(f" βœ— Model loading failed: {e}", file=sys.stderr)
113
- import traceback
114
- print(traceback.format_exc(), file=sys.stderr)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
- print("\n" + "=" * 80, file=sys.stderr)
117
- print("DIAGNOSTIC TESTS COMPLETED", file=sys.stderr)
118
- print("=" * 80 + "\n", file=sys.stderr)
119
 
120
- # Display results to user
121
- st.title("πŸ” Diagnostic Mode")
122
- st.write("This is a diagnostic version to identify the issue.")
123
 
124
- st.header("Test Results:")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
- st.subheader("1. Environment Variables")
127
- if hf_token:
128
- st.success(f"βœ“ HF_TOKEN found (length: {len(hf_token)})")
129
- else:
130
- st.error("βœ— HF_TOKEN not found in environment")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
- st.subheader("2. Model Loading")
133
- if model is not None:
134
- st.success("βœ“ Model loaded successfully!")
135
- st.write(f"Model type: {type(model)}")
136
 
137
- if hasattr(model, 'feature_names_in_'):
138
- st.write("Expected features:")
139
- st.code(str(model.feature_names_in_))
140
-
141
- # Try a test prediction
142
- st.subheader("3. Test Prediction")
143
- try:
144
- import pandas as pd
145
- test_input = pd.DataFrame([{
146
- "Engine rpm": 791.0,
147
- "Lub oil pressure": 3.3,
148
- "Fuel pressure": 6.7,
149
- "Coolant pressure": 2.3,
150
- "lub oil temp": 77.6,
151
- "Coolant temp": 78.4
152
  }])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
- prediction = model.predict(test_input)[0]
155
- proba = model.predict_proba(test_input)[0]
156
-
157
- st.success("βœ“ Test prediction successful!")
158
- st.write(f"Prediction: {prediction}")
159
- st.write(f"Probabilities: {proba}")
160
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  except Exception as e:
162
- st.error(f"βœ— Test prediction failed: {e}")
163
- st.code(str(e))
164
-
165
- else:
166
- st.error("βœ— Model loading failed!")
167
- if model_error:
168
- st.code(model_error)
169
- st.warning("Check Container logs for detailed traceback")
170
-
171
- st.divider()
172
- st.info("πŸ“ Check the 'Container' logs tab for detailed diagnostic information")
173
-
174
- st.header("Next Steps:")
175
- if model is not None:
176
- st.success("βœ… Everything works! The issue might be with the healthcheck timing.")
177
- st.write("Recommendation: Just wait longer for the Space to become healthy, or increase healthcheck start-period to 90s")
178
- else:
179
- st.error("There's a real issue with model loading.")
180
- st.write("Common causes:")
181
- st.write("1. HF_TOKEN is wrong or expired")
182
- st.write("2. Model file doesn't exist in the repository")
183
- st.write("3. Network/connectivity issue")
184
- st.write("4. File permissions issue")
 
1
  """
2
+ Streamlit Application for Engine Predictive Maintenance
3
+ Production Version
4
  """
5
 
6
  import streamlit as st
7
+ import pandas as pd
8
  import os
9
+ import sys
10
 
11
+ # Print to console (will show in HF Space logs)
12
+ print("=" * 70, file=sys.stderr)
13
+ print("APP STARTING - INITIALIZATION", file=sys.stderr)
14
+ print("=" * 70, file=sys.stderr)
15
 
16
+ # Page Configuration MUST be first
17
+ st.set_page_config(
18
+ page_title="Engine Predictive Maintenance",
19
+ page_icon="πŸ”§",
20
+ layout="wide",
21
+ initial_sidebar_state="expanded"
22
+ )
 
 
 
 
 
 
23
 
24
+ # Import after page config
 
25
  try:
26
+ print("Importing huggingface_hub...", file=sys.stderr)
 
 
 
 
27
  from huggingface_hub import hf_hub_download, login
28
+ print("Importing joblib...", file=sys.stderr)
 
 
29
  import joblib
 
 
30
  print("βœ“ All imports successful", file=sys.stderr)
31
  except Exception as e:
32
+ print(f"βœ— Import error: {e}", file=sys.stderr)
33
+ st.error(f"Import failed: {e}")
 
 
34
  st.stop()
35
 
36
+ # CRITICAL: Feature columns must EXACTLY match model training
37
+ FEATURE_COLUMNS = [
38
+ "Engine rpm",
39
+ "Lub oil pressure",
40
+ "Fuel pressure",
41
+ "Coolant pressure",
42
+ "lub oil temp",
43
+ "Coolant temp"
44
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ # Custom CSS
47
+ st.markdown("""
48
+ <style>
49
+ .main-header {
50
+ font-size: 42px;
51
+ font-weight: bold;
52
+ color: #1f77b4;
53
+ text-align: center;
54
+ margin-bottom: 10px;
55
+ }
56
+ .sub-header {
57
+ font-size: 18px;
58
+ color: #555;
59
+ text-align: center;
60
+ margin-bottom: 30px;
61
+ }
62
+ .prediction-box {
63
+ padding: 20px;
64
+ border-radius: 10px;
65
+ text-align: center;
66
+ font-size: 24px;
67
+ font-weight: bold;
68
+ margin-top: 20px;
69
+ }
70
+ .normal {
71
+ background-color: #d4edda;
72
+ color: #155724;
73
+ border: 2px solid #c3e6cb;
74
+ }
75
+ .maintenance {
76
+ background-color: #f8d7da;
77
+ color: #721c24;
78
+ border: 2px solid #f5c6cb;
79
+ }
80
+ .metric-card {
81
+ background-color: #f8f9fa;
82
+ padding: 15px;
83
+ border-radius: 8px;
84
+ border-left: 4px solid #1f77b4;
85
+ }
86
+ </style>
87
+ """, unsafe_allow_html=True)
88
 
89
+
90
+ @st.cache_resource
91
+ def load_model():
92
+ """Load model from Hugging Face with detailed logging and retries"""
 
93
 
94
+ print("\n" + "=" * 70, file=sys.stderr)
95
+ print("LOADING MODEL FROM HUGGING FACE", file=sys.stderr)
96
+ print("=" * 70, file=sys.stderr)
 
 
 
97
 
98
+ max_retries = 3
99
+ retry_count = 0
100
 
101
+ while retry_count < max_retries:
102
+ try:
103
+ # Get HF_TOKEN and clean it
104
+ hf_token = os.environ.get("HF_TOKEN")
105
+ if hf_token:
106
+ hf_token = hf_token.strip() # Remove any newlines or whitespace
107
+
108
+ print(f"HF_TOKEN found: {hf_token is not None}", file=sys.stderr)
109
+
110
+ if hf_token:
111
+ print("Authenticating with Hugging Face...", file=sys.stderr)
112
+ login(token=hf_token)
113
+ print("βœ“ Authentication successful", file=sys.stderr)
114
+ else:
115
+ print("⚠ No HF_TOKEN - attempting public access", file=sys.stderr)
116
+
117
+ # Download model
118
+ print("\nDownloading model...", file=sys.stderr)
119
+ print(" Repo: Quantum9999/xgb-predictive-maintenance", file=sys.stderr)
120
+ print(" File: xgb_tuned_model.joblib", file=sys.stderr)
121
+
122
+ model_path = hf_hub_download(
123
+ repo_id="Quantum9999/xgb-predictive-maintenance",
124
+ filename="xgb_tuned_model.joblib",
125
+ token=hf_token,
126
+ cache_dir="/tmp/hf_cache"
127
+ )
128
+ print(f"βœ“ Model downloaded: {model_path}", file=sys.stderr)
129
+
130
+ # Load model
131
+ print("Loading model into memory...", file=sys.stderr)
132
+ model = joblib.load(model_path)
133
+ print("βœ“ Model loaded successfully", file=sys.stderr)
134
+
135
+ # Verify model features
136
+ if hasattr(model, 'feature_names_in_'):
137
+ print(f"Model expects features: {model.feature_names_in_}", file=sys.stderr)
138
+
139
+ print("=" * 70 + "\n", file=sys.stderr)
140
+
141
+ return model, None
142
+
143
+ except Exception as e:
144
+ retry_count += 1
145
+ error_msg = f"Model loading attempt {retry_count}/{max_retries} failed: {str(e)}"
146
+ print(f"βœ— {error_msg}", file=sys.stderr)
147
+
148
+ if retry_count < max_retries:
149
+ import time
150
+ wait_time = 2 * retry_count
151
+ print(f"Retrying in {wait_time} seconds...", file=sys.stderr)
152
+ time.sleep(wait_time)
153
+ else:
154
+ import traceback
155
+ print(f"Final traceback:\n{traceback.format_exc()}", file=sys.stderr)
156
+ print("=" * 70 + "\n", file=sys.stderr)
157
+ return None, error_msg
158
+
159
+
160
+ def main():
161
+ """Main application"""
162
 
163
+ print("Starting main application...", file=sys.stderr)
 
 
 
 
 
 
164
 
165
+ # Header
166
+ st.markdown(
167
+ '<div class="main-header">πŸ”§ Engine Predictive Maintenance System</div>',
168
+ unsafe_allow_html=True
169
+ )
170
+ st.markdown(
171
+ '<div class="sub-header">AI-powered engine health monitoring & failure prediction</div>',
172
+ unsafe_allow_html=True
173
+ )
174
+
175
+ # Load model with progress indicator
176
+ with st.spinner("Loading AI model... This may take a moment."):
177
+ model, error = load_model()
178
+
179
+ if model is None:
180
+ st.error(f"❌ Failed to load prediction model")
181
+ st.code(error)
182
+
183
+ with st.expander("πŸ” Troubleshooting"):
184
+ st.write("**Possible Issues:**")
185
+ st.write("1. HF_TOKEN not set in Space secrets")
186
+ st.write("2. Model repository is private")
187
+ st.write("3. Model filename is incorrect")
188
+ st.write("4. Network connectivity issue")
189
+
190
+ st.write("\n**Current Configuration:**")
191
+ st.write(f"- HF_TOKEN set: {os.environ.get('HF_TOKEN') is not None}")
192
+ st.write("- Expected repo: Quantum9999/xgb-predictive-maintenance")
193
+ st.write("- Expected file: xgb_tuned_model.joblib")
194
+
195
+ st.stop()
196
+
197
+ st.success("βœ“ Model loaded successfully!")
198
+
199
+ # Sidebar
200
+ with st.sidebar:
201
+ st.header("ℹ️ About")
202
+ st.write(
203
+ "This application predicts engine maintenance needs using "
204
+ "machine learning analysis of 6 critical sensor parameters."
205
+ )
206
+
207
+ st.header("πŸ“Š Model Information")
208
+ st.markdown("""
209
+ - **Algorithm**: XGBoost Classifier
210
+ - **Features**: 6 sensor readings
211
+ - **Target Classes**:
212
+ - 0: Normal Operation
213
+ - 1: Maintenance Required
214
+ - **Training Data**: 19,535 records
215
+ """)
216
+
217
+ st.header("🎯 How to Use")
218
+ st.markdown("""
219
+ 1. Enter current sensor readings
220
+ 2. Click 'Predict Engine Condition'
221
+ 3. Review prediction and confidence
222
+ 4. Take action based on results
223
+ """)
224
+
225
+ st.header("πŸ“ˆ Sensor Ranges")
226
+ st.markdown("""
227
+ **Normal Operating Ranges:**
228
+ - RPM: 161 - 2,239
229
+ - Lub Oil Pressure: 0.003 - 7.3 bar
230
+ - Fuel Pressure: 0.003 - 21.1 bar
231
+ - Coolant Pressure: 0.002 - 7.5 bar
232
+ - Lub Oil Temp: 71 - 90 Β°C
233
+ - Coolant Temp: 62 - 196 Β°C
234
+ """)
235
 
236
+ # Main content
237
+ st.header("πŸ“ Enter Engine Sensor Readings")
238
+ st.markdown("---")
239
 
240
+ # Input columns
241
+ col1, col2 = st.columns(2)
 
242
 
243
+ with col1:
244
+ st.subheader("βš™οΈ Speed & Pressure Sensors")
245
+
246
+ engine_rpm = st.number_input(
247
+ "Engine RPM (Revolutions per Minute)",
248
+ min_value=100.0,
249
+ max_value=2500.0,
250
+ value=791.0,
251
+ step=10.0,
252
+ help="Engine speed - Normal range: 161-2,239 RPM"
253
+ )
254
+
255
+ lub_oil_pressure = st.number_input(
256
+ "Lubrication Oil Pressure (bar)",
257
+ min_value=0.0,
258
+ max_value=10.0,
259
+ value=3.3,
260
+ step=0.1,
261
+ help="Lubricating oil pressure - Normal range: 0.003-7.266 bar"
262
+ )
263
+
264
+ fuel_pressure = st.number_input(
265
+ "Fuel Pressure (bar)",
266
+ min_value=0.0,
267
+ max_value=25.0,
268
+ value=6.7,
269
+ step=0.1,
270
+ help="Fuel delivery pressure - Normal range: 0.003-21.138 bar"
271
+ )
272
 
273
+ with col2:
274
+ st.subheader("🌑️ Temperature & Coolant Sensors")
275
+
276
+ coolant_pressure = st.number_input(
277
+ "Coolant Pressure (bar)",
278
+ min_value=0.0,
279
+ max_value=10.0,
280
+ value=2.3,
281
+ step=0.1,
282
+ help="Coolant system pressure - Normal range: 0.002-7.479 bar"
283
+ )
284
+
285
+ lub_oil_temp = st.number_input(
286
+ "Lubrication Oil Temperature (Β°C)",
287
+ min_value=60.0,
288
+ max_value=100.0,
289
+ value=77.6,
290
+ step=0.5,
291
+ help="Lubricating oil temperature - Normal range: 71.3-89.6 Β°C"
292
+ )
293
+
294
+ coolant_temp = st.number_input(
295
+ "Coolant Temperature (Β°C)",
296
+ min_value=50.0,
297
+ max_value=200.0,
298
+ value=78.4,
299
+ step=0.5,
300
+ help="Engine coolant temperature - Normal range: 61.7-195.5 Β°C"
301
+ )
302
 
303
+ # Prediction button
304
+ st.markdown("---")
 
 
305
 
306
+ if st.button("πŸ” Predict Engine Condition", use_container_width=True, type="primary"):
307
+ # Create input DataFrame with exact column names
308
+ input_df = pd.DataFrame([{
309
+ "Engine rpm": engine_rpm,
310
+ "Lub oil pressure": lub_oil_pressure,
311
+ "Fuel pressure": fuel_pressure,
312
+ "Coolant pressure": coolant_pressure,
313
+ "lub oil temp": lub_oil_temp,
314
+ "Coolant temp": coolant_temp
 
 
 
 
 
 
315
  }])
316
+
317
+ try:
318
+ print(f"Making prediction with input: {input_df.to_dict()}", file=sys.stderr)
319
+
320
+ # Make prediction
321
+ prediction = model.predict(input_df)[0]
322
+ proba = model.predict_proba(input_df)[0]
323
+
324
+ print(f"Prediction: {prediction}, Probabilities: {proba}", file=sys.stderr)
325
+
326
+ # Display results
327
+ st.markdown("---")
328
+ st.header("🎯 Prediction Result")
329
+
330
+ if prediction == 0:
331
+ st.markdown(
332
+ '<div class="prediction-box normal">βœ… Engine Operating Normally</div>',
333
+ unsafe_allow_html=True
334
+ )
335
+ st.success("βœ“ No maintenance required at this time. Engine is functioning within normal parameters.")
336
+ else:
337
+ st.markdown(
338
+ '<div class="prediction-box maintenance">⚠️ Maintenance Required</div>',
339
+ unsafe_allow_html=True
340
+ )
341
+ st.warning("⚠ Engine shows signs of potential failure. Schedule maintenance as soon as possible to prevent breakdown.")
342
+
343
+ # Confidence scores
344
+ st.subheader("πŸ“Š Prediction Confidence")
345
+
346
+ conf_col1, conf_col2 = st.columns(2)
347
+
348
+ with conf_col1:
349
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
350
+ st.metric(
351
+ label="Normal Operation Probability",
352
+ value=f"{proba[0]:.2%}",
353
+ help="Confidence that engine is operating normally"
354
+ )
355
+ st.markdown('</div>', unsafe_allow_html=True)
356
+
357
+ with conf_col2:
358
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
359
+ st.metric(
360
+ label="Maintenance Required Probability",
361
+ value=f"{proba[1]:.2%}",
362
+ help="Confidence that engine requires maintenance"
363
+ )
364
+ st.markdown('</div>', unsafe_allow_html=True)
365
+
366
+ # Input summary
367
+ with st.expander("πŸ“‹ View Input Summary"):
368
+ st.dataframe(
369
+ input_df.T.rename(columns={0: "Value"}),
370
+ use_container_width=True
371
+ )
372
+
373
+ # Recommendations
374
+ with st.expander("πŸ’‘ Recommendations"):
375
+ if prediction == 0:
376
+ st.markdown("""
377
+ **Current Status: Healthy**
378
+ - Continue regular monitoring
379
+ - Maintain current maintenance schedule
380
+ - Monitor for any sudden changes in sensor readings
381
+ - Schedule next routine inspection as planned
382
+ """)
383
+ else:
384
+ st.markdown("""
385
+ **Immediate Actions Required:**
386
+ - Schedule comprehensive engine inspection
387
+ - Check lubrication system
388
+ - Inspect cooling system
389
+ - Review fuel delivery system
390
+ - Monitor engine closely until serviced
391
+ - Consider reducing operational load
392
+ """)
393
 
394
+ except Exception as e:
395
+ error_msg = f"Prediction error: {e}"
396
+ print(f"βœ— {error_msg}", file=sys.stderr)
397
+ import traceback
398
+ print(f"Traceback:\n{traceback.format_exc()}", file=sys.stderr)
399
+
400
+ st.error(f"❌ {error_msg}")
401
+ st.info("Please verify all sensor values are within valid ranges and try again.")
402
+
403
+ # Footer
404
+ st.markdown("---")
405
+ st.markdown(
406
+ "<p style='text-align: center; color: #666; font-size: 14px;'>"
407
+ "πŸ€– Built with XGBoost & Streamlit | πŸ€— Model hosted on Hugging Face<br>"
408
+ "Developed as part of ML Deployment & Automation Project"
409
+ "</p>",
410
+ unsafe_allow_html=True
411
+ )
412
+
413
+
414
+ if __name__ == "__main__":
415
+ print("Entering main()...", file=sys.stderr)
416
+ try:
417
+ main()
418
+ print("βœ“ Main completed successfully", file=sys.stderr)
419
  except Exception as e:
420
+ print(f"βœ— FATAL ERROR: {e}", file=sys.stderr)
421
+ import traceback
422
+ print(f"Traceback:\n{traceback.format_exc()}", file=sys.stderr)
423
+ st.error(f"Application error: {e}")