Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from transformers import pipeline | |
| import pandas as pd | |
| from datetime import datetime | |
| import os | |
| # ---------------------------------------------------- | |
| # Load pretrained Hugging Face emotion model | |
| # ---------------------------------------------------- | |
| model_name = "superb/hubert-large-superb-er" | |
| emotion_classifier = pipeline("audio-classification", model=model_name) | |
| # Emotion mapping | |
| EMOTION_MAP = { | |
| "ang": ("Angry", "π‘"), | |
| "hap": ("Happy", "π"), | |
| "neu": ("Neutral", "π"), | |
| "sad": ("Sad", "π’"), | |
| "exc": ("Excited", "π€©"), | |
| "fru": ("Frustrated", "π€"), | |
| "fea": ("Fearful", "π¨"), | |
| "sur": ("Surprised", "π²"), | |
| "dis": ("Disgusted", "π€’"), | |
| } | |
| # ---------------------------------------------------- | |
| # Setup data storage | |
| # ---------------------------------------------------- | |
| os.makedirs("data", exist_ok=True) | |
| CSV_PATH = "data/customer_complaints_emotion.csv" | |
| ORDER_ISSUES = [ | |
| "Late Delivery", | |
| "Damaged Package", | |
| "Wrong Product Delivered", | |
| "Missing Items", | |
| "Rude Delivery Staff", | |
| "Payment Issue", | |
| "Return/Refund Request", | |
| "Order Cancelled Automatically", | |
| "Other Complaint" | |
| ] | |
| # ---------------------------------------------------- | |
| # Priority estimation | |
| # ---------------------------------------------------- | |
| def get_priority(label, score): | |
| if label in ["Angry", "Frustrated", "Fearful", "Disgusted"] and score >= 60: | |
| return "π΄ High Priority" | |
| elif label in ["Sad", "Surprised", "Excited"] and score >= 50: | |
| return "π Medium Priority" | |
| else: | |
| return "π’ Low Priority" | |
| # ---------------------------------------------------- | |
| # Main analysis function | |
| # ---------------------------------------------------- | |
| def analyze_complaint(audio_file, complaint_type, order_id): | |
| if audio_file is None or not complaint_type or not order_id: | |
| return ( | |
| "β οΈ Please upload an audio complaint, select issue type, and enter Order ID.", | |
| "", | |
| None | |
| ) | |
| # Run model | |
| results = emotion_classifier(audio_file) | |
| results = sorted(results, key=lambda x: x['score'], reverse=True) | |
| top = results[0] | |
| label, emoji = EMOTION_MAP.get(top['label'], (top['label'], "π")) | |
| score = round(top['score'] * 100, 2) | |
| priority = get_priority(label, score) | |
| # Dashboard summary (markdown) | |
| summary = f""" | |
| ### π― Detected Emotion: {emoji} **{label.upper()} ({score}%)** | |
| ### β‘ Priority Level: {priority} | |
| --- | |
| **Complaint Type:** {complaint_type} | |
| **Order ID:** {order_id} | |
| **Timestamp:** {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} | |
| """ | |
| # Detailed emotion breakdown | |
| breakdown = "### π Emotion Breakdown\n" | |
| for r in results: | |
| lbl, emo = EMOTION_MAP.get(r['label'], (r['label'], "π")) | |
| scr = round(r['score'] * 100, 2) | |
| bar = "β" * int(scr / 5) | |
| breakdown += f"{emo} **{lbl}**: {scr}% \n{bar}\n\n" | |
| # Save log to CSV | |
| df = pd.DataFrame({ | |
| "datetime": [datetime.now().strftime("%Y-%m-%d %H:%M:%S")], | |
| "order_id": [order_id], | |
| "complaint_type": [complaint_type], | |
| "emotion": [label], | |
| "score": [score], | |
| "priority": [priority] | |
| }) | |
| if os.path.exists(CSV_PATH): | |
| df.to_csv(CSV_PATH, mode="a", header=False, index=False) | |
| else: | |
| df.to_csv(CSV_PATH, index=False) | |
| # Display updated log | |
| try: | |
| log_df = pd.read_csv(CSV_PATH).tail(10) | |
| except: | |
| log_df = pd.DataFrame() | |
| return summary, breakdown, log_df | |
| # ---------------------------------------------------- | |
| # Gradio Interface with Blocks | |
| # ---------------------------------------------------- | |
| with gr.Blocks(theme=gr.themes.Soft(), title="Customer Complaint Emotion Analyzer") as app: | |
| gr.Markdown( | |
| """ | |
| # π§ Customer Complaint Emotion Analyzer | |
| Analyze customer **voice complaints** to detect emotional tone and **auto-prioritize** based on urgency. | |
| Ideal for logistics, delivery, and supply chain customer service operations. | |
| --- | |
| """ | |
| ) | |
| with gr.Row(): | |
| audio_input = gr.Audio(type="filepath", label="ποΈ Upload Complaint Audio") | |
| complaint_type = gr.Dropdown(ORDER_ISSUES, label="π Complaint Type", interactive=True) | |
| order_id = gr.Textbox(label="π¦ Order ID / Reference Number", placeholder="e.g., ORD123456") | |
| analyze_btn = gr.Button("π Analyze Complaint", variant="primary") | |
| with gr.Row(): | |
| summary_output = gr.Markdown(label="Summary") | |
| breakdown_output = gr.Markdown(label="Detailed Breakdown") | |
| with gr.Accordion("π Recent Complaint Logs (Last 10 Entries)", open=False): | |
| log_table = gr.Dataframe(headers=["datetime", "order_id", "complaint_type", "emotion", "score", "priority"], interactive=False) | |
| analyze_btn.click( | |
| fn=analyze_complaint, | |
| inputs=[audio_input, complaint_type, order_id], | |
| outputs=[summary_output, breakdown_output, log_table], | |
| ) | |
| gr.Markdown("---") | |
| gr.Markdown("π¨βπΌ **Developed for Supply Chain Customer Service Emotion Monitoring.**") | |
| # ---------------------------------------------------- | |
| # Run app | |
| # ---------------------------------------------------- | |
| if __name__ == "__main__": | |
| app.launch() | |