File size: 6,822 Bytes
8174974
e3ac22d
8174974
efa60b3
 
66128ac
efa60b3
49f0804
 
 
 
 
66128ac
b3f2d3d
efa60b3
0e52653
66128ac
0e52653
66128ac
 
 
 
b35a08e
 
0e52653
 
e3ac22d
 
 
68ffcfc
 
e3ac22d
 
 
68ffcfc
e3ac22d
68ffcfc
8174974
49f0804
0ca9296
49f0804
0ca9296
 
 
 
 
8174974
 
 
 
 
0ca9296
 
 
66128ac
8174974
 
 
 
b35a08e
49f0804
b35a08e
49f0804
b35a08e
 
 
66128ac
29a8952
 
 
 
 
 
 
 
 
 
 
 
 
 
223059a
 
29a8952
 
 
ef8cc0f
8174974
e16b3ce
29a8952
e3ac22d
 
8174974
 
e16b3ce
8174974
223059a
8174974
d40453d
e16b3ce
223059a
 
fb0a176
223059a
 
e16b3ce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e3ac22d
 
29a8952
 
e16b3ce
29a8952
e16b3ce
 
 
 
29a8952
fb0a176
e6fc2f8
29a8952
 
e6fc2f8
 
29a8952
e6fc2f8
29a8952
e3ac22d
29a8952
 
 
 
 
ef8cc0f
29a8952
 
8174974
ef8cc0f
29a8952
e3ac22d
e16b3ce
d40453d
e3ac22d
 
 
 
 
 
223059a
e3ac22d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Smart Customer Support Assistant (Enhanced UI Version)
# Note: Enhanced UI with role avatars, structured suggestions, and end chat functionality

import streamlit as st
from transformers import pipeline
import re

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")

candidate_tasks = [
    "change mobile plan",
    "top up balance",
    "report service outage",
    "ask for billing support",
    "reactivate service",
    "cancel subscription",
    "check account status",
    "upgrade device"
]

def generate_response(intent, human=True):
    if human:
        prompt = (
            f"You are a telecom customer service agent. For the customer intent '{intent}', provide a helpful reply using this 3-part format: "
            "[Greeting: short polite opener.] [Middle: Mention customer is currently using Plan X at Β₯X/month (fictional), recommend Plan Y with XXGB at Β₯Y/month (fictional).] [Ending: Ask if they want to proceed.]"
        )
    else:
        prompt = (
            f"You are a helpful telecom AI assistant. Answer the customer intent '{intent}' in a short, friendly, single sentence. Offer relevant support or recommendation directly, using fictional placeholders like Plan X, Β₯X, 10GB etc."
        )
    return text_generator(prompt, max_new_tokens=80, do_sample=False)[0]['generated_text']

urgent_emotions = {"anger", "frustration", "anxiety", "urgency", "afraid", "annoyed"}
moderate_emotions = {"confused", "sad", "tired", "concerned", "sadness"}

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

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": []}
customer_names = list(st.session_state.customers.keys())
selected_customer = st.sidebar.selectbox("Choose a customer:", customer_names)

if "chat_sessions" not in st.session_state:
    st.session_state.chat_sessions = {}
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)")

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'])

col1, col2 = st.columns([6,1])
with col1:
    session["user_input"] = st.text_input("Enter customer message:", value=session["user_input"])
with col2:
    analyze_clicked = st.button("Analyze", use_container_width=True)

if analyze_clicked and session["user_input"].strip():
    user_input = session["user_input"]
    session["chat"].append({"role": "user", "content": user_input})
    session["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=False)
        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"] = ""

if session["support_required"]:
    st.markdown(f"### {session['support_required']}")

st.subheader("Agent Response Console")
session["agent_reply"] = st.text_area("Compose your reply:", value=session["agent_reply"])
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"] = ""

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)

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.")