JoshuaZywoo's picture
Update app.py
07994df verified
raw
history blame
6.97 kB
import streamlit as st
from transformers import pipeline
# Load Models
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")
text_generator = pipeline("text2text-generation", model="declare-lab/flan-alpaca-base")
# Tasks
candidate_tasks = [
"change mobile plan", "top up balance", "report service outage",
"ask for billing support", "reactivate service", "cancel subscription",
"check account status", "upgrade device"
]
# Emotion Tiers
urgent_emotions = {"anger", "frustration", "anxiety", "urgency", "afraid", "annoyed"}
moderate_emotions = {"confused", "sad", "tired", "concerned", "sadness"}
# Utilities
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 w in text.split() if w.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(result, text):
sorted_emotions = sorted(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
def generate_response(intent, human=True):
if human:
prompt = (
f"You are a telecom customer service agent. For the customer intent '{intent}', generate a professional 3-part response:\n"
"1. Greeting (e.g., Thank you for contacting us...)\n"
"2. Current plan summary (e.g., You're currently on Plan X at Β₯X/month. We suggest Plan Y with XXGB for Β₯Y/month.)\n"
"3. Close with a question (e.g., Would you like to switch?)"
)
else:
prompt = (
f"As a telecom assistant, generate a full 3-part structured response for customer intent: '{intent}'.\n"
"Include greeting, summary of their current plan and a better offer (fictional), and end with a follow-up question."
)
result = text_generator(prompt, max_new_tokens=120, do_sample=False)
return result[0]['generated_text'].strip()
# App UI Setup
st.set_page_config(page_title="Smart Customer Support Assistant", layout="wide")
st.sidebar.title("πŸ“ Customer Selector")
if "customers" not in st.session_state:
st.session_state.customers = {"Customer A": [], "Customer B": [], "Customer C": []}
if "chat_sessions" not in st.session_state:
st.session_state.chat_sessions = {}
selected_customer = st.sidebar.selectbox("Choose a customer:", list(st.session_state.customers.keys()))
if selected_customer not in st.session_state.chat_sessions:
st.session_state.chat_sessions[selected_customer] = {
"chat": [], "system_result": None,
"agent_reply": "", "support_required": "", "user_input": ""
}
session = st.session_state.chat_sessions[selected_customer]
st.title("Smart Customer Support Assistant (for Agents Only)")
# Conversation Window
st.markdown("### Conversation")
for msg in session["chat"]:
avatar = "πŸ‘€" if msg['role'] == 'user' else ("πŸ€–" if msg.get("auto") else "πŸ‘¨β€πŸ’Ό")
with st.chat_message(msg['role'], avatar=avatar):
st.markdown(msg['content'])
# Input & Analysis
col1, col2 = st.columns([6, 1])
with col1:
user_input = st.text_input("Enter customer message:", key="customer_input")
with col2:
if st.button("Analyze"):
if user_input.strip():
session["chat"].append({"role": "user", "content": user_input})
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
if final_score < 0.5 and top_intents:
intent = top_intents[0]
response = generate_response(intent, human=True)
session["chat"].append({"role": "assistant", "content": response, "auto": True})
session["system_result"] = None
session["support_required"] = "🟒 Automated response handled this request."
else:
session["system_result"] = {
"emotion": emotion_label,
"tone": "Urgent" if emotion_score > 0.8 else "Concerned" if emotion_score > 0.5 else "Calm",
"intents": top_intents
}
session["support_required"] = "πŸ”΄ Human support required."
session["agent_reply"] = ""
st.rerun()
# Support Tag
if session["support_required"]:
st.markdown(f"### {session['support_required']}")
# Agent Reply Console
st.subheader("Agent Response Console")
session["agent_reply"] = st.text_area("Compose your reply:", value=session["agent_reply"], key="agent_reply_box")
if st.button("Send Reply"):
if session["agent_reply"].strip():
session["chat"].append({"role": "assistant", "content": session["agent_reply"], "auto": False})
session["agent_reply"] = ""
session["system_result"] = None
session["support_required"] = ""
st.experimental_rerun()
# Human Needed View
if session["system_result"] is not None:
st.markdown("#### Customer Status")
st.markdown(f"- **Emotion:** {session['system_result']['emotion'].capitalize()}")
st.markdown(f"- **Tone:** {session['system_result']['tone']}")
st.markdown("#### Detected Customer Needs")
for intent in session["system_result"]["intents"]:
suggestion = generate_response(intent, human=True)
st.markdown(f"**β€’ {intent.capitalize()}**")
st.code(suggestion)
# End Button
if st.button("End Conversation"):
session["chat"] = []
session["system_result"] = None
session["agent_reply"] = ""
session["support_required"] = ""
session["user_input"] = ""
st.success("Conversation ended and cleared.")
st.rerun()