JoshuaZywoo commited on
Commit
8174974
·
verified ·
1 Parent(s): 0ca9296

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -99
app.py CHANGED
@@ -1,8 +1,13 @@
 
 
 
1
  import streamlit as st
2
  from transformers import pipeline
3
  import re
4
 
5
- # Load upgraded models
 
 
6
  emotion_classifier = pipeline(
7
  "text-classification",
8
  model="j-hartmann/emotion-english-distilroberta-base",
@@ -10,7 +15,9 @@ emotion_classifier = pipeline(
10
  )
11
  intent_classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
12
 
13
- # Candidate intents
 
 
14
  candidate_tasks = [
15
  "change mobile plan",
16
  "top up balance",
@@ -22,34 +29,52 @@ candidate_tasks = [
22
  "upgrade device"
23
  ]
24
 
25
- # Emotion scoring
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  urgent_emotions = {"anger", "frustration", "anxiety", "urgency", "afraid", "annoyed"}
27
  moderate_emotions = {"confused", "sad", "tired", "concerned", "sadness"}
28
 
29
- # ⬇️ 情绪判断(融合模型输出 + 语言信号)
30
- def get_emotion_label(emotion_result, text):
31
- sorted_emotions = sorted(emotion_result[0], key=lambda x: x['score'], reverse=True)
32
- top_emotion = sorted_emotions[0]['label']
33
- return refine_emotion_label(text, top_emotion)
34
-
35
  def refine_emotion_label(text, model_emotion):
36
  text_lower = text.lower()
37
  urgent_keywords = ["fix", "now", "immediately", "urgent", "can't", "need", "asap"]
38
  exclamations = text.count("!")
39
  upper_words = sum(1 for word in text.split() if word.isupper())
40
-
41
- signal_score = 0
42
- if any(word in text_lower for word in urgent_keywords):
43
- signal_score += 1
44
- if exclamations >= 2:
45
- signal_score += 1
46
- if upper_words >= 1:
47
- signal_score += 1
48
-
49
  if model_emotion.lower() in {"joy", "neutral", "sadness"} and signal_score >= 2:
50
  return "urgency"
51
  return model_emotion
52
 
 
 
 
 
53
  def get_emotion_score(emotion):
54
  if emotion.lower() in urgent_emotions:
55
  return 1.0
@@ -58,95 +83,85 @@ def get_emotion_score(emotion):
58
  else:
59
  return 0.2
60
 
61
- def get_content_score(text, top_intents):
62
- score = 0.0
63
- trigger_words = ["out of service", "urgent", "not working", "stopped", "can't", "immediately"]
64
- if any(kw in text.lower() for kw in trigger_words):
65
- score += 0.3
66
- if any(label in ["top up balance", "reactivate service", "report service outage"] for label in top_intents):
67
- score += 0.4
68
- if any(label in ["change mobile plan", "ask for billing support"] for label in top_intents):
69
- score += 0.2
70
- return min(score + 0.1, 1.0)
71
-
72
- def generate_reply(input_text, intent):
73
- intent_solutions = {
74
- "top up balance": "Your balance is ¥12. Current promo: recharge ¥100 get ¥5 bonus.",
75
- "reactivate service": "Your service is suspended due to unpaid ¥38. Recharge to restore within 30 mins.",
76
- "change mobile plan": "You're on Plan Basic (¥68/5GB). Suggest Plan Plus (¥98/20GB).",
77
- "check account status": "Your data usage is 3.2GB/5GB. Balance: ¥12. Calls left: 22 mins.",
78
- "ask for billing support": "Last bill was ¥96 for March. Includes data overage ¥16.",
79
- "cancel subscription": "Your contract ends on 2025-06-30. No penalty after this date.",
80
- "upgrade device": "You're eligible for upgrade. New iPhone plan starts at ¥399/month.",
81
- "report service outage": "We're detecting signal issues in your area (ZIP: XXX). Engineers notified."
82
- }
83
- intent_closings = {
84
- "top up balance": "Would you like to proceed with a recharge now?",
85
- "reactivate service": "Shall I help you restart your service now?",
86
- "report service outage": "Would you like me to file a service report for you?",
87
- "change mobile plan": "Would you like to switch to a better plan?",
88
- "ask for billing support": "Shall I show your last 3 billing records?",
89
- "cancel subscription": "Shall I guide you through cancellation?",
90
- "check account status": "Want a summary of your usage and balance?",
91
- "upgrade device": "Would you like me to show available upgrade options?"
92
- }
93
-
94
- solution = intent_solutions.get(intent.lower(), "Here's how we can assist you with this issue.")
95
- closing = intent_closings.get(intent.lower(), "Is there anything else I can help with?")
96
- opening = "Thank you for contacting us. I understand your concern."
97
- return f"{opening} {solution} {closing}"
98
-
99
- # UI
100
- st.set_page_config(page_title="Customer Support Assistant", layout="centered")
101
- st.title("📞 Smart Customer Support Assistant (for Agents Only)")
102
-
103
- user_input = st.text_area("Enter customer's message or complaint:", height=150)
104
-
105
- if st.button("Analyze Message"):
106
- if user_input.strip() == "":
107
- st.warning("Please enter a customer message.")
108
- else:
109
- with st.spinner("Processing..."):
110
-
111
- # Emotion detection (model + rule)
112
  emotion_result = emotion_classifier(user_input)
113
  emotion_label = get_emotion_label(emotion_result, user_input)
114
  emotion_score = get_emotion_score(emotion_label)
115
 
116
- # Intent detection
117
  intent_result = intent_classifier(user_input, candidate_tasks)
118
  top_intents = [label for label, score in zip(intent_result['labels'], intent_result['scores']) if score > 0.15][:3]
119
 
120
- # Content score
121
- content_score = get_content_score(user_input, top_intents)
 
 
 
122
 
123
- # Final decision score
124
- final_score = (0.5 * emotion_score) + (0.5 * content_score)
125
 
126
- st.subheader("🧾 System Summary")
 
127
 
128
- if final_score < 0.5:
129
- st.markdown("### 🟢 This message was handled automatically.")
130
- if top_intents:
131
- auto_intent = top_intents[0]
132
- auto_reply = generate_reply(user_input, auto_intent)
133
- st.markdown("#### 🤖 Auto-Response Sent to User:")
134
- st.success(auto_reply)
135
- else:
136
- st.info("No clear intent detected. A general auto-reply was used.")
137
  else:
138
- st.markdown("### 🔴 Human Support Required")
139
-
140
- # Customer Profile Summary
141
- st.markdown("#### 👤 Customer Status:")
142
- st.write(f"- **Emotion detected**: {emotion_label.capitalize()}")
143
- st.write(f"- **Tone**: {'Urgent' if emotion_score > 0.8 else 'Concerned' if emotion_score > 0.5 else 'Calm'}")
144
-
145
- if top_intents:
146
- st.markdown("#### 🧩 Detected Customer Needs:")
147
- for intent in top_intents:
148
- reply = generate_reply(user_input, intent)
149
- st.markdown(f"**• {intent.capitalize()}**")
150
- st.write(reply)
151
- else:
152
- st.warning("No clear intent detected. Manual review recommended.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Smart Customer Support Assistant (Enhanced UI Version)
2
+ # Note: Core analysis logic remains unchanged
3
+
4
  import streamlit as st
5
  from transformers import pipeline
6
  import re
7
 
8
+ # ------------------------------
9
+ # Load models (same as before)
10
+ # ------------------------------
11
  emotion_classifier = pipeline(
12
  "text-classification",
13
  model="j-hartmann/emotion-english-distilroberta-base",
 
15
  )
16
  intent_classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
17
 
18
+ # ------------------------------
19
+ # Candidate tasks / templates
20
+ # ------------------------------
21
  candidate_tasks = [
22
  "change mobile plan",
23
  "top up balance",
 
29
  "upgrade device"
30
  ]
31
 
32
+ intent_solutions = {
33
+ "top up balance": "Your balance is \u00a512. Promo: recharge \u00a5100 get \u00a55 bonus.",
34
+ "reactivate service": "Service suspended due to unpaid \u00a538. Recharge to restore in 30 mins.",
35
+ "change mobile plan": "You're on Basic (\u00a568/5GB). Suggest Plus (\u00a598/20GB).",
36
+ "check account status": "Data: 3.2GB/5GB. Balance: \u00a512. Calls left: 22 mins.",
37
+ "ask for billing support": "Last bill: \u00a596 (Mar). Includes \u00a516 overage.",
38
+ "cancel subscription": "Contract ends: 2025-06-30. No penalty after this date.",
39
+ "upgrade device": "Eligible for upgrade. New iPhone plan: \u00a5399/month.",
40
+ "report service outage": "Signal issues detected (ZIP: XXX). Engineers notified."
41
+ }
42
+
43
+ intent_closings = {
44
+ "top up balance": "Proceed with recharge now?",
45
+ "reactivate service": "Shall I help restart your service?",
46
+ "report service outage": "Shall I file a service report?",
47
+ "change mobile plan": "Switch to a better plan?",
48
+ "ask for billing support": "Show recent billing records?",
49
+ "cancel subscription": "Guide you through cancellation?",
50
+ "check account status": "Show usage and balance?",
51
+ "upgrade device": "See available upgrades?"
52
+ }
53
+
54
  urgent_emotions = {"anger", "frustration", "anxiety", "urgency", "afraid", "annoyed"}
55
  moderate_emotions = {"confused", "sad", "tired", "concerned", "sadness"}
56
 
57
+ # ------------------------------
58
+ # Emotion processing
59
+ # ------------------------------
 
 
 
60
  def refine_emotion_label(text, model_emotion):
61
  text_lower = text.lower()
62
  urgent_keywords = ["fix", "now", "immediately", "urgent", "can't", "need", "asap"]
63
  exclamations = text.count("!")
64
  upper_words = sum(1 for word in text.split() if word.isupper())
65
+ signal_score = sum([
66
+ any(word in text_lower for word in urgent_keywords),
67
+ exclamations >= 2,
68
+ upper_words >= 1
69
+ ])
 
 
 
 
70
  if model_emotion.lower() in {"joy", "neutral", "sadness"} and signal_score >= 2:
71
  return "urgency"
72
  return model_emotion
73
 
74
+ def get_emotion_label(emotion_result, text):
75
+ sorted_emotions = sorted(emotion_result[0], key=lambda x: x['score'], reverse=True)
76
+ return refine_emotion_label(text, sorted_emotions[0]['label'])
77
+
78
  def get_emotion_score(emotion):
79
  if emotion.lower() in urgent_emotions:
80
  return 1.0
 
83
  else:
84
  return 0.2
85
 
86
+ # ------------------------------
87
+ # Streamlit UI Logic
88
+ # ------------------------------
89
+ st.set_page_config(page_title="Smart Customer Support Assistant", layout="centered")
90
+ st.title("\ud83d\udcde Smart Customer Support Assistant (for Agents Only)")
91
+
92
+ # Session state to store chat
93
+ if 'chat' not in st.session_state:
94
+ st.session_state.chat = []
95
+ if 'system_result' not in st.session_state:
96
+ st.session_state.system_result = None
97
+ if 'agent_reply' not in st.session_state:
98
+ st.session_state.agent_reply = ""
99
+
100
+ # Display chat history
101
+ for msg in st.session_state.chat:
102
+ with st.chat_message(msg['role']):
103
+ st.markdown(msg['content'])
104
+
105
+ # Customer input + Analyze button
106
+ col1, col2 = st.columns([5,1])
107
+ with col1:
108
+ user_input = st.text_input("Enter customer message:", key="user_input")
109
+ with col2:
110
+ if st.button("Analyze"):
111
+ if user_input.strip():
112
+ # Run analysis pipeline
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  emotion_result = emotion_classifier(user_input)
114
  emotion_label = get_emotion_label(emotion_result, user_input)
115
  emotion_score = get_emotion_score(emotion_label)
116
 
 
117
  intent_result = intent_classifier(user_input, candidate_tasks)
118
  top_intents = [label for label, score in zip(intent_result['labels'], intent_result['scores']) if score > 0.15][:3]
119
 
120
+ content_score = 0.0
121
+ if any(x in user_input.lower() for x in ["out of service", "can't", "urgent", "immediately"]):
122
+ content_score += 0.4
123
+ if any(label in ["top up balance", "reactivate service"] for label in top_intents):
124
+ content_score += 0.4
125
 
126
+ final_score = 0.5 * emotion_score + 0.5 * content_score
 
127
 
128
+ # Store user message
129
+ st.session_state.chat.append({"role": "user", "content": user_input})
130
 
131
+ # Auto response or escalate to agent
132
+ if final_score < 0.5 and top_intents:
133
+ intent = top_intents[0]
134
+ response = f"Thank you for contacting us. I understand your concern. {intent_solutions[intent]} {intent_closings[intent]}"
135
+ st.session_state.chat.append({"role": "assistant", "content": response})
 
 
 
 
136
  else:
137
+ st.session_state.system_result = {
138
+ "emotion": emotion_label,
139
+ "tone": "Urgent" if emotion_score > 0.8 else "Concerned" if emotion_score > 0.5 else "Calm",
140
+ "intents": top_intents
141
+ }
142
+
143
+ # If human support needed
144
+ if st.session_state.system_result:
145
+ st.markdown("---")
146
+ st.subheader("\ud83d\udc69\u200d\ud83d\udcbb Agent Response Panel")
147
+
148
+ # Agent editable response
149
+ st.session_state.agent_reply = st.text_area("Compose your reply:", value=st.session_state.agent_reply)
150
+ if st.button("Send Reply"):
151
+ if st.session_state.agent_reply.strip():
152
+ st.session_state.chat.append({"role": "assistant", "content": st.session_state.agent_reply})
153
+ st.session_state.agent_reply = ""
154
+ st.session_state.system_result = None
155
+
156
+ # Context info
157
+ st.markdown("#### \ud83d\udc64 Customer Status")
158
+ st.markdown(f"- **Emotion:** {st.session_state.system_result['emotion'].capitalize()}")
159
+ st.markdown(f"- **Tone:** {st.session_state.system_result['tone']}")
160
+
161
+ # Suggested replies
162
+ st.markdown("#### \ud83e\uddf0 Detected Customer Needs")
163
+ for intent in st.session_state.system_result['intents']:
164
+ st.markdown(f"**• {intent.capitalize()}**")
165
+ suggestion = f"Thank you for contacting us. I understand your concern. {intent_solutions[intent]} {intent_closings[intent]}"
166
+ if st.button(f"Use suggestion for '{intent}'", key=intent):
167
+ st.session_state.agent_reply = suggestion