ISOM5240GP4 commited on
Commit
9d82315
·
verified ·
1 Parent(s): 58687a0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -135
app.py CHANGED
@@ -3,70 +3,47 @@ from transformers import pipeline, AutoModelForSequenceClassification, AutoToken
3
  import torch
4
  import numpy as np
5
 
6
- # Load models with caching to improve performance
7
- @st.cache_resource
8
- def load_spam_pipeline():
9
- return pipeline("text-classification", model="cybersectony/phishing-email-detection-distilbert_v2.4.1")
10
-
11
- @st.cache_resource
12
- def load_sentiment_model():
13
- model = AutoModelForSequenceClassification.from_pretrained("ISOM5240GP4/email_sentiment", num_labels=2)
14
  tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
15
- return model, tokenizer
16
 
17
- # Initialize models
18
- spam_pipeline = load_spam_pipeline()
19
- sentiment_model, tokenizer = load_sentiment_model()
20
 
21
- # Function to analyze email
22
- def analyze_email(email_body):
23
- """Analyzes an email for spam and sentiment, returning result type and message."""
24
- if not email_body.strip():
25
- return "error", "Email body is empty. Please provide an email to analyze."
26
-
27
- try:
28
- # Step 1: Check if the email is spam
29
- spam_result = spam_pipeline(email_body)
30
- spam_label = spam_result[0]["label"] # LABEL_1 indicates spam
31
- spam_confidence = spam_result[0]["score"]
32
-
33
- if spam_label == "LABEL_1":
34
- return "spam", f"This is a spam email (Confidence: {spam_confidence:.2f}). No follow-up needed."
35
  else:
36
- # Step 2: Analyze sentiment for non-spam emails
37
- inputs = tokenizer(email_body, padding=True, truncation=True, return_tensors='pt')
38
- outputs = sentiment_model(**inputs)
39
- predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
40
- predictions = predictions.cpu().detach().numpy()
41
- sentiment_index = np.argmax(predictions)
42
- sentiment_confidence = predictions[0][sentiment_index]
43
- sentiment = "Positive" if sentiment_index == 1 else "Negative"
44
-
45
- if sentiment == "Positive":
46
- return "positive", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
47
- f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}). No follow-up needed.")
48
- else:
49
- return "negative", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
50
- f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}).\n"
51
- "<b>Need to Follow-Up</b>: This email is not spam and has negative sentiment.")
52
- except Exception as e:
53
- return "error", f"An error occurred during analysis: {str(e)}"
54
 
55
- # Main application function
56
  def main():
57
- # Set title and objective
58
  st.title("EmailSentry")
59
  st.write("Aims to perform analysis on incoming emails and to determine whether there is urgency or higher priority for the company to follow-up.")
60
-
61
- # Initialize session state variables
62
  if "email_body" not in st.session_state:
63
  st.session_state.email_body = ""
64
  if "result" not in st.session_state:
65
  st.session_state.result = ""
66
  if "result_type" not in st.session_state:
67
  st.session_state.result_type = ""
68
-
69
- # Instructions section
70
  with st.expander("How to Use", expanded=False):
71
  st.write("""
72
  - Type or paste an email into the text box.
@@ -74,11 +51,11 @@ def main():
74
  - Press 'Analyze Email' to check if it’s spam and analyze its sentiment.
75
  - Use 'Clear' to reset the input and result.
76
  """)
77
-
78
  # Text area for email input
79
  email_body = st.text_area("Email Body", value=st.session_state.email_body, height=200, key="email_input")
80
-
81
- # Define sample emails
82
  sample_spam = """
83
  Subject: Urgent: Verify Your Account Now!
84
  Dear Customer,
@@ -89,7 +66,7 @@ Best regards,
89
  The Security Team
90
  """
91
  spam_snippet = "Subject: Urgent: Verify Your Account Now! Dear Customer, We have detected unusual activity..."
92
-
93
  sample_not_spam_positive = """
94
  Subject: Great Experience with HKTV mall
95
  Dear Sir,
@@ -98,7 +75,7 @@ Best regards,
98
  Emily
99
  """
100
  positive_snippet = "Subject: Great Experience with HKTV mall Dear Sir, I just received my order and I’m really..."
101
-
102
  sample_not_spam_negative = """
103
  Subject: Issue with Recent Delivery
104
  Dear Support,
@@ -107,9 +84,67 @@ Thanks,
107
  Sarah
108
  """
109
  negative_snippet = "Subject: Issue with Recent Delivery Dear Support, I received my package today, but..."
110
-
111
- # Display sample buttons
112
- st.subheader("Examples")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  col1, col2, col3 = st.columns(3)
114
  with col1:
115
  if st.button(spam_snippet, key="spam_sample"):
@@ -129,11 +164,11 @@ Sarah
129
  st.session_state.result = ""
130
  st.session_state.result_type = ""
131
  st.rerun()
132
-
133
- # Action buttons
134
- col_analyze, col_clear = st.columns(2)
135
  with col_analyze:
136
- if st.button("Analyze Email", key="analyze"):
137
  if email_body:
