Vishu2006 commited on
Commit
bcf41d2
·
verified ·
1 Parent(s): 98becca

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +282 -180
app.py CHANGED
@@ -1,12 +1,13 @@
1
  import os
2
  import sys
3
  import json
 
 
4
 
5
  # ============================================================
6
- # PROJECT PATH CONFIGURATION
7
  # ============================================================
8
 
9
- # Ensure project root is in sys.path BEFORE importing ML modules
10
  PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
11
 
12
  if PROJECT_ROOT not in sys.path:
@@ -14,45 +15,38 @@ if PROJECT_ROOT not in sys.path:
14
 
15
 
16
  # ============================================================
17
- # DEPENDENCIES
18
  # ============================================================
19
 
20
- import spaces
21
- import gradio as gr
22
-
23
- from fastapi import FastAPI, HTTPException, Header, status, Query
24
- from pydantic import BaseModel
25
 
26
 
27
  # ============================================================
28
- # HUGGING FACE ZERO GPU STARTUP DETECTION
29
  # ============================================================
30
 
31
- @spaces.GPU(duration=1)
32
- def _zerogpu_health_check():
33
- """
34
- ZeroGPU compatibility function.
35
-
36
- This function exists so that Hugging Face ZeroGPU
37
- can detect a GPU-decorated function during startup.
38
-
39
- The actual Customer360 AI inference pipeline remains
40
- CPU-based.
41
- """
42
- return "GPU available"
43
-
44
 
45
- # ============================================================
46
- # ML INFERENCE SERVICE
47
- # ============================================================
48
 
49
  from ml.inference.unified_inference import inference_service
50
 
51
 
52
  # ============================================================
53
- # CONFIGURATION
54
  # ============================================================
