ISOM5240GP4 commited on
Commit
40b7a7a
·
verified ·
1 Parent(s): 7a0022c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -40
app.py CHANGED
@@ -5,53 +5,55 @@ import numpy as np
5
 
6
  # Function to analyze email for spam and sentiment
7
  def analyze_email(email_body):
8
- # Load pre-trained models for spam detection and sentiment analysis
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
- # Step 1: Check if email is spam
14
  spam_result = spam_pipeline(email_body)
15
- spam_label = spam_result[0]["label"]
16
  spam_confidence = spam_result[0]["score"]
17
 
18
  if spam_label == "LABEL_1":
 
19
  return "spam", f"This is a spam email (Confidence: {spam_confidence:.2f}). No follow-up needed."
20
  else:
21
- # Step 2: Analyze sentiment for non-spam emails
22
- inputs = tokenizer(email_body, padding=True, truncation=True, return_tensors='pt')
23
- outputs = sentiment_model(**inputs)
24
- predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
25
- predictions = predictions.cpu().detach().numpy()
26
- sentiment_index = np.argmax(predictions)
27
  sentiment_confidence = predictions[0][sentiment_index]
28
  sentiment = "Positive" if sentiment_index == 1 else "Negative"
29
 
30
  if sentiment == "Positive":
 
31
  return "positive", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
32
  f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}). No follow-up needed.")
33
  else:
34
- # Using HTML <b> tags to ensure bolding
35
  return "negative", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
36
  f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}).\n"
37
  "<b>Need to Follow-Up</b>: This email is not spam and has negative sentiment.")
38
 
39
  # Main application function
40
  def main():
41
- # Set page title
42
  st.title("EmailSentry")
43
- # Set project objective
44
  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.")
45
 
46
- # Initialize session state variables
47
  if "email_body" not in st.session_state:
48
- st.session_state.email_body = ""
49
  if "result" not in st.session_state:
50
- st.session_state.result = ""
51
  if "result_type" not in st.session_state:
52
- st.session_state.result_type = ""
53
 
54
- # Collapsible instructions section
55
  with st.expander("How to Use", expanded=False):
56
  st.write("""
57
  - Type or paste an email into the text box.
@@ -60,10 +62,10 @@ def main():
60
  - Use 'Clear' to reset the input and result.
61
  """)
62
 
63
- # Input text area for email content
64
  email_body = st.text_area("Email Body", value=st.session_state.email_body, height=200, key="email_input")
65
 
66
- # Define sample emails and their snippets for buttons
67
  sample_spam = """
68
  Subject: Urgent: Verify Your Account Now!
69
  Dear Customer,
@@ -96,7 +98,7 @@ Sarah
96
  # Custom CSS for styling buttons and result boxes
97
  st.markdown("""
98
  <style>
99
- /* Sample buttons (smaller text) */
100
  div.stButton > button[kind="secondary"] {
101
  font-size: 12px;
102
  padding: 5px 10px;
@@ -105,21 +107,21 @@ Sarah
105
  border: 1px solid #cccccc;
106
  border-radius: 3px;
107
  }
108
- /* Analyze Email button (orange) */
109
  div.stButton > button[key="analyze"] {
110
- background-color: #FF5733;
111
  color: white;
112
  font-size: 18px;
113
  padding: 12px 24px;
114
  border: none;
115
  border-radius: 5px;
116
  width: 100%;
117
- height: 50px; /* Fixed height for consistency */
118
  box-sizing: border-box;
119
  text-align: center;
120
  }
121
  div.stButton > button[key="analyze"]:hover {
122
- background-color: #E74C3C;
123
  }
124
  /* Clear button (gray, aligned with Analyze) */
125
  div.stButton > button[key="clear"] {
@@ -130,80 +132,88 @@ Sarah
130
  border: none;
131
  border-radius: 5px;
132
  width: 100%;
133
- height: 50px; /* Fixed height for consistency */
134
  box-sizing: border-box;
135
  text-align: center;
136
  }
137
  div.stButton > button[key="clear"]:hover {
138
- background-color: #b0b0b0;
139
  }
140
- /* Result boxes */
141
  .spam-result {
142
- background-color: #ffdddd; /* Softer red */
 
143
  padding: 10px;
144
  border-radius: 5px;
145
- border: 1px solid #ffaaaa;
146
  }
147
  .positive-result {
148
- background-color: #d4edda; /* Softer green */
 
149
  padding: 10px;
150
  border-radius: 5px;
151
- border: 1px solid #a3d7a9;
152
  }
153
  .negative-result {
154
- background-color: #fff4e6; /* Softer orange */
 
155
  padding: 10px;
156
  border-radius: 5px;
157
- border: 1px solid #ffd6a5;
158
  }
159
  </style>