138
  with st.spinner("Analyzing email..."):
139
  result_type, result = analyze_email(email_body)
@@ -142,15 +177,14 @@ Sarah
142
  else:
143
  st.session_state.result = "Please enter an email body or select a sample to analyze."
144
  st.session_state.result_type = ""
145
-
146
  with col_clear:
147
  if st.button("Clear", key="clear"):
148
  st.session_state.email_body = ""
149
  st.session_state.result = ""
150
  st.session_state.result_type = ""
151
  st.rerun()
152
-
153
- # Display analysis result
154
  if st.session_state.result:
155
  if st.session_state.result_type == "spam":
156
  st.markdown(f'<div class="spam-result">{st.session_state.result}</div>', unsafe_allow_html=True)
@@ -159,76 +193,7 @@ Sarah
159
  elif st.session_state.result_type == "negative":
160
  st.markdown(f'<div class="negative-result">{st.session_state.result}</div>', unsafe_allow_html=True)
161
  else:
162
- st.write(st.session_state.result)
163
-
164
- # Inject custom CSS without !important, based on your previous working code
165
- st.markdown("""
166
- <style>
167
- /* Style for sample buttons (light grey) */
168
- div.stButton > button[kind="secondary"]:not([key="clear"]) {
169
- font-size: 12px;
170
- padding: 5px 10px;
171
- background-color: #f0f0f0;
172
- color: #333333;
173
- border: 1px solid #cccccc;
174
- border-radius: 3px;
175
- }
176
- /* Analyze Email button (orange) */
177
- div.stButton > button[key="analyze"] {
178
- background-color: #FF5733;
179
- color: white;
180
- font-size: 18px;
181
- padding: 12px 24px;
182
- border: none;
183
- border-radius: 5px;
184
- width: 100%;
185
- height: 50px;
186
- box-sizing: border-box;
187
- text-align: center;
188
- }
189
- div.stButton > button[key="analyze"]:hover {
190
- background-color: #E74C3C;
191
- }
192
- /* Clear button (blue) */
193
- div.stButton > button[key="clear"] {
194
- background-color: #007BFF;
195
- color: white;
196
- font-size: 18px;
197
- padding: 12px 24px;
198
- border: none;
199
- border-radius: 5px;
200
- width: 100%;
201
- height: 50px;
202
- box-sizing: border-box;
203
- text-align: center;
204
- }
205
- div.stButton > button[key="clear"]:hover {
206
- background-color: #0056b3;
207
- }
208
- /* Result boxes */
209
- .spam-result {
210
- background-color: #ff3333;
211
- color: white;
212
- padding: 10px;
213
- border-radius: 5px;
214
- border: 1px solid #cc0000;
215
- }
216
- .positive-result {
217
- background-color: #ff3333;
218
- color: white;
219
- padding: 10px;
220
- border-radius: 5px;
221
- border: 1px solid #cc0000;
222
- }
223
- .negative-result {
224
- background-color: #006633;
225
- color: white;
226
- padding: 10px;
227
- border-radius: 5px;
228
- border: 1px solid #004d26;
229
- }
230
- </style>
231
- """, unsafe_allow_html=True)
232
 
233
  if __name__ == "__main__":
234
  main()
 
3
  import torch
4
  import numpy as np
5
 
6
+ def analyze_email(email_body):
7
+ spam_pipeline = pipeline("text-classification", model="cybersectony/phishing-email-detection-distilbert_v2.4.1")
8
+ sentiment_model = AutoModelForSequenceClassification.from_pretrained("ISOM5240GP4/email_sentiment", num_labels=2)
 
 
 
 
 
9
  tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
 
10
 
11
+ spam_result = spam_pipeline(email_body)
12
+ spam_label = spam_result[0]["label"]
13
+ spam_confidence = spam_result[0]["score"]
14
 
15
+ if spam_label == "LABEL_1":
16
+ return "spam", f"This is a spam email (Confidence: {spam_confidence:.2f}). No follow-up needed."
17
+ else:
18
+ inputs = tokenizer(email_body, padding=True, truncation=True, return_tensors='pt')
19
+ outputs = sentiment_model(**inputs)
20
+ predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
21
+ predictions = predictions.cpu().detach().numpy()
22
+ sentiment_index = np.argmax(predictions)
23
+ sentiment_confidence = predictions[0][sentiment_index]
24
+ sentiment = "Positive" if sentiment_index == 1 else "Negative"
25
+
26
+ if sentiment == "Positive":
27
+ return "positive", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
28
+ f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}). No follow-up needed.")
29
  else:
30
+ return "negative", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
31
+ f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}).\n"
32
+ "**Need to Follow-Up**: This email is not spam and has negative sentiment.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
 
34
  def main():
 
35
  st.title("EmailSentry")
36
  st.write("Aims to perform analysis on incoming emails and to determine whether there is urgency or higher priority for the company to follow-up.")
37
+
38
+ # Initialize session state
39
  if "email_body" not in st.session_state:
40
  st.session_state.email_body = ""
41
  if "result" not in st.session_state:
