Spaces:
Running
Running
File size: 9,494 Bytes
f9903ea 9739fd6 f9903ea 12f1d61 9d82315 12f1d61 9d82315 9739fd6 f9903ea cc474be 12f1d61 7c483c8 12f1d61 cc474be 12f1d61 cc474be 12f1d61 7c483c8 12f1d61 7c483c8 12f1d61 7d63c56 12f1d61 bfc5779 0b21d86 7c483c8 0b21d86 48034cd 0b21d86 12f1d61 48034cd 12f1d61 0b21d86 b17d738 12f1d61 7c483c8 345319f 12f1d61 7c483c8 7f5130a 7d63c56 7c483c8 7f5130a 12f1d61 7c483c8 345319f 12f1d61 318aea1 9d82315 12f1d61 9d82315 318aea1 9d82315 318aea1 9d82315 12f1d61 318aea1 9d82315 12f1d61 9d82315 318aea1 9d82315 318aea1 9d82315 318aea1 9d82315 318aea1 9d82315 318aea1 9d82315 318aea1 9d82315 318aea1 9d82315 fbd79d5 7a0022c |
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 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
import streamlit as st
from transformers import pipeline, AutoModelForSequenceClassification, AutoTokenizer
import torch
import numpy as np
# Function to analyze email (no caching, models loaded each time)
def analyze_email(email_body):
"""Analyzes an email for spam and sentiment, returning result type and message."""
spam_pipeline = pipeline("text-classification", model="cybersectony/phishing-email-detection-distilbert_v2.4.1")
sentiment_model = AutoModelForSequenceClassification.from_pretrained("ISOM5240GP4/email_sentiment", num_labels=2)
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
# this is to handle if user does not input anything
if not email_body.strip():
return "error", "Email body is empty. Please provide an email to analyze."
try:
# Step 1: Check if the email is spam
spam_result = spam_pipeline(email_body)
spam_label = spam_result[0]["label"] # LABEL_1 indicates spam
spam_confidence = spam_result[0]["score"]
if spam_label == "LABEL_1":
return "spam", f"This is a spam email (Confidence: {spam_confidence:.2f}). No follow-up needed."
else:
# Step 2: Analyze sentiment for non-spam emails
inputs = tokenizer(email_body, padding=True, truncation=True, return_tensors='pt')
# Pass the tokenized inputs to the sentiment model
# **inputs unpacks the dictionary of inputs to the model
outputs = sentiment_model(**inputs)
predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
predictions = predictions.cpu().detach().numpy()
sentiment_index = np.argmax(predictions)
sentiment_confidence = predictions[0][sentiment_index]
# Convert numeric prediction to human-readable sentiment
# If index is 1, it's Positive, otherwise Negative
sentiment = "Positive" if sentiment_index == 1 else "Negative"
if sentiment == "Positive":
return "positive", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}). No follow-up needed.")
else:
return "negative", (f"This email is not spam (Confidence: {spam_confidence:.2f}).\n"
f"Sentiment: {sentiment} (Confidence: {sentiment_confidence:.2f}).\n"
"<b>Need to Follow-Up</b>: This email is not spam and has negative sentiment.")
except Exception as e:
return "error", f"An error occurred during analysis: {str(e)}"
# Main application function
def main():
# Set title and objective
st.title("EmailSentry")
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.")
# Initialize session state variables
if "email_body" not in st.session_state:
st.session_state.email_body = ""
if "result" not in st.session_state:
st.session_state.result = ""
if "result_type" not in st.session_state:
st.session_state.result_type = ""
# Instructions section
with st.expander("How to Use", expanded=False):
st.write("""
- Type or paste an email into the text box.
- Alternatively, click one of the sample buttons to load a predefined email.
- Press 'Analyze Email' to check if it’s spam and analyze its sentiment.
- Use 'Clear' to reset the input and result.
""")
# Text area for email input
email_body = st.text_area("Email", value=st.session_state.email_body, height=200, key="email_input")
# Define sample emails
sample_spam = """
Subject: Urgent: Verify Your Account Now!
Dear Customer,
We have detected unusual activity on your account. To prevent suspension, please verify your login details immediately by clicking the link below:
[Click Here to Verify](http://totally-legit-site.com/verify)
Failure to verify within 24 hours will result in your account being locked. This is for your security.
Best regards,
The Security Team
"""
spam_snippet = "Subject: Urgent: Verify Your Account Now! Dear Customer, We have detected unusual activity..."
sample_not_spam_positive = """
Subject: Great Experience with HKTV mall
Dear Sir,
I just received my order and I’m really impressed with the speed of the delivery. Keep up the good work.
Best regards,
Emily
"""
positive_snippet = "Subject: Great Experience with HKTV mall Dear Sir, I just received my order and I’m really..."
sample_not_spam_negative = """
Subject: Issue with Recent Delivery
Dear Support,
I received my package today, but it was damaged, and two items were missing. This is really frustrating—please let me know how we can resolve this as soon as possible.
Thanks,
Sarah
"""
negative_snippet = "Subject: Issue with Recent Delivery Dear Support, I received my package today, but..."
# Display sample buttons
st.subheader("Examples")
col1, col2, col3 = st.columns(3)
with col1:
if st.button(spam_snippet, key="spam_sample"):
st.session_state.email_body = sample_spam
st.session_state.result = ""
st.session_state.result_type = ""
st.rerun()
with col2:
if st.button(positive_snippet, key="positive_sample"):
st.session_state.email_body = sample_not_spam_positive
st.session_state.result = ""
st.session_state.result_type = ""
st.rerun()
with col3:
if st.button(negative_snippet, key="negative_sample"):
st.session_state.email_body = sample_not_spam_negative
st.session_state.result = ""
st.session_state.result_type = ""
st.rerun()
# Action buttons
col_analyze, col_clear = st.columns(2)
with col_analyze:
if st.button("Analyze Email", key="analyze", type="primary"):
if email_body:
with st.spinner("Analyzing email..."):
result_type, result = analyze_email(email_body)
st.session_state.result = result
st.session_state.result_type = result_type
else:
st.session_state.result = "Please enter an email body or select a sample to analyze."
st.session_state.result_type = ""
with col_clear:
if st.button("Clear", key="clear"):
st.session_state.email_body = ""
st.session_state.result = ""
st.session_state.result_type = ""
st.rerun()
# Display analysis result
if st.session_state.result:
if st.session_state.result_type == "spam":
st.markdown(f'<div class="spam-result">{st.session_state.result}</div>', unsafe_allow_html=True)
elif st.session_state.result_type == "positive":
st.markdown(f'<div class="positive-result">{st.session_state.result}</div>', unsafe_allow_html=True)
elif st.session_state.result_type == "negative":
st.markdown(f'<div class="negative-result">{st.session_state.result}</div>', unsafe_allow_html=True)
else:
st.write(st.session_state.result)
# Inject custom CSS with updated result block colors
st.markdown("""
<style>
/* Sample buttons (light grey, small) */
div.stButton > button[kind="secondary"] {
font-size: 12px;
padding: 5px 10px;
background-color: #f0f0f0;
color: #333333;
border: 1px solid #cccccc;
border-radius: 3px;
}
/* Analyze Email button (orange, larger) */
div.stButton > button[kind="primary"] {
background-color: #FF5733;
color: white;
font-size: 18px;
padding: 12px 24px;
border: none;
border-radius: 5px;
margin-right: 10px;
}
div.stButton > button[kind="primary"]:hover {
background-color: #E74C3C;
}
/* Clear button (blue) */
div.stButton > button[kind="secondary"][key="clear"] {
background-color: #007BFF;
color: white;
font-size: 18px;
padding: 12px 24px;
border: none;
border-radius: 5px;
}
div.stButton > button[kind="secondary"][key="clear"]:hover {
background-color: #0056b3;
}
/* Result boxes: Red for no follow-up, Green for follow-up */
.spam-result {
background-color: #ff3333; /* Red for no follow-up */
color: white;
padding: 10px;
border-radius: 5px;
border: 1px solid #cc0000;
}
.positive-result {
background-color: #ff3333; /* Red for no follow-up */
color: white;
padding: 10px;
border-radius: 5px;
border: 1px solid #cc0000;
}
.negative-result {
background-color: #33cc33; /* Green for follow-up needed */
color: white;
padding: 10px;
border-radius: 5px;
border: 1px solid #009900;
}
</style>
""", unsafe_allow_html=True)
if __name__ == "__main__":
main() |