Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import joblib | |
| rf_model = joblib.load("rf_model.pkl") | |
| feature_cols = joblib.load("feature_cols.pkl") | |
| gender_map = {'Female': 0, 'Male': 1} | |
| partner_map = {'No': 0, 'Yes': 1} | |
| dependents_map = {'No': 0, 'Yes': 1} | |
| contract_map = {'Month-to-month': 0, 'One year': 1, 'Two year': 2} | |
| payment_map = { | |
| 'Bank transfer (automatic)': 0, | |
| 'Credit card (automatic)': 1, | |
| 'Electronic check': 2, | |
| 'Mailed check': 3 | |
| } | |
| internet_map = {'DSL': 0, 'Fiber optic': 1, 'No': 2} | |
| tech_map = {'No': 0, 'No internet service': 1, 'Yes': 2} | |
| complaint_map = { | |
| 'Billing Issue': 0, | |
| 'Contract Dispute': 1, | |
| 'Overcharge': 2, | |
| 'Service Outage': 3, | |
| 'Speed/Performance': 4, | |
| 'Technical Failure': 5 | |
| } | |
| risk_map = {'High': 0, 'Low': 1, 'Medium': 2} | |
| def predict_churn( | |
| tenure, | |
| monthly_charges, | |
| total_charges, | |
| senior, | |
| gender, | |
| partner, | |
| dependents, | |
| contract, | |
| payment, | |
| internet, | |
| tech, | |
| support_calls, | |
| avg_call_duration, | |
| days_since_last_contact, | |
| sentiment, | |
| complaint, | |
| risk | |
| ): | |
| try: | |
| input_df = pd.DataFrame([{ | |
| 'SeniorCitizen': senior, | |
| 'tenure': tenure, | |
| 'MonthlyCharges': monthly_charges, | |
| 'TotalCharges': total_charges, | |
| 'gender_enc': gender_map[gender], | |
| 'Partner_enc': partner_map[partner], | |
| 'Dependents_enc': dependents_map[dependents], | |
| 'Contract_enc': contract_map[contract], | |
| 'PaymentMethod_enc': payment_map[payment], | |
| 'InternetService_enc': internet_map[internet], | |
| 'TechSupport_enc': tech_map[tech], | |
| 'support_calls': support_calls, | |
| 'avg_call_duration': avg_call_duration, | |
| 'days_since_last_contact': days_since_last_contact, | |
| 'sentiment_score': sentiment, | |
| 'complaint_type_enc': complaint_map[complaint], | |
| 'support_churn_risk_enc': risk_map[risk] | |
| }]) | |
| input_df = input_df[feature_cols] | |
| pred = rf_model.predict(input_df)[0] | |
| prob = rf_model.predict_proba(input_df)[0][1] | |
| if prob >= 0.75: | |
| risk_level = "High" | |
| recommendation = "Immediate retention outreach and service recovery." | |
| elif prob >= 0.40: | |
| risk_level = "Medium" | |
| recommendation = "Proactive follow-up and customer care check-in." | |
| else: | |
| risk_level = "Low" | |
| recommendation = "Maintain normal engagement and service quality." | |
| churn_label = "Yes" if pred == 1 else "No" | |
| drivers = [] | |
| if contract == "Month-to-month": | |
| drivers.append("month-to-month contract") | |
| if support_calls >= 5: | |
| drivers.append("frequent support calls") | |
| if sentiment < 0: | |
| drivers.append("negative sentiment") | |
| if tech == "No": | |
| drivers.append("lack of tech support") | |
| if monthly_charges > 80: | |
| drivers.append("higher monthly charges") | |
| if drivers: | |
| explanation = "Main risk drivers: " + ", ".join(drivers) + "." | |
| else: | |
| explanation = "Risk is based on the combined customer, billing, and support profile." | |
| return churn_label, f"{prob:.2%}", risk_level, explanation, recommendation | |
| except Exception as e: | |
| return "Error", "Error", "Error", f"Something went wrong: {str(e)}", "Please review the inputs." | |
| with gr.Blocks(title="ChurnGuard – AI Customer Retention Advisor") as demo: | |
| gr.Markdown(""" | |
| # ChurnGuard – AI Customer Retention Advisor | |
| This app turns our churn model into a decision-support tool for telecom retention strategy. | |
| It combines billing, contract, demographic, and synthetic support-interaction features to estimate churn risk. | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| gr.Markdown("## Customer Profile") | |
| senior = gr.Dropdown([0, 1], value=0, label="Senior Citizen (0 = No, 1 = Yes)") | |
| gender = gr.Dropdown(['Female', 'Male'], value='Female', label="Gender") | |
| partner = gr.Dropdown(['No', 'Yes'], value='No', label="Partner") | |
| dependents = gr.Dropdown(['No', 'Yes'], value='No', label="Dependents") | |
| tenure = gr.Slider(0, 72, value=12, step=1, label="Tenure (months)") | |
| gr.Markdown("## Service & Contract") | |
| monthly_charges = gr.Slider(0, 150, value=70, step=0.1, label="Monthly Charges") | |
| total_charges = gr.Slider(0, 10000, value=1000, step=1, label="Total Charges") | |
| contract = gr.Dropdown(['Month-to-month', 'One year', 'Two year'], value='Month-to-month', label="Contract") | |
| payment = gr.Dropdown([ | |
| 'Bank transfer (automatic)', | |
| 'Credit card (automatic)', | |
| 'Electronic check', | |
| 'Mailed check' | |
| ], value='Bank transfer (automatic)', label="Payment Method") | |
| internet = gr.Dropdown(['DSL', 'Fiber optic', 'No'], value='DSL', label="Internet Service") | |
| tech = gr.Dropdown(['No', 'No internet service', 'Yes'], value='No', label="Tech Support") | |
| gr.Markdown("## Support Interaction Signals") | |
| support_calls = gr.Slider(0, 15, value=3, step=1, label="Support Calls") | |
| avg_call_duration = gr.Slider(0, 30, value=8, step=0.1, label="Average Call Duration (minutes)") | |
| days_since_last_contact = gr.Slider(0, 120, value=20, step=1, label="Days Since Last Contact") | |
| sentiment = gr.Slider(-1, 1, value=0, step=0.01, label="Sentiment Score") | |
| complaint = gr.Dropdown([ | |
| 'Billing Issue', | |
| 'Contract Dispute', | |
| 'Overcharge', | |
| 'Service Outage', | |
| 'Speed/Performance', | |
| 'Technical Failure' | |
| ], value='Billing Issue', label="Complaint Type") | |
| risk = gr.Dropdown(['High', 'Low', 'Medium'], value='Low', label="Support Churn Risk") | |
| submit_btn = gr.Button("Predict Churn Risk", variant="primary") | |
| with gr.Column(scale=1): | |
| gr.Markdown("## Prediction Results") | |
| pred_out = gr.Textbox(label="Predicted Churn") | |
| prob_out = gr.Textbox(label="Churn Probability") | |
| risk_out = gr.Textbox(label="Risk Level") | |
| explanation_out = gr.Textbox(label="Explanation") | |
| recommendation_out = gr.Textbox(label="Recommended Action") | |
| submit_btn.click( | |
| fn=predict_churn, | |
| inputs=[ | |
| tenure, monthly_charges, total_charges, senior, gender, partner, dependents, | |
| contract, payment, internet, tech, support_calls, avg_call_duration, | |
| days_since_last_contact, sentiment, complaint, risk | |
| ], | |
| outputs=[pred_out, prob_out, risk_out, explanation_out, recommendation_out] | |
| ) | |
| demo.launch() |