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()