Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import joblib | |
| import pandas as pd | |
| import os | |
| # Debug: List files in current directory to see what's available | |
| st.write("Current directory files:", os.listdir(".")) | |
| # Load model and columns from the same src folder | |
| model = joblib.load("churn_predictor_xgb.pkl") | |
| columns = joblib.load("churn_model_columns.pkl") | |
| st.set_page_config(page_title="RUCTURO", page_icon="π£", layout="centered") | |
| # Premium futuristic CSS | |
| st.markdown(""" | |
| <style> | |
| .main { | |
| background: linear-gradient(to bottom, #0F172A, #1E293B); | |
| color: #F1F5F9; | |
| } | |
| h1, h2, h3 { | |
| color: #6D28D9; | |
| text-shadow: 0 0 10px #22D3EE; | |
| font-family: 'Orbitron', sans-serif; | |
| } | |
| .stButton>button { | |
| background: linear-gradient(to right, #6D28D9, #22D3EE); | |
| color: white; | |
| border: none; | |
| border-radius: 12px; | |
| padding: 12px 24px; | |
| font-size: 18px; | |
| box-shadow: 0 0 20px #22D3EE; | |
| transition: all 0.3s; | |
| } | |
| .stButton>button:hover { | |
| transform: scale(1.05); | |
| box-shadow: 0 0 30px #6D28D9; | |
| } | |
| .risk-high { color: #F87171; font-size: 36px; font-weight: bold; text-shadow: 0 0 10px #F87171; } | |
| .risk-medium { color: #FBBF24; font-size: 32px; font-weight: bold; } | |
| .risk-low { color: #10B981; font-size: 32px; font-weight: bold; } | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@700&display=swap'); | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.title("π£ RUCTURO") | |
| st.markdown("### Premium AI-Powered Customer Churn Predictor for SaaS Tools") | |
| st.markdown("Predict churn risk instantly and get actionable retention insights.") | |
| # Input form | |
| with st.form("churn_form"): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| tenure = st.slider("Tenure (months)", 0, 72, 12) | |
| monthly = st.slider("Monthly Charges ($)", 18, 120, 70) | |
| senior = st.radio("Senior Citizen", [0, 1], format_func=lambda x: "Yes" if x else "No") | |
| contract = st.selectbox("Contract Type", ["Month-to-month", "One year", "Two year"]) | |
| internet = st.selectbox("Internet Service", ["DSL", "Fiber optic", "No"]) | |
| tech_support = st.selectbox("Tech Support", ["Yes", "No"]) | |
| with col2: | |
| online_security = st.selectbox("Online Security", ["Yes", "No"]) | |
| payment = st.selectbox("Payment Method", ["Electronic check", "Mailed check", "Bank transfer (automatic)", "Credit card (automatic)"]) | |
| paperless = st.selectbox("Paperless Billing", ["Yes", "No"]) | |
| num_services = st.slider("Number of Services (approx)", 0, 10, 5) | |
| has_internet = st.radio("Has Internet", [0, 1], format_func=lambda x: "Yes" if x else "No") | |
| submitted = st.form_submit_button("Predict Churn Risk") | |
| if submitted: | |
| data = { | |
| 'tenure': tenure, | |
| 'MonthlyCharges': monthly, | |
| 'TotalCharges': monthly * (tenure + 1), | |
| 'SeniorCitizen': senior, | |
| 'Num_Services': num_services, | |
| 'Has_Internet': has_internet, | |
| 'TotalCharges_per_Tenure': monthly, | |
| 'Charges_Increase': 0, | |
| 'Is_Month_to_Month': 1 if contract == "Month-to-month" else 0, | |
| 'Is_Fiber_Optic': 1 if internet == "Fiber optic" else 0, | |
| 'Has_No_TechSupport': 1 if tech_support == "No" else 0, | |
| 'PaperlessBilling_Yes': 1 if paperless == "Yes" else 0, | |
| } | |
| df = pd.DataFrame([data]) | |
| df = pd.get_dummies(df, columns=['Contract', 'InternetService', 'TechSupport', 'OnlineSecurity', 'PaymentMethod']) | |
| df = df.reindex(columns=columns, fill_value=0) | |
| prob = model.predict_proba(df)[0, 1] | |
| st.markdown("---") | |
| st.markdown(f"### Churn Probability: **{prob:.1%}**") | |
| if prob >= 0.4: | |
| st.markdown('<p class="risk-high">π₯ HIGH RISK β Immediate Action Needed</p>', unsafe_allow_html=True) | |
| st.warning("β’ Short tenure + month-to-month contract\nβ’ Fiber optic service\nβ’ No tech support\nβ’ Electronic check payment\n**Recommendation**: Offer discount, upgrade, or dedicated support") | |
| elif prob >= 0.2: | |
| st.markdown('<p class="risk-medium">π§ Medium Risk</p>', unsafe_allow_html=True) | |
| st.info("Monitor closely β consider proactive engagement") | |
| else: | |
| st.markdown('<p class="risk-low">π© Low Risk β Strong Retention</p>', unsafe_allow_html=True) | |
| st.success("Excellent loyalty signals β keep up the great service!") | |
| st.markdown("---") | |
| st.markdown("Powered by XGBoost β’ Built for SaaS teams β’ Premium futuristic design β’ Β© 2025") |