160
  """, unsafe_allow_html=True)
161
 
162
- # Subheading for sample buttons
163
  st.subheader("Examples")
164
 
165
- # Sample buttons layout (3 columns)
166
  col1, col2, col3 = st.columns(3)
167
  with col1:
 
168
  if st.button(spam_snippet, key="spam_sample"):
169
  st.session_state.email_body = sample_spam
170
  st.session_state.result = ""
171
  st.session_state.result_type = ""
172
  st.rerun()
173
  with col2:
 
174
  if st.button(positive_snippet, key="positive_sample"):
175
  st.session_state.email_body = sample_not_spam_positive
176
  st.session_state.result = ""
177
  st.session_state.result_type = ""
178
  st.rerun()
179
  with col3:
 
180
  if st.button(negative_snippet, key="negative_sample"):
181
  st.session_state.email_body = sample_not_spam_negative
182
  st.session_state.result = ""
183
  st.session_state.result_type = ""
184
  st.rerun()
185
 
186
- # Action buttons layout (Analyze and Clear)
187
  col_analyze, col_clear = st.columns(2)
188
  with col_analyze:
189
- # Removed type="primary" to rely on custom CSS
190
  if st.button("Analyze Email", key="analyze"):
191
  if email_body:
192
- with st.spinner("Analyzing email..."):
193
  result_type, result = analyze_email(email_body)
194
  st.session_state.result = result
195
  st.session_state.result_type = result_type
196
  else:
 
197
  st.session_state.result = "Please enter an email body or select a sample to analyze."
198
  st.session_state.result_type = ""
199
  with col_clear:
 
200
  if st.button("Clear", key="clear"):
201
  st.session_state.email_body = ""
202
  st.session_state.result = ""
203
  st.session_state.result_type = ""
204
  st.rerun()
205
 
206
- # Display analysis result in styled boxes
207
  if st.session_state.result:
208
  if st.session_state.result_type == "spam":
209
  st.markdown(f'<div class="spam-result">{st.session_state.result}</div>', unsafe_allow_html=True)
@@ -212,7 +222,7 @@ Sarah
212
  elif st.session_state.result_type == "negative":
213
  st.markdown(f'<div class="negative-result">{st.session_state.result}</div>', unsafe_allow_html=True)
214
  else:
215
- st.write(st.session_state.result) # For error messages
216
 
217
  # Run the app
218
  if __name__ == "__main__":
 
5
 
6
  # Function to analyze email for spam and sentiment
7
  def analyze_email(email_body):
8
+ # Load pre-trained models: spam detection and sentiment analysis
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
+ # Step 1: Check if the email is spam using the spam detection model
14
  spam_result = spam_pipeline(email_body)
15
+ spam_label = spam_result[0]["label"] # LABEL_1 indicates spam
16
  spam_confidence = spam_result[0]["score"]
17
 
18
  if spam_label == "LABEL_1":
19
+ # If spam, return type "spam" and a message indicating no follow-up
20
  return "spam", f"This is a spam email (Confidence: {spam_confidence:.2f}). No follow-up needed."
21
  else:
22
+ # Step 2: For non-spam emails, analyze sentiment (positive/negative)
23
+ inputs = tokenizer(email_body, padding=True, truncation=True, return_tensors='pt') # Tokenize input
24
+ outputs = sentiment_model(**inputs) # Get model predictions
25
+ predictions = torch.nn.functional.softmax(outputs.logits, dim=-1) # Apply softmax for probabilities
26
+ predictions = predictions.cpu().detach().numpy() # Convert to numpy array
27
+ sentiment_index = np.argmax(predictions) # Get the predicted sentiment (0 = negative, 1 = positive)
28
  sentiment_confidence = predictions[0][sentiment_index]
29
  sentiment = "Positive" if sentiment_index == 1 else "Negative"
30
 
31
  if sentiment == "Positive":
32
+ # If positive sentiment, no follow-up needed
33
  return "positive", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
34
  f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}). No follow-up needed.")
35
  else:
36
+ # If negative sentiment, mark as needing follow-up with bolded text
37
  return "negative", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
38
  f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}).\n"
39
  "<b>Need to Follow-Up</b>: This email is not spam and has negative sentiment.")
40
 
41
  # Main application function
42
  def main():
43
+ # Set the app title to the project name
44
  st.title("EmailSentry")
45
+ # Display the project objective
46
  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.")
47
 
48
+ # Initialize session state to store email input and analysis results
49
  if "email_body" not in st.session_state:
50
+ st.session_state.email_body = "" # Holds the email text
51
  if "result" not in st.session_state:
52
+ st.session_state.result = "" # Stores the analysis result text
53
  if "result_type" not in st.session_state:
54
+ st.session_state.result_type = "" # Tracks result type (spam, positive, negative)
55
 
56
+ # Add collapsible instructions for user guidance
57
  with st.expander("How to Use", expanded=False):
58
  st.write("""
59
  - Type or paste an email into the text box.
 
62
  - Use 'Clear' to reset the input and result.
63
  """)
64
 
65
+ # Text area where users input or view the email body
66
  email_body = st.text_area("Email Body", value=st.session_state.email_body, height=200, key="email_input")
67
 
68
+ # Define sample emails and their snippets for example buttons
69
  sample_spam = """