42
  st.session_state.result = ""
43
  if "result_type" not in st.session_state:
44
  st.session_state.result_type = ""
45
+
46
+ # Collapsible instructions
47
  with st.expander("How to Use", expanded=False):
48
  st.write("""
49
  - Type or paste an email into the text box.
 
51
  - Press 'Analyze Email' to check if it’s spam and analyze its sentiment.
52
  - Use 'Clear' to reset the input and result.
53
  """)
54
+
55
  # Text area for email input
56
  email_body = st.text_area("Email Body", value=st.session_state.email_body, height=200, key="email_input")
57
+
58
+ # Sample emails (shortened snippets for button labels)
59
  sample_spam = """
60
  Subject: Urgent: Verify Your Account Now!
61
  Dear Customer,
 
66
  The Security Team
67
  """
68
  spam_snippet = "Subject: Urgent: Verify Your Account Now! Dear Customer, We have detected unusual activity..."
69
+
70
  sample_not_spam_positive = """
71
  Subject: Great Experience with HKTV mall
72
  Dear Sir,
 
75
  Emily
76
  """
77
  positive_snippet = "Subject: Great Experience with HKTV mall Dear Sir, I just received my order and I’m really..."
78
+
79
  sample_not_spam_negative = """
80
  Subject: Issue with Recent Delivery
81
  Dear Support,
 
84
  Sarah
85
  """
86
  negative_snippet = "Subject: Issue with Recent Delivery Dear Support, I received my package today, but..."
87
+
88
+ # Custom CSS for buttons and result boxes
89
+ st.markdown("""
90
+ <style>
91
+ /* Sample buttons (smaller text) */
92
+ div.stButton > button[kind="secondary"] {
93
+ font-size: 12px;
94
+ padding: 5px 10px;
95
+ background-color: #f0f0f0;
96
+ color: #333333;
97
+ border: 1px solid #cccccc;
98
+ border-radius: 3px;
99
+ }
100
+ /* Analyze Email button (larger, orange) */
101
+ div.stButton > button[kind="primary"] {
102
+ background-color: #FF5733;
103
+ color: white;
104
+ font-size: 18px;
105
+ padding: 12px 24px;
106
+ border: none;
107
+ border-radius: 5px;
108
+ margin-right: 10px;
109
+ }
110
+ div.stButton > button[kind="primary"]:hover {
111
+ background-color: #E74C3C;
112
+ }
113
+ /* Clear button (gray) */
114
+ div.stButton > button[kind="secondary"][key="clear"] {
115
+ background-color: #d3d3d3;
116
+ color: #333333;
117
+ font-size: 16px;
118
+ padding: 10px 20px;
119
+ border: none;
120
+ border-radius: 5px;
121
+ }
122
+ div.stButton > button[kind="secondary"][key="clear"]:hover {
123
+ background-color: #b0b0b0;
124
+ }
125
+ /* Result boxes */
126
+ .spam-result {
127
+ background-color: #ffcccc;
128
+ padding: 10px;
129
+ border-radius: 5px;
130
+ border: 1px solid #ff9999;
131
+ }
132
+ .positive-result {
133
+ background-color: #ccffcc;
134
+ padding: 10px;
135
+ border-radius: 5px;
136
+ border: 1px solid #99cc99;
137
+ }
138
+ .negative-result {
139
+ background-color: #fff3cc;
140
+ padding: 10px;
141
+ border-radius: 5px;
142
+ border: 1px solid #ffcc66;
143
+ }
144
+ </style>
145
+ """, unsafe_allow_html=True)
146
+
147
+ # Sample buttons (in columns)
148
  col1, col2, col3 = st.columns(3)
149
  with col1:
150
  if st.button(spam_snippet, key="spam_sample"):
 
164
  st.session_state.result = ""
165
  st.session_state.result_type = ""
166
  st.rerun()
167
+
168
+ # Analyze and Clear buttons (in a row)
169
+ col_analyze, col_clear = st.columns([1, 1])
170
  with col_analyze:
171
+ if st.button("Analyze Email", key="analyze", type="primary"):
172
  if email_body:
173
  with st.spinner("Analyzing email..."):
174
  result_type, result = analyze_email(email_body)
 
177
  else:
178
  st.session_state.result = "Please enter an email body or select a sample to analyze."
179
  st.session_state.result_type = ""
 
180
  with col_clear:
181
  if st.button("Clear", key="clear"):
182
  st.session_state.email_body = ""
183
  st.session_state.result = ""
184
  st.session_state.result_type = ""
185
  st.rerun()
186
+
187
+ # Display result with styled box
188
  if st.session_state.result:
189
  if st.session_state.result_type == "spam":
190
  st.markdown(f'<div class="spam-result">{st.session_state.result}</div>', unsafe_allow_html=True)
 
193
  elif st.session_state.result_type == "negative":
194
  st.markdown(f'<div class="negative-result">{st.session_state.result}</div>', unsafe_allow_html=True)
195
  else:
196
+ st.write(st.session_state.result) # For error messages
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
  if __name__ == "__main__":
199
  main()