File size: 6,365 Bytes
73cb5e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import os
import sys
import json
import gradio as gr
from fastapi import FastAPI, HTTPException, Depends, Header, Query, status
from fastapi.security import APIKeyHeader
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import Optional, List

# Ensure project root is in sys.path
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
if PROJECT_ROOT not in sys.path:
    sys.path.insert(0, PROJECT_ROOT)

from ml.inference.unified_inference import inference_service

LIVE_API_KEY = os.getenv("MODEL_API_KEY", "c360_live_key_9f8a2b7c4e1d")

# 1. Initialize FastAPI Application
app = FastAPI(
    title="Customer360 AI -- Live Model Engine",
    description="24/7 Live Machine Learning Model Engine with Uptime Monitoring & API Key Authentication.",
    version="1.0.0"
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)

def verify_api_key(api_key: Optional[str] = Depends(api_key_header)):
    if not api_key or api_key != LIVE_API_KEY:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Unauthorized: Invalid or missing 'X-API-Key' header."
        )
    return api_key

class CustomerInputSchema(BaseModel):
    customer_id: str = Field("C1024", description="Unique customer identifier")
    name: Optional[str] = Field("Ananya Sharma", description="Customer full name")
    recency_days: int = Field(74, description="Days since last purchase")
    frequency_purchases: int = Field(12, description="Total purchases in 12m")
    monetary_total_spend: float = Field(45000.0, description="Lifetime spend in INR")
    website_visits_30d: int = Field(3, description="Website visits in 30d")
    product_views_30d: int = Field(5, description="Product views in 30d")
    cart_additions_30d: int = Field(3, description="Cart additions in 30d")
    cart_abandonments_30d: int = Field(2, description="Abandoned carts in 30d")
    support_tickets_30d: int = Field(3, description="Support tickets in 30d")
    engagement_change_pct: float = Field(-65.0, description="Engagement change %")
    preferred_channel: Optional[str] = Field("WhatsApp", description="WhatsApp, Email, Push, SMS")
    preferred_category: Optional[str] = Field("Electronics", description="Product category")

# FastAPI Health Endpoint (for UptimeRobot 24/7 Monitoring & Incident Emails)
@app.get("/health")
def health_check():
    return {
        "status": "healthy",
        "service": "Customer360 AI Model",
        "models_loaded": inference_service.loaded,
        "api_key_configured": True
    }

# FastAPI Browser Demo Endpoint
@app.get("/demo-predict")
def demo_predict(recency_days: int = 74, abandoned_carts: int = 2, support_tickets: int = 3):
    cust_dict = {
        "customer_id": "DEMO_C1024",
        "name": "Ananya Sharma",
        "recency_days": recency_days,
        "frequency_purchases": 12,
        "monetary_total_spend": 45000.0,
        "website_visits_30d": 3,
        "product_views_30d": 5,
        "cart_additions_30d": 3,
        "cart_abandonments_30d": abandoned_carts,
        "support_tickets_30d": support_tickets,
        "engagement_change_pct": -65.0,
        "preferred_channel": "WhatsApp",
        "preferred_category": "Electronics"
    }
    return inference_service.predict_customer_decision(cust_dict)

# FastAPI REST API Prediction Endpoint
@app.post("/api/v1/predict", dependencies=[Depends(verify_api_key)])
def predict_single(payload: CustomerInputSchema):
    return inference_service.predict_customer_decision(payload.model_dump())

# 2. Initialize Gradio UI
def predict_gradio(customer_id, recency_days, frequency_purchases, monetary_total_spend, cart_abandonments_30d, support_tickets_30d, preferred_channel, preferred_category, api_key_input):
    if api_key_input != LIVE_API_KEY:
        return {"error": "Unauthorized: Invalid API Key."}

    cust_dict = {
        "customer_id": customer_id or "C1024",
        "recency_days": int(recency_days),
        "frequency_purchases": int(frequency_purchases),
        "monetary_total_spend": float(monetary_total_spend),
        "cart_abandonments_30d": int(cart_abandonments_30d),
        "support_tickets_30d": int(support_tickets_30d),
        "preferred_channel": preferred_channel,
        "preferred_category": preferred_category
    }
    return inference_service.predict_customer_decision(cust_dict)

with gr.Blocks(title="Customer360 AI -- Live Decision Studio") as gradio_ui:
    gr.Markdown("# 🧠 Customer360 AI -- Live Model Engine")
    gr.Markdown("Direct Hugging Face 24/7 Live Deployment with Uptime Monitoring & API Key Protection.")
    
    with gr.Row():
        with gr.Column():
            api_key_input = gr.Textbox(label="Live API Key", value="c360_live_key_9f8a2b7c4e1d", type="password")
            customer_id = gr.Textbox(label="Customer ID", value="C1024")
            recency_days = gr.Number(label="Days Inactive", value=74)
            frequency_purchases = gr.Number(label="Total Purchases", value=12)
            monetary_total_spend = gr.Number(label="Lifetime Spend (INR)", value=45000)
            cart_abandonments_30d = gr.Number(label="Abandoned Carts", value=2)
            support_tickets_30d = gr.Number(label="Support Tickets", value=3)
            preferred_channel = gr.Dropdown(label="Preferred Channel", choices=["WhatsApp", "Email", "Push", "SMS"], value="WhatsApp")
            preferred_category = gr.Dropdown(label="Preferred Category", choices=["Electronics", "Fashion", "Home & Kitchen"], value="Electronics")
            btn = gr.Button("🚀 Run Live Inference", variant="primary")

        with gr.Column():
            output_json = gr.JSON(label="ML Prediction & Next Best Action Result")

    btn.click(
        fn=predict_gradio,
        inputs=[customer_id, recency_days, frequency_purchases, monetary_total_spend, cart_abandonments_30d, support_tickets_30d, preferred_channel, preferred_category, api_key_input],
        outputs=output_json
    )

# Mount Gradio onto FastAPI
app = gr.mount_gradio_app(app, gradio_ui, path="/")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("app:app", host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))