70
  Subject: Urgent: Verify Your Account Now!
71
  Dear Customer,
 
98
  # Custom CSS for styling buttons and result boxes
99
  st.markdown("""
100
  <style>
101
+ /* Style for sample buttons (smaller, light gray) */
102
  div.stButton > button[kind="secondary"] {
103
  font-size: 12px;
104
  padding: 5px 10px;
 
107
  border: 1px solid #cccccc;
108
  border-radius: 3px;
109
  }
110
+ /* Analyze Email button (orange, matches Clear button size) */
111
  div.stButton > button[key="analyze"] {
112
+ background-color: #FF5733; /* Original orange color */
113
  color: white;
114
  font-size: 18px;
115
  padding: 12px 24px;
116
  border: none;
117
  border-radius: 5px;
118
  width: 100%;
119
+ height: 50px;
120
  box-sizing: border-box;
121
  text-align: center;
122
  }
123
  div.stButton > button[key="analyze"]:hover {
124
+ background-color: #E74C3C; /* Darker orange on hover */
125
  }
126
  /* Clear button (gray, aligned with Analyze) */
127
  div.stButton > button[key="clear"] {
 
132
  border: none;
133
  border-radius: 5px;
134
  width: 100%;
135
+ height: 50px;
136
  box-sizing: border-box;
137
  text-align: center;
138
  }
139
  div.stButton > button[key="clear"]:hover {
140
+ background-color: #b0b0b0; /* Darker gray on hover */
141
  }
142
+ /* Result boxes with updated colors */
143
  .spam-result {
144
+ background-color: #ff3333; /* Red for no follow-up (spam) */
145
+ color: white;
146
  padding: 10px;
147
  border-radius: 5px;
148
+ border: 1px solid #cc0000;
149
  }
150
  .positive-result {
151
+ background-color: #ff3333; /* Red for no follow-up (positive) */
152
+ color: white;
153
  padding: 10px;
154
  border-radius: 5px;
155
+ border: 1px solid #cc0000;
156
  }
157
  .negative-result {
158
+ background-color: #006633; /* Dark green for follow-up needed */
159
+ color: white;
160
  padding: 10px;
161
  border-radius: 5px;
162
+ border: 1px solid #004d26;
163
  }
164
  </style>
165
  """, unsafe_allow_html=True)
166
 
167
+ # Subheading to label the sample email buttons
168
  st.subheader("Examples")
169
 
170
+ # Layout for sample buttons in 3 columns
171
  col1, col2, col3 = st.columns(3)
172
  with col1:
173
+ # Button to load spam sample
174
  if st.button(spam_snippet, key="spam_sample"):
175
  st.session_state.email_body = sample_spam
176
  st.session_state.result = ""
177
  st.session_state.result_type = ""
178
  st.rerun()
179
  with col2:
180
+ # Button to load positive non-spam sample
181
  if st.button(positive_snippet, key="positive_sample"):
182
  st.session_state.email_body = sample_not_spam_positive
183
  st.session_state.result = ""
184
  st.session_state.result_type = ""
185
  st.rerun()
186
  with col3:
187
+ # Button to load negative non-spam sample
188
  if st.button(negative_snippet, key="negative_sample"):
189
  st.session_state.email_body = sample_not_spam_negative
190
  st.session_state.result = ""
191
  st.session_state.result_type = ""
192
  st.rerun()
193
 
194
+ # Layout for action buttons (Analyze and Clear) in 2 columns
195
  col_analyze, col_clear = st.columns(2)
196
  with col_analyze:
197
+ # Button to trigger email analysis
198
  if st.button("Analyze Email", key="analyze"):
199
  if email_body:
200
+ with st.spinner("Analyzing email..."): # Show spinner during processing
201
  result_type, result = analyze_email(email_body)
202
  st.session_state.result = result
203
  st.session_state.result_type = result_type
204
  else:
205
+ # Error message if no email is provided
206
  st.session_state.result = "Please enter an email body or select a sample to analyze."
207
  st.session_state.result_type = ""
208
  with col_clear:
209
+ # Button to reset the app state
210
  if st.button("Clear", key="clear"):
211
  st.session_state.email_body = ""
212
  st.session_state.result = ""
213
  st.session_state.result_type = ""
214
  st.rerun()
215
 
216
+ # Display the analysis result in styled boxes based on result type
217
  if st.session_state.result:
218
  if st.session_state.result_type == "spam":
219
  st.markdown(f'<div class="spam-result">{st.session_state.result}</div>', unsafe_allow_html=True)
 
222
  elif st.session_state.result_type == "negative":
223
  st.markdown(f'<div class="negative-result">{st.session_state.result}</div>', unsafe_allow_html=True)
224
  else:
225
+ st.write(st.session_state.result) # Display error messages without styling
226
 
227
  # Run the app
228
  if __name__ == "__main__":