ISOM5240GP4 commited on
Commit
12f1d61
·
verified ·
1 Parent(s): 9d82315

Update app.py

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