JoshuaZywoo's picture
Update app.py
ef8cc0f verified
raw
history blame
6.86 kB
# Smart Customer Support Assistant (Enhanced UI Version)
# Note: Core analysis logic remains unchanged
import streamlit as st
from transformers import pipeline
import re
# ------------------------------
# Load models (same as before)
# ------------------------------
emotion_classifier = pipeline(
"text-classification",
model="j-hartmann/emotion-english-distilroberta-base",
return_all_scores=True
)
intent_classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
# ------------------------------
# Candidate tasks / templates
# ------------------------------
candidate_tasks = [
"change mobile plan",
"top up balance",
"report service outage",
"ask for billing support",
"reactivate service",
"cancel subscription",
"check account status",
"upgrade device"
]
intent_solutions = {
"top up balance": "Your balance is ¥12. Promo: recharge ¥100 get ¥5 bonus.",
"reactivate service": "Service suspended due to unpaid ¥38. Recharge to restore in 30 mins.",
"change mobile plan": "You're on Basic (¥68/5GB). Suggest Plus (¥98/20GB).",
"check account status": "Data: 3.2GB/5GB. Balance: ¥12. Calls left: 22 mins.",
"ask for billing support": "Last bill: ¥96 (Mar). Includes ¥16 overage.",
"cancel subscription": "Contract ends: 2025-06-30. No penalty after this date.",
"upgrade device": "Eligible for upgrade. New iPhone plan: ¥399/month.",
"report service outage": "Signal issues detected (ZIP: XXX). Engineers notified."
}
intent_closings = {
"top up balance": "Proceed with recharge now?",
"reactivate service": "Shall I help restart your service?",
"report service outage": "Shall I file a service report?",
"change mobile plan": "Switch to a better plan?",
"ask for billing support": "Show recent billing records?",
"cancel subscription": "Guide you through cancellation?",
"check account status": "Show usage and balance?",
"upgrade device": "See available upgrades?"
}
urgent_emotions = {"anger", "frustration", "anxiety", "urgency", "afraid", "annoyed"}
moderate_emotions = {"confused", "sad", "tired", "concerned", "sadness"}
# ------------------------------
# Emotion processing
# ------------------------------
def refine_emotion_label(text, model_emotion):
text_lower = text.lower()
urgent_keywords = ["fix", "now", "immediately", "urgent", "can't", "need", "asap"]
exclamations = text.count("!")
upper_words = sum(1 for word in text.split() if word.isupper())
signal_score = sum([
any(word in text_lower for word in urgent_keywords),
exclamations >= 2,
upper_words >= 1
])
if model_emotion.lower() in {"joy", "neutral", "sadness"} and signal_score >= 2:
return "urgency"
return model_emotion
def get_emotion_label(emotion_result, text):
sorted_emotions = sorted(emotion_result[0], key=lambda x: x['score'], reverse=True)
return refine_emotion_label(text, sorted_emotions[0]['label'])
def get_emotion_score(emotion):
if emotion.lower() in urgent_emotions:
return 1.0
elif emotion.lower() in moderate_emotions:
return 0.6
else:
return 0.2
# ------------------------------
# Streamlit UI Logic
# ------------------------------
st.set_page_config(page_title="Smart Customer Support Assistant", layout="centered")
st.title("Smart Customer Support Assistant (for Agents Only)")
# Session state to store chat
if 'chat' not in st.session_state:
st.session_state.chat = []
if 'system_result' not in st.session_state:
st.session_state.system_result = None
if 'agent_reply' not in st.session_state:
st.session_state.agent_reply = ""
# Display chat history
for msg in st.session_state.chat:
with st.chat_message(msg['role']):
st.markdown(msg['content'])
# Customer input + Analyze button
col1, col2 = st.columns([5,1])
with col1:
user_input = st.text_input("Enter customer message:", key="user_input")
with col2:
if st.button("Analyze"):
if user_input.strip():
# Run analysis pipeline
emotion_result = emotion_classifier(user_input)
emotion_label = get_emotion_label(emotion_result, user_input)
emotion_score = get_emotion_score(emotion_label)
intent_result = intent_classifier(user_input, candidate_tasks)
top_intents = [label for label, score in zip(intent_result['labels'], intent_result['scores']) if score > 0.15][:3]
content_score = 0.0
if any(x in user_input.lower() for x in ["out of service", "can't", "urgent", "immediately"]):
content_score += 0.4
if any(label in ["top up balance", "reactivate service"] for label in top_intents):
content_score += 0.4
final_score = 0.5 * emotion_score + 0.5 * content_score
# Store user message
st.session_state.chat.append({"role": "user", "content": user_input})
# Auto response or escalate to agent
if final_score < 0.5 and top_intents:
intent = top_intents[0]
response = f"Thank you for contacting us. I understand your concern. {intent_solutions[intent]} {intent_closings[intent]}"
st.session_state.chat.append({"role": "assistant", "content": response})
else:
st.session_state.system_result = {
"emotion": emotion_label,
"tone": "Urgent" if emotion_score > 0.8 else "Concerned" if emotion_score > 0.5 else "Calm",
"intents": top_intents
}
# If human support needed
if st.session_state.system_result:
st.markdown("---")
st.subheader("Agent Response Panel")
# Agent editable response
st.session_state.agent_reply = st.text_area("Compose your reply:", value=st.session_state.agent_reply)
if st.button("Send Reply"):
if st.session_state.agent_reply.strip():
st.session_state.chat.append({"role": "assistant", "content": st.session_state.agent_reply})
st.session_state.agent_reply = ""
st.session_state.system_result = None
# Context info
st.markdown("#### Customer Status")
st.markdown(f"- **Emotion:** {st.session_state.system_result['emotion'].capitalize()}")
st.markdown(f"- **Tone:** {st.session_state.system_result['tone']}")
# Suggested replies
st.markdown("#### Detected Customer Needs")
for intent in st.session_state.system_result['intents']:
st.markdown(f"**• {intent.capitalize()}**")
suggestion = f"Thank you for contacting us. I understand your concern. {intent_solutions[intent]} {intent_closings[intent]}"
if st.button(f"Use suggestion for '{intent}'", key=intent):
st.session_state.agent_reply = suggestion