55
 
 
 
 
 
 
 
 
56
  LIVE_API_KEY = os.getenv(
57
  "MODEL_API_KEY",
58
  "c360_live_key_9f8a2b7c4e1d"
@@ -74,20 +68,32 @@ fastapi_app = FastAPI(
74
 
75
 
76
  # ============================================================
77
- # HEALTH CHECK ENDPOINT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  # ============================================================
79
 
80
  @fastapi_app.get("/health")
81
  def health_check():
82
- """
83
- Health endpoint for uptime monitoring.
84
- """
85
 
86
  return {
87
  "status": "healthy",
88
  "service": "Customer360 AI Model",
89
  "models_loaded": inference_service.loaded,
90
- "api_key_configured": True
91
  }
92
 
93
 
@@ -101,79 +107,77 @@ def demo_predict(
101
  abandoned_carts: int = 2,
102
  support_tickets: int = 3
103
  ):
104
- """
105
- Demo prediction endpoint.
106
-
107
- This endpoint allows external applications to test
108
- the deployed Customer360 AI inference engine.
109
- """
110
 
111
  cust_dict = {
 
112
  "customer_id": "DEMO_C1024",
 
113
  "name": "Ananya Sharma",
114
 
115
- # ----------------------------
116
- # RFM FEATURES
117
- # ----------------------------
118
 
119
  "recency_days": recency_days,
 
120
  "frequency_purchases": 12,
 
121
  "monetary_total_spend": 45000.0,
 
122
  "avg_order_value": 3750.0,
123
 
124
- # ----------------------------
125
- # WEBSITE BEHAVIOUR
126
- # ----------------------------
127
 
128
  "website_visits_30d": 3,
 
129
  "product_views_30d": 5,
 
130
  "cart_additions_30d": 3,
 
131
  "cart_abandonments_30d": abandoned_carts,
132
 
133
- # ----------------------------
134
- # EMAIL ENGAGEMENT
135
- # ----------------------------
136
 
137
  "email_opens_30d": 1,
 
138
  "email_clicks_30d": 0,
139
 
140
- # ----------------------------
141
- # CUSTOMER SUPPORT
142
- # ----------------------------
143
 
144
  "support_tickets_30d": support_tickets,
145
 
146
- # ----------------------------
147
- # ENGAGEMENT TREND
148
- # ----------------------------
149
 
150
  "engagement_change_pct": -65.0,
151
 
152
- # ----------------------------
153
- # CUSTOMER BEHAVIOUR
154
- # ----------------------------
155
-
156
  "return_rate": 0.08,
 
157
  "discount_dependency_ratio": 0.35,
158
 
159
- # ----------------------------
160
- # SPENDING WINDOWS
161
- # ----------------------------
162
 
163
  "spend_30d": 0.0,
164
- "spend_90d": 15000.0,
165
 
166
- # ----------------------------
167
- # PURCHASE VELOCITY
168
- # ----------------------------
169
 
170
  "purchase_velocity": 30.0,
171
 
172
- # ----------------------------
173
- # PREFERENCES
174
- # ----------------------------
175
 
176
  "preferred_channel": "WhatsApp",
 
177
  "preferred_category": "Electronics"
178
  }
179
 
@@ -202,15 +206,13 @@ def predict_gradio(
202
  preferred_category,
203
  api_key_input
204
  ):
205
- """
206
- Runs Customer360 AI inference through the Gradio UI.
207
- """
208
 
209
  # ========================================================
210
  # API KEY VALIDATION
211
  # ========================================================
212
 
213
  if api_key_input != LIVE_API_KEY:
 
214
  return {
215
  "error": (
216
  "Unauthorized: Invalid API Key. "
@@ -220,23 +222,20 @@ def predict_gradio(
220
 
221
 
222
  # ========================================================
223
- # DATA TYPE CONVERSION
224
  # ========================================================
225
 
226
- frequency = int(frequency_purchases)
 
 
 
227
 
228
- monetary_total_spend = float(
229
  monetary_total_spend
230
  )
231
 
232
-
233
- # ========================================================
234
- # AVERAGE ORDER VALUE
235
- # ========================================================
236
-
237
  avg_order_value = (
238
- monetary_total_spend /
239
- max(1, frequency)
240
  )
241
 
242
 
@@ -246,109 +245,134 @@ def predict_gradio(
246
 
247
  cust_dict = {
248
 
249
- # ----------------------------
250
- # IDENTITY
251
- # ----------------------------
 
252
 
253
- "customer_id": customer_id or "C1024",
254
- "name": name or "Sample Customer",
 
 
255
 
256
- # ----------------------------
257
  # RFM
258
- # ----------------------------
259
 
260
- "recency_days": int(recency_days),
 
 
261
 
262
- "frequency_purchases": frequency,
 
 
263
 
264
- "monetary_total_spend":
265
- monetary_total_spend,
266
 
267
- "avg_order_value":
268
- avg_order_value,
269
 
270
- # ----------------------------
271
- # WEBSITE BEHAVIOUR
272
- # ----------------------------
273
 
274
- "website_visits_30d":
275
- int(website_visits_30d),
 
276
 
277
- "product_views_30d":
278
- int(product_views_30d),
 
279
 
280
- "cart_additions_30d":
281
- int(cart_additions_30d),
 
282
 
283
- "cart_abandonments_30d":
284
- int(cart_abandonments_30d),
 
285
 
286
- # ----------------------------
287
- # EMAIL ENGAGEMENT
288
- # ----------------------------
289
 
290
  "email_opens_30d": 5,
291
- "email_clicks_30d": 2,
292
 
293
- # ----------------------------
294
- # CUSTOMER SUPPORT
295
- # ----------------------------
296
 
297
- "support_tickets_30d":
298
- int(support_tickets_30d),
 
299
 
300
- # ----------------------------
301
- # ENGAGEMENT
302
- # ----------------------------
303
 
304
- "engagement_change_pct":
305
- float(engagement_change_pct),
 
306
 
307
- # ----------------------------
308
- # CUSTOMER BEHAVIOUR
309
- # ----------------------------
310
 
311
  "return_rate": 0.08,
312
 
313
  "discount_dependency_ratio": 0.35,
314
 
315
- # ----------------------------
316
- # SPENDING
317
- # ----------------------------
318
 
319
  "spend_30d": 0.0,
320
 
321
  "spend_90d": 15000.0,
322
 
323
- # ----------------------------
324
- # PURCHASE VELOCITY
325
- # ----------------------------
326
-
327
  "purchase_velocity": 30.0,
328
 
329
- # ----------------------------
330
- # CUSTOMER PREFERENCES
331
- # ----------------------------
332
 
333
- "preferred_channel":
334
- preferred_channel,
 
335
 
336
- "preferred_category":
337
  preferred_category
 
338
  }
339
 
340
 
341
  # ========================================================
342
- # RUN ML INFERENCE
343
  # ========================================================
344
 
345
- return inference_service.predict_customer_decision(
346
- cust_dict
347
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
 
349
 
350
  # ============================================================
351
- # GRADIO INTERFACE
352
  # ============================================================
353
 
354
  with gr.Blocks(
@@ -360,17 +384,29 @@ with gr.Blocks(
360
  # ========================================================
361
 
362
  gr.Markdown(
363
- "# 🧠 Customer360 AI -- Live Model Decision Engine"
 
 
 
 
 
 
 
 
 
 
364
  )
365
 
366
  gr.Markdown(
367
- "Direct Hugging Face 24/7 Live Deployment "
368
- "with Uptime Monitoring & API Key Protection."
 
 
369
  )
370
 
371
 
372
  # ========================================================
373
- # MAIN UI
374
  # ========================================================
375
 
376
  with gr.Row():
@@ -381,6 +417,10 @@ with gr.Blocks(
381
 
382
  with gr.Column():
383
 
 
 
 
 
384
  api_key_input = gr.Textbox(
385
  label="Live API Key",
386
  value="c360_live_key_9f8a2b7c4e1d",
@@ -397,6 +437,15 @@ with gr.Blocks(
397
  value="Ananya Sharma"
398
  )
399
 
 
 
 
 
 
 
 
 
 
400
  recency_days = gr.Number(
401
  label="Days Inactive",
402
  value=74
@@ -412,6 +461,15 @@ with gr.Blocks(
412
  value=45000
413
  )
414
 
 
 
 
 
 
 
 
 
 
415
  website_visits_30d = gr.Number(
416
  label="30-Day Website Visits",
417
  value=3
@@ -442,31 +500,41 @@ with gr.Blocks(
442
  value=-65.0
443
  )
444
 
 
 
 
 
 
 
 
 
 
445
  preferred_channel = gr.Dropdown(
446
  label="Preferred Channel",
447
-
448
  choices=[
449
  "WhatsApp",
450
  "Email",
451
  "Push",
452
  "SMS"
453
  ],
454
-
455
  value="WhatsApp"
456
  )
457
 
458
  preferred_category = gr.Dropdown(
459
  label="Preferred Category",
460
-
461
  choices=[
462
  "Electronics",
463
  "Fashion",
464
  "Home & Kitchen"
465
  ],
466
-
467
  value="Electronics"
468
  )
469
 
 
 
 
 
 
470
  btn = gr.Button(
471
  "🚀 Run Live Inference",
472
  variant="primary"
@@ -479,13 +547,20 @@ with gr.Blocks(
479
 
480
  with gr.Column():
481
 
 
 
 
 
482
  output_json = gr.JSON(
483
- label="ML Prediction & Next Best Action Result"
 
 
 
484
  )
485
 
486
 
487
  # ========================================================
488
- # BUTTON EVENT
489
  # ========================================================
490
 
491
  btn.click(
@@ -509,54 +584,70 @@ with gr.Blocks(
509
  api_key_input
510
  ],
511
 
512
- outputs=output_json
 
 
513
  )
514
 
515
 
516
  # ============================================================
517
- # MOUNT GRADIO APPLICATION ON FASTAPI
518
  # ============================================================
519
 
520
- app = gr.mount_gradio_app(
521
- fastapi_app,
522
- demo,
523
- path="/"
524
- )
 
525
 
 
 
 
526
 
527
- # ============================================================
528
- # APPLICATION ENTRY POINT
529
- # ============================================================
530
 
531
- if __name__ == "__main__":
 
 
532
 
533
- import uvicorn
534
 
 
535
 
536
- # ========================================================
537
- # ZERO GPU STARTUP HOOK
538
- # ========================================================
539
 
540
- try:
541
 
542
- import spaces.zero as _spaces_zero
 
 
 
543
 
544
- if hasattr(
545
- _spaces_zero,
546
- "startup"
547
- ):
548
- _spaces_zero.startup()
549
 
550
- except Exception as e:
 
 
 
551
 
552
- print(
553
- f"[ZeroGPU] Startup hook warning: {e}"
554
- )
555
 
 
 
 
 
 
556
 
557
- # ========================================================
558
- # SERVER CONFIGURATION
559
- # ========================================================
 
 
 
 
 
560
 
561
  port = int(
562
  os.environ.get(
@@ -565,10 +656,21 @@ if __name__ == "__main__":
565
  )
566
  )
567
 
 
 
 
568
 
569
- # ========================================================
570
- # START SERVER
571
- # ========================================================
 
 
 
 
 
 
 
 
572
 
573
  uvicorn.run(
574
  app,
 
1
  import os
2
  import sys
3
  import json
4
+ import inspect
5
+
6
 
7
  # ============================================================
8
+ # PROJECT ROOT CONFIGURATION
9
  # ============================================================
10
 
 
11
  PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
12
 
13
  if PROJECT_ROOT not in sys.path:
 
15
 
16
 
17
  # ============================================================
18
+ # GRADIO CONFIGURATION
19
  # ============================================================
20
 
21
+ # Prevent Gradio from attempting Server-Side Rendering where
22
+ # supported. This is useful for FastAPI + mounted Gradio apps.
23
+ os.environ["GRADIO_SSR_MODE"] = "False"
 
 
24
 
25
 
26
  # ============================================================
27
+ # IMPORTS
28
  # ============================================================
29
 
30
+ import spaces
31
+ import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ from fastapi import FastAPI, HTTPException, Header, status, Query
34
+ from pydantic import BaseModel
 
35
 
36
  from ml.inference.unified_inference import inference_service
37
 
38
 
39
  # ============================================================
40
+ # API CONFIGURATION
41
  # ============================================================
42
 
43
+ # IMPORTANT:
44
+ # For production, set MODEL_API_KEY as a Hugging Face Space Secret.
45
+ #
46
+ # The fallback below is retained temporarily so the current
47
+ # hackathon deployment continues to work if the Secret is not
48
+ # configured yet.
49
+
50
  LIVE_API_KEY = os.getenv(
51
  "MODEL_API_KEY",
52
  "c360_live_key_9f8a2b7c4e1d"
 
68
 
69
 
70
  # ============================================================
71
+ # ZEROGPU COMPATIBILITY FUNCTION
72
+ # ============================================================
73
+
74
+ # ZeroGPU detects GPU-enabled functions through @spaces.GPU.
75
+ #
76
+ # Your current Customer360 models are already loaded successfully,
77
+ # so this function does not perform the actual Customer360
78
+ # inference. It simply keeps the Space compatible with ZeroGPU.
79
+
80
+ @spaces.GPU(duration=1)
81
+ def _zerogpu_health_check():
82
+ return "GPU available"
83
+
84
+
85
+ # ============================================================
86
+ # FASTAPI HEALTH ENDPOINT
87
  # ============================================================
88
 
89
  @fastapi_app.get("/health")
90
  def health_check():
 
 
 
91
 
92
  return {
93
  "status": "healthy",
94
  "service": "Customer360 AI Model",
95
  "models_loaded": inference_service.loaded,
96
+ "api_key_configured": bool(LIVE_API_KEY)
97
  }
98
 
99
 
 
107
  abandoned_carts: int = 2,
108
  support_tickets: int = 3
109
  ):
 
 
 
 
 
 
110
 
111
  cust_dict = {
112
+
113
  "customer_id": "DEMO_C1024",
114
+
115
  "name": "Ananya Sharma",
116
 
117
+ # -----------------------------
118
+ # RFM
119
+ # -----------------------------
120
 
121
  "recency_days": recency_days,
122
+
123
  "frequency_purchases": 12,
124
+
125
  "monetary_total_spend": 45000.0,
126
+
127
  "avg_order_value": 3750.0,
128
 
129
+ # -----------------------------
130
+ # Engagement
131
+ # -----------------------------
132
 
133
  "website_visits_30d": 3,
134
+
135
  "product_views_30d": 5,
136
+
137
  "cart_additions_30d": 3,
138
+
139
  "cart_abandonments_30d": abandoned_carts,
140
 
141
+ # -----------------------------
142
+ # Communication
143
+ # -----------------------------
144
 
145
  "email_opens_30d": 1,
146
+
147
  "email_clicks_30d": 0,
148
 
149
+ # -----------------------------
150
+ # Support
151
+ # -----------------------------
152
 
153
  "support_tickets_30d": support_tickets,
154
 
155
+ # -----------------------------
156
+ # Behavioral trend
157
+ # -----------------------------
158
 
159
  "engagement_change_pct": -65.0,
160
 
 
 
 
 
161
  "return_rate": 0.08,
162
+
163
  "discount_dependency_ratio": 0.35,
164
 
165
+ # -----------------------------
166
+ # Spending
167
+ # -----------------------------
168
 
169
  "spend_30d": 0.0,
 
170
 
171
+ "spend_90d": 15000.0,
 
 
172
 
173
  "purchase_velocity": 30.0,
174
 
175
+ # -----------------------------
176
+ # Preferences
177
+ # -----------------------------
178
 
179
  "preferred_channel": "WhatsApp",
180
+
181
  "preferred_category": "Electronics"
182
  }
183
 
 
206
  preferred_category,
207
  api_key_input
208
  ):
 
 
 
209
 
210
  # ========================================================
211
  # API KEY VALIDATION
212
  # ========================================================
213
 
214
  if api_key_input != LIVE_API_KEY:
215
+
216
  return {
217
  "error": (
218
  "Unauthorized: Invalid API Key. "
 
222
 
223
 
224
  # ========================================================
225
+ # CUSTOMER INPUT NORMALIZATION
226
  # ========================================================
227
 
228
+ purchases = max(
229
+ 1,
230
+ int(frequency_purchases)
231
+ )
232
 
233
+ total_spend = float(
234
  monetary_total_spend
235
  )
236
 
 
 
 
 
 
237
  avg_order_value = (
238
+ total_spend / purchases
 
239
  )
240
 
241
 
 
245
 
246
  cust_dict = {
247
 
248
+ "customer_id": (
249
+ customer_id
250
+ or "C1024"
251
+ ),
252
 
253
+ "name": (
254
+ name
255
+ or "Sample Customer"
256
+ ),
257
 
258
+ # -----------------------------
259
  # RFM
260
+ # -----------------------------
261
 
262
+ "recency_days": int(
263
+ recency_days
264
+ ),
265
 
266
+ "frequency_purchases": int(
267
+ frequency_purchases
268
+ ),
269
 
270
+ "monetary_total_spend": total_spend,
 
271
 
272
+ "avg_order_value": avg_order_value,
 
273
 
274
+ # -----------------------------
275
+ # Engagement
276
+ # -----------------------------
277
 
278
+ "website_visits_30d": int(
279
+ website_visits_30d
280
+ ),
281
 
282
+ "product_views_30d": int(
283
+ product_views_30d
284
+ ),
285
 
286
+ "cart_additions_30d": int(
287
+ cart_additions_30d
288
+ ),
289
 
290
+ "cart_abandonments_30d": int(
291
+ cart_abandonments_30d
292
+ ),
293
 
294
+ # -----------------------------
295
+ # Communication
296
+ # -----------------------------
297
 
298
  "email_opens_30d": 5,
 
299
 
300
+ "email_clicks_30d": 2,
 
 
301
 
302
+ # -----------------------------
303
+ # Support
304
+ # -----------------------------
305
 
306
+ "support_tickets_30d": int(
307
+ support_tickets_30d
308
+ ),
309
 
310
+ # -----------------------------
311
+ # Behavioral trend
312
+ # -----------------------------
313
 
314
+ "engagement_change_pct": float(
315
+ engagement_change_pct
316
+ ),
317
 
318
  "return_rate": 0.08,
319
 
320
  "discount_dependency_ratio": 0.35,
321
 
322
+ # -----------------------------
323
+ # Spending
324
+ # -----------------------------
325
 
326
  "spend_30d": 0.0,
327
 
328
  "spend_90d": 15000.0,
329
 
 
 
 
 
330
  "purchase_velocity": 30.0,
331
 
332
+ # -----------------------------
333
+ # Preferences
334
+ # -----------------------------
335
 
336
+ "preferred_channel": (
337
+ preferred_channel
338
+ ),
339
 
340
+ "preferred_category": (
341
  preferred_category
342
+ )
343
  }
344
 
345
 
346
  # ========================================================
347
+ # RUN CUSTOMER360 ML PIPELINE
348
  # ========================================================
349
 
350
+ try:
351
+
352
+ result = (
353
+ inference_service
354
+ .predict_customer_decision(
355
+ cust_dict
356
+ )
357
+ )
358
+
359
+ return result
360
+
361
+ except Exception as e:
362
+
363
+ print(
364
+ "[Inference Error]",
365
+ repr(e)
366
+ )
367
+
368
+ return {
369
+ "error": "ML inference failed.",
370
+ "details": str(e)
371
+ }
372
 
373
 
374
  # ============================================================
375
+ # GRADIO USER INTERFACE
376
  # ============================================================
377
 
378
  with gr.Blocks(
 
384
  # ========================================================
385
 
386
  gr.Markdown(
387
+ """
388
+ # 🧠 Customer360 AI -- Live Model Decision Engine
389
+ """
390
+ )
391
+
392
+ gr.Markdown(
393
+ """
394
+ **Production ML inference engine for customer
395
+ churn, purchase propensity, CLV, segmentation,
396
+ explainability, and Next Best Action.**
397
+ """
398
  )
399
 
400
  gr.Markdown(
401
+ """
402
+ Direct Hugging Face live deployment with
403
+ API-key protected model inference.
404
+ """
405
  )
406
 
407
 
408
  # ========================================================
409
+ # MAIN LAYOUT
410
  # ========================================================
411
 
412
  with gr.Row():
 
417
 
418
  with gr.Column():
419
 
420
+ gr.Markdown(
421
+ "## Customer Information"
422
+ )
423
+
424
  api_key_input = gr.Textbox(
425
  label="Live API Key",
426
  value="c360_live_key_9f8a2b7c4e1d",
 
437
  value="Ananya Sharma"
438
  )
439
 
440
+
441
+ # -----------------------------------------------
442
+ # RFM
443
+ # -----------------------------------------------
444
+
445
+ gr.Markdown(
446
+ "### RFM Signals"
447
+ )
448
+
449
  recency_days = gr.Number(
450
  label="Days Inactive",
451
  value=74
 
461
  value=45000
462
  )
463
 
464
+
465
+ # -----------------------------------------------
466
+ # ENGAGEMENT
467
+ # -----------------------------------------------
468
+
469
+ gr.Markdown(
470
+ "### Engagement Signals"
471
+ )
472
+
473
  website_visits_30d = gr.Number(
474
  label="30-Day Website Visits",
475
  value=3
 
500
  value=-65.0
501
  )
502
 
503
+
504
+ # -----------------------------------------------
505
+ # CUSTOMER PREFERENCES
506
+ # -----------------------------------------------
507
+
508
+ gr.Markdown(
509
+ "### Customer Preferences"
510
+ )
511
+
512
  preferred_channel = gr.Dropdown(
513
  label="Preferred Channel",
 
514
  choices=[
515
  "WhatsApp",
516
  "Email",
517
  "Push",
518
  "SMS"
519
  ],
 
520
  value="WhatsApp"
521
  )
522
 
523
  preferred_category = gr.Dropdown(
524
  label="Preferred Category",
 
525
  choices=[
526
  "Electronics",
527
  "Fashion",
528
  "Home & Kitchen"
529
  ],
 
530
  value="Electronics"
531
  )
532
 
533
+
534
+ # -----------------------------------------------
535
+ # INFERENCE BUTTON
536
+ # -----------------------------------------------
537
+
538
  btn = gr.Button(
539
  "🚀 Run Live Inference",
540
  variant="primary"
 
547
 
548
  with gr.Column():
549
 
550
+ gr.Markdown(
551
+ "## Customer Decision Intelligence"
552
+ )
553
+
554
  output_json = gr.JSON(
555
+ label=(
556
+ "ML Prediction & "
557
+ "Next Best Action Result"
558
+ )
559
  )
560
 
561
 
562
  # ========================================================
563
+ # GRADIO EVENT
564
  # ========================================================
565
 
566
  btn.click(
 
584
  api_key_input
585
  ],
586
 
587
+ outputs=[
588
+ output_json
589
+ ]
590
  )
591
 
592
 
593
  # ============================================================
594
+ # MOUNT GRADIO ON FASTAPI
595
  # ============================================================
596
 
597
+ # Gradio versions differ in whether mount_gradio_app()
598
+ # accepts the ssr_mode parameter.
599
+ #
600
+ # We detect support dynamically so the same application works
601
+ # with your current Gradio 4.44.x installation as well as newer
602
+ # Gradio versions.
603
 
604
+ mount_kwargs = {
605
+ "path": "/"
606
+ }
607
 
608
+ try:
 
 
609
 
610
+ mount_signature = inspect.signature(
611
+ gr.mount_gradio_app
612
+ )
613
 
614
+ if "ssr_mode" in mount_signature.parameters:
615
 
616
+ mount_kwargs["ssr_mode"] = False
617
 
618
+ print(
619
+ "[Gradio] SSR explicitly disabled."
620
+ )
621
 
622
+ else:
623
 
624
+ print(
625
+ "[Gradio] Current version does not "
626
+ "support ssr_mode parameter."
627
+ )
628
 
629
+ except Exception as e:
 
 
 
 
630
 
631
+ print(
632
+ "[Gradio] Could not inspect mount_gradio_app:",
633
+ repr(e)
634
+ )
635
 
 
 
 
636
 
637
+ app = gr.mount_gradio_app(
638
+ fastapi_app,
639
+ demo,
640
+ **mount_kwargs
641
+ )
642
 
643
+
644
+ # ============================================================
645
+ # APPLICATION ENTRY POINT
646
+ # ============================================================
647
+
648
+ if __name__ == "__main__":
649
+
650
+ import uvicorn
651
 
652
  port = int(
653
  os.environ.get(
 
656
  )
657
  )
658
 
659
+ print(
660
+ f"[Customer360 AI] Starting server on port {port}"
661
+ )
662
 
663
+ print(
664
+ "[Customer360 AI] Models loaded:",
665
+ inference_service.loaded
666
+ )
667
+
668
+ print(
669
+ "[Customer360 AI] Gradio SSR mode:",
670
+ os.environ.get(
671
+ "GRADIO_SSR_MODE"
672
+ )
673
+ )
674
 
675
  uvicorn.run(
676
  app,