IqraFatima commited on
Commit
fd0b808
·
verified ·
1 Parent(s): 2551196

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +245 -245
app.py CHANGED
@@ -1,202 +1,16 @@
1
 
2
 
3
- # app.py v2
4
 
5
- import os
6
- import re
7
- import fitz # PyMuPDF
8
- import tempfile
9
- from datetime import datetime
10
- import base64
11
- from gtts import gTTS
12
- import streamlit as st
13
- from transformers.pipelines import pipeline
14
- from groq import Groq
15
-
16
- # ✅ Hugging Face and GROQ secrets loaded via Hugging Face Spaces Secrets interface
17
-
18
- # ⛳ Access secrets securely from environment variables
19
- GROQ_API_KEY = os.getenv("GROQ_API_KEY")
20
- HF_TOKEN = os.getenv("HF_TOKEN")
21
- KAGGLE_USERNAME = os.getenv("KAGGLE_USERNAME")
22
- KAGGLE_KEY = os.getenv("KAGGLE_KEY")
23
-
24
- # ✅ Validate secrets
25
- if not all([GROQ_API_KEY, HF_TOKEN, KAGGLE_USERNAME, KAGGLE_KEY]):
26
- st.error("❌ One or more required API keys are missing from the environment.")
27
- st.stop()
28
-
29
- # ✅ Initialize Groq client
30
- client = Groq(api_key=GROQ_API_KEY)
31
-
32
- # ✅ Load phishing detection pipeline from Hugging Face
33
- phishing_pipe = pipeline(
34
- "text-classification",
35
- model="ealvaradob/bert-finetuned-phishing",
36
- token=HF_TOKEN
37
- )
38
-
39
- # ✅ Language and role options
40
- language_choices = ["English", "Urdu", "French"]
41
- role_choices = ["Admin", "Procurement", "Logistics"]
42
-
43
- # ✅ Glossary terms
44
- GLOSSARY = {
45
- "phishing": "Phishing is a scam where attackers trick you into revealing personal information.",
46
- "malware": "Malicious software designed to harm or exploit systems.",
47
- "spam": "Unwanted or unsolicited messages.",
48
- "tone": "The emotional character of the message."
49
- }
50
-
51
- # ✅ Translations (demo dictionary-based)
52
- TRANSLATIONS = {
53
- "Phishing": {"Urdu": "فشنگ", "French": "Hameçonnage"},
54
- "Spam": {"Urdu": "سپیم", "French": "Courrier indésirable"},
55
- "Malware": {"Urdu": "میلویئر", "French": "Logiciel malveillant"},
56
- "Safe": {"Urdu": "محفوظ", "French": "Sûr"}
57
- }
58
-
59
- # =======================
60
- # Streamlit UI
61
- # =======================
62
- st.set_page_config(page_title="ZeroPhish Gate", layout="wide")
63
- st.title("🛡️ ZeroPhish Gate")
64
- st.markdown("AI-powered phishing message detection and explanation.")
65
-
66
- # Input fields
67
- col1, col2 = st.columns([3, 1])
68
- with col1:
69
- text_input = st.text_area("✉️ Paste Suspicious Message", height=200)
70
- uploaded_file = st.file_uploader("📄 Upload PDF/TXT (optional)", type=["pdf", "txt"])
71
-
72
- with col2:
73
- language = st.selectbox("🌐 Preferred Language", language_choices)
74
- role = st.selectbox("🧑‍💼 Your Role", role_choices)
75
-
76
- analyze_btn = st.button("🔍 Analyze with AI")
77
-
78
- # =======================
79
- # Function Definitions
80
- # =======================
81
- def extract_text_from_file(file):
82
- if file is None:
83
- return ""
84
- ext = file.name.split(".")[-1].lower()
85
- if ext == "pdf":
86
- doc = fitz.open(stream=file.read(), filetype="pdf")
87
- return "\n".join(page.get_text() for page in doc)
88
- elif ext == "txt":
89
- return file.read().decode("utf-8")
90
- return ""
91
-
92
- def analyze_with_huggingface(text):
93
- try:
94
- result = phishing_pipe(text)
95
- label = result[0]['label']
96
- confidence = round(result[0]['score'] * 100, 2)
97
- threat_type = {
98
- "PHISHING": "Phishing",
99
- "SPAM": "Spam",
100
- "MALWARE": "Malware",
101
- "LEGITIMATE": "Safe"
102
- }.get(label.upper(), "Unknown")
103
- return label, confidence, threat_type
104
- except Exception as e:
105
- return "Error", 0, f"Error: {e}"
106
-
107
- def semantic_analysis(text):
108
- response = client.chat.completions.create(
109
- model="llama3-8b-8192",
110
- messages=[
111
- {"role": "system", "content": "You are a cybersecurity assistant."},
112
- {"role": "user", "content": f"Please explain this message in professional tone for a {role} in {language}. Do not end with questions.\n\nMessage:\n{text}"}
113
- ]
114
- )
115
- return response.choices[0].message.content
116
-
117
- def translate_label(threat_type):
118
- return TRANSLATIONS.get(threat_type, {}).get(language, threat_type)
119
-
120
- def text_to_speech(text):
121
- tts = gTTS(text=text, lang='en')
122
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as fp:
123
- tts.save(fp.name)
124
- return fp.name
125
-
126
- def create_report(label, score, threat_type, explanation, text):
127
- ts = datetime.now().strftime("%Y%m%d_%H%M%S")
128
- filename = f"Zerophish_Report_{ts}.txt"
129
- report = f"""
130
- 🔍 AI Threat Detection Report
131
-
132
- Input Message:
133
- {text}
134
-
135
- Prediction: {label}
136
- Threat Type: {threat_type}
137
- Confidence: {score}%
138
-
139
- ---
140
-
141
- 🧠 Explanation:
142
- {explanation}
143
- """
144
- with open(filename, "w") as f:
145
- f.write(report)
146
- return filename
147
-
148
- # =======================
149
- # Run Analysis
150
- # =======================
151
- if analyze_btn:
152
- combined_text = text_input
153
- if uploaded_file:
154
- extracted = extract_text_from_file(uploaded_file)
155
- combined_text += "\n" + extracted
156
-
157
- if not combined_text.strip():
158
- st.warning("⚠️ Please enter some text or upload a file to analyze.")
159
- else:
160
- label, score, threat_type = analyze_with_huggingface(combined_text)
161
- translated_threat = translate_label(threat_type)
162
-
163
- st.subheader("🔍 AI Threat Detection Result")
164
- st.markdown(f"**Prediction:** {label}")
165
- st.markdown(f"**Threat Type:** {threat_type} ({translated_threat})")
166
- st.markdown(f"**Confidence:** {score}%")
167
-
168
- explanation = ""
169
- if threat_type.lower() != "safe":
170
- with st.expander("🧠 Semantic Reanalysis by LLaMA"):
171
- explanation = semantic_analysis(combined_text)
172
- st.write(explanation)
173
-
174
- if st.button("🔊 Play Explanation as Audio"):
175
- audio_path = text_to_speech(explanation)
176
- with open(audio_path, "rb") as f:
177
- st.audio(f.read(), format="audio/mp3")
178
-
179
- with st.expander("📜 Glossary Help"):
180
- for term, definition in GLOSSARY.items():
181
- st.markdown(f"**{term.capitalize()}**: {definition}")
182
-
183
- if explanation:
184
- report_path = create_report(label, score, threat_type, explanation, combined_text)
185
- with open(report_path, "rb") as f:
186
- b64 = base64.b64encode(f.read()).decode()
187
- href = f'<a href="data:file/txt;base64,{b64}" download="{report_path}">📄 Download Full Report</a>'
188
- st.markdown(href, unsafe_allow_html=True)
189
-
190
- #app v3
191
  # import os
192
  # import re
193
  # import fitz # PyMuPDF
194
  # import tempfile
195
- # import base64
196
  # from datetime import datetime
 
197
  # from gtts import gTTS
198
  # import streamlit as st
199
- # from transformers import pipeline
200
  # from groq import Groq
201
 
202
  # # ✅ Hugging Face and GROQ secrets loaded via Hugging Face Spaces Secrets interface
@@ -242,30 +56,10 @@ if analyze_btn:
242
  # "Safe": {"Urdu": "محفوظ", "French": "Sûr"}
243
  # }
244
 
245
- # # ✅ In-memory history
246
- # if "history" not in st.session_state:
247
- # st.session_state.history = []
248
-
249
  # # =======================
250
  # # Streamlit UI
251
  # # =======================
252
  # st.set_page_config(page_title="ZeroPhish Gate", layout="wide")
253
-
254
- # st.markdown("""
255
- # <style>
256
- # .report-container {
257
- # border: 1px solid #ddd;
258
- # padding: 1rem;
259
- # border-radius: 10px;
260
- # background-color: #f9f9f9;
261
- # }
262
- # .highlight {
263
- # font-weight: bold;
264
- # color: #d9534f;
265
- # }
266
- # </style>
267
- # """, unsafe_allow_html=True)
268
-
269
  # st.title("🛡️ ZeroPhish Gate")
270
  # st.markdown("AI-powered phishing message detection and explanation.")
271
 
@@ -280,7 +74,6 @@ if analyze_btn:
280
  # role = st.selectbox("🧑‍💼 Your Role", role_choices)
281
 
282
  # analyze_btn = st.button("🔍 Analyze with AI")
283
- # clear_btn = st.button("🗑️ Clear History")
284
 
285
  # # =======================
286
  # # Function Definitions
@@ -316,12 +109,10 @@ if analyze_btn:
316
  # model="llama3-8b-8192",
317
  # messages=[
318
  # {"role": "system", "content": "You are a cybersecurity assistant."},
319
- # {"role": "user", "content": f"Explain this suspicious message for a {role} in {language}:\n{text}"}
320
  # ]
321
  # )
322
- # raw = response.choices[0].message.content
323
- # clean = re.sub(r"Is there anything else you'd like.*", "", raw, flags=re.I).strip()
324
- # return clean
325
 
326
  # def translate_label(threat_type):
327
  # return TRANSLATIONS.get(threat_type, {}).get(language, threat_type)
@@ -332,23 +123,31 @@ if analyze_btn:
332
  # tts.save(fp.name)
333
  # return fp.name
334
 
335
- # def render_history():
336
- # with st.expander("🕓 View Analysis History"):
337
- # for i, record in enumerate(reversed(st.session_state.history)):
338
- # with st.container():
339
- # st.markdown(f"**🔢 Entry #{len(st.session_state.history) - i}**")
340
- # st.markdown(f"**📝 Input:** {record['input'][:100]}...")
341
- # st.markdown(f"**🔐 Type:** {record['threat']} | **📊 Confidence:** {record['score']}%")
342
- # st.markdown(f"**📖 Summary:** {record['summary'][:200]}...")
343
- # st.markdown("---")
 
 
 
 
 
 
 
 
 
 
 
 
344
 
345
  # # =======================
346
  # # Run Analysis
347
  # # =======================
348
- # if clear_btn:
349
- # st.session_state.history.clear()
350
- # st.success("✅ History cleared!")
351
-
352
  # if analyze_btn:
353
  # combined_text = text_input
354
  # if uploaded_file:
@@ -362,36 +161,237 @@ if analyze_btn:
362
  # translated_threat = translate_label(threat_type)
363
 
364
  # st.subheader("🔍 AI Threat Detection Result")
365
- # st.markdown(f"<div class='report-container'>"
366
- # f"<p><span class='highlight'>Prediction:</span> {label}</p>"
367
- # f"<p><span class='highlight'>Threat Type:</span> {threat_type} ({translated_threat})</p>"
368
- # f"<p><span class='highlight'>Confidence:</span> {score}%</p>"
369
- # f"</div>", unsafe_allow_html=True)
370
 
371
- # summary = ""
372
  # if threat_type.lower() != "safe":
373
  # with st.expander("🧠 Semantic Reanalysis by LLaMA"):
374
- # summary = semantic_analysis(combined_text)
375
- # st.write(summary)
376
 
377
  # if st.button("🔊 Play Explanation as Audio"):
378
- # audio_path = text_to_speech(summary)
379
  # with open(audio_path, "rb") as f:
380
  # st.audio(f.read(), format="audio/mp3")
381
 
382
- # # Save history
383
- # st.session_state.history.append({
384
- # "input": combined_text,
385
- # "threat": threat_type,
386
- # "score": score,
387
- # "summary": summary
388
- # })
389
-
390
  # with st.expander("📜 Glossary Help"):
391
  # for term, definition in GLOSSARY.items():
392
  # st.markdown(f"**{term.capitalize()}**: {definition}")
393
 
394
- # render_history()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
 
396
  #App v 3
397
  # app.py
 
1
 
2
 
3
+ # # app.py v2
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  # import os
6
  # import re
7
  # import fitz # PyMuPDF
8
  # import tempfile
 
9
  # from datetime import datetime
10
+ # import base64
11
  # from gtts import gTTS
12
  # import streamlit as st
13
+ # from transformers.pipelines import pipeline
14
  # from groq import Groq
15
 
16
  # # ✅ Hugging Face and GROQ secrets loaded via Hugging Face Spaces Secrets interface
 
56
  # "Safe": {"Urdu": "محفوظ", "French": "Sûr"}
57
  # }
58
 
 
 
 
 
59
  # # =======================
60
  # # Streamlit UI
61
  # # =======================
62
  # st.set_page_config(page_title="ZeroPhish Gate", layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  # st.title("🛡️ ZeroPhish Gate")
64
  # st.markdown("AI-powered phishing message detection and explanation.")
65
 
 
74
  # role = st.selectbox("🧑‍💼 Your Role", role_choices)
75
 
76
  # analyze_btn = st.button("🔍 Analyze with AI")
 
77
 
78
  # # =======================
79
  # # Function Definitions
 
109
  # model="llama3-8b-8192",
110
  # messages=[
111
  # {"role": "system", "content": "You are a cybersecurity assistant."},
112
+ # {"role": "user", "content": f"Please explain this message in professional tone for a {role} in {language}. Do not end with questions.\n\nMessage:\n{text}"}
113
  # ]
114
  # )
115
+ # return response.choices[0].message.content
 
 
116
 
117
  # def translate_label(threat_type):
118
  # return TRANSLATIONS.get(threat_type, {}).get(language, threat_type)
 
123
  # tts.save(fp.name)
124
  # return fp.name
125
 
126
+ # def create_report(label, score, threat_type, explanation, text):
127
+ # ts = datetime.now().strftime("%Y%m%d_%H%M%S")
128
+ # filename = f"Zerophish_Report_{ts}.txt"
129
+ # report = f"""
130
+ # 🔍 AI Threat Detection Report
131
+
132
+ # Input Message:
133
+ # {text}
134
+
135
+ # Prediction: {label}
136
+ # Threat Type: {threat_type}
137
+ # Confidence: {score}%
138
+
139
+ # ---
140
+
141
+ # 🧠 Explanation:
142
+ # {explanation}
143
+ # """
144
+ # with open(filename, "w") as f:
145
+ # f.write(report)
146
+ # return filename
147
 
148
  # # =======================
149
  # # Run Analysis
150
  # # =======================
 
 
 
 
151
  # if analyze_btn:
152
  # combined_text = text_input
153
  # if uploaded_file:
 
161
  # translated_threat = translate_label(threat_type)
162
 
163
  # st.subheader("🔍 AI Threat Detection Result")
164
+ # st.markdown(f"**Prediction:** {label}")
165
+ # st.markdown(f"**Threat Type:** {threat_type} ({translated_threat})")
166
+ # st.markdown(f"**Confidence:** {score}%")
 
 
167
 
168
+ # explanation = ""
169
  # if threat_type.lower() != "safe":
170
  # with st.expander("🧠 Semantic Reanalysis by LLaMA"):
171
+ # explanation = semantic_analysis(combined_text)
172
+ # st.write(explanation)
173
 
174
  # if st.button("🔊 Play Explanation as Audio"):
175
+ # audio_path = text_to_speech(explanation)
176
  # with open(audio_path, "rb") as f:
177
  # st.audio(f.read(), format="audio/mp3")
178
 
 
 
 
 
 
 
 
 
179
  # with st.expander("📜 Glossary Help"):
180
  # for term, definition in GLOSSARY.items():
181
  # st.markdown(f"**{term.capitalize()}**: {definition}")
182
 
183
+ # if explanation:
184
+ # report_path = create_report(label, score, threat_type, explanation, combined_text)
185
+ # with open(report_path, "rb") as f:
186
+ # b64 = base64.b64encode(f.read()).decode()
187
+ # href = f'<a href="data:file/txt;base64,{b64}" download="{report_path}">📄 Download Full Report</a>'
188
+ # st.markdown(href, unsafe_allow_html=True)
189
+
190
+ #app v3
191
+ import os
192
+ import re
193
+ import fitz # PyMuPDF
194
+ import tempfile
195
+ import base64
196
+ from datetime import datetime
197
+ from gtts import gTTS
198
+ import streamlit as st
199
+ from transformers import pipeline
200
+ from groq import Groq
201
+
202
+ # ✅ Hugging Face and GROQ secrets loaded via Hugging Face Spaces Secrets interface
203
+
204
+ # ⛳ Access secrets securely from environment variables
205
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
206
+ HF_TOKEN = os.getenv("HF_TOKEN")
207
+ KAGGLE_USERNAME = os.getenv("KAGGLE_USERNAME")
208
+ KAGGLE_KEY = os.getenv("KAGGLE_KEY")
209
+
210
+ # ✅ Validate secrets
211
+ if not all([GROQ_API_KEY, HF_TOKEN, KAGGLE_USERNAME, KAGGLE_KEY]):
212
+ st.error("❌ One or more required API keys are missing from the environment.")
213
+ st.stop()
214
+
215
+ # ✅ Initialize Groq client
216
+ client = Groq(api_key=GROQ_API_KEY)
217
+
218
+ # ✅ Load phishing detection pipeline from Hugging Face
219
+ phishing_pipe = pipeline(
220
+ "text-classification",
221
+ model="ealvaradob/bert-finetuned-phishing",
222
+ token=HF_TOKEN
223
+ )
224
+
225
+ # ✅ Language and role options
226
+ language_choices = ["English", "Urdu", "French"]
227
+ role_choices = ["Admin", "Procurement", "Logistics"]
228
+
229
+ # ✅ Glossary terms
230
+ GLOSSARY = {
231
+ "phishing": "Phishing is a scam where attackers trick you into revealing personal information.",
232
+ "malware": "Malicious software designed to harm or exploit systems.",
233
+ "spam": "Unwanted or unsolicited messages.",
234
+ "tone": "The emotional character of the message."
235
+ }
236
+
237
+ # ✅ Translations (demo dictionary-based)
238
+ TRANSLATIONS = {
239
+ "Phishing": {"Urdu": "فشنگ", "French": "Hameçonnage"},
240
+ "Spam": {"Urdu": "سپیم", "French": "Courrier indésirable"},
241
+ "Malware": {"Urdu": "میلویئر", "French": "Logiciel malveillant"},
242
+ "Safe": {"Urdu": "محفوظ", "French": "Sûr"}
243
+ }
244
+
245
+ # ✅ In-memory history
246
+ if "history" not in st.session_state:
247
+ st.session_state.history = []
248
+
249
+ # =======================
250
+ # Streamlit UI
251
+ # =======================
252
+ st.set_page_config(page_title="ZeroPhish Gate", layout="wide")
253
+
254
+ st.markdown("""
255
+ <style>
256
+ .report-container {
257
+ border: 1px solid #ddd;
258
+ padding: 1rem;
259
+ border-radius: 10px;
260
+ background-color: #f9f9f9;
261
+ }
262
+ .highlight {
263
+ font-weight: bold;
264
+ color: #d9534f;
265
+ }
266
+ </style>
267
+ """, unsafe_allow_html=True)
268
+
269
+ st.title("🛡️ ZeroPhish Gate")
270
+ st.markdown("AI-powered phishing message detection and explanation.")
271
+
272
+ # Input fields
273
+ col1, col2 = st.columns([3, 1])
274
+ with col1:
275
+ text_input = st.text_area("✉️ Paste Suspicious Message", height=200)
276
+ uploaded_file = st.file_uploader("📄 Upload PDF/TXT (optional)", type=["pdf", "txt"])
277
+
278
+ with col2:
279
+ language = st.selectbox("🌐 Preferred Language", language_choices)
280
+ role = st.selectbox("🧑‍💼 Your Role", role_choices)
281
+
282
+ analyze_btn = st.button("🔍 Analyze with AI")
283
+ clear_btn = st.button("🗑️ Clear History")
284
+
285
+ # =======================
286
+ # Function Definitions
287
+ # =======================
288
+ def extract_text_from_file(file):
289
+ if file is None:
290
+ return ""
291
+ ext = file.name.split(".")[-1].lower()
292
+ if ext == "pdf":
293
+ doc = fitz.open(stream=file.read(), filetype="pdf")
294
+ return "\n".join(page.get_text() for page in doc)
295
+ elif ext == "txt":
296
+ return file.read().decode("utf-8")
297
+ return ""
298
+
299
+ def analyze_with_huggingface(text):
300
+ try:
301
+ result = phishing_pipe(text)
302
+ label = result[0]['label']
303
+ confidence = round(result[0]['score'] * 100, 2)
304
+ threat_type = {
305
+ "PHISHING": "Phishing",
306
+ "SPAM": "Spam",
307
+ "MALWARE": "Malware",
308
+ "LEGITIMATE": "Safe"
309
+ }.get(label.upper(), "Unknown")
310
+ return label, confidence, threat_type
311
+ except Exception as e:
312
+ return "Error", 0, f"Error: {e}"
313
+
314
+ def semantic_analysis(text):
315
+ response = client.chat.completions.create(
316
+ model="llama3-8b-8192",
317
+ messages=[
318
+ {"role": "system", "content": "You are a cybersecurity assistant."},
319
+ {"role": "user", "content": f"Explain this suspicious message for a {role} in {language}:\n{text}"}
320
+ ]
321
+ )
322
+ raw = response.choices[0].message.content
323
+ clean = re.sub(r"Is there anything else you'd like.*", "", raw, flags=re.I).strip()
324
+ return clean
325
+
326
+ def translate_label(threat_type):
327
+ return TRANSLATIONS.get(threat_type, {}).get(language, threat_type)
328
+
329
+ def text_to_speech(text):
330
+ tts = gTTS(text=text, lang='en')
331
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as fp:
332
+ tts.save(fp.name)
333
+ return fp.name
334
+
335
+ def render_history():
336
+ with st.expander("🕓 View Analysis History"):
337
+ for i, record in enumerate(reversed(st.session_state.history)):
338
+ with st.container():
339
+ st.markdown(f"**🔢 Entry #{len(st.session_state.history) - i}**")
340
+ st.markdown(f"**📝 Input:** {record['input'][:100]}...")
341
+ st.markdown(f"**🔐 Type:** {record['threat']} | **📊 Confidence:** {record['score']}%")
342
+ st.markdown(f"**📖 Summary:** {record['summary'][:200]}...")
343
+ st.markdown("---")
344
+
345
+ # =======================
346
+ # Run Analysis
347
+ # =======================
348
+ if clear_btn:
349
+ st.session_state.history.clear()
350
+ st.success("✅ History cleared!")
351
+
352
+ if analyze_btn:
353
+ combined_text = text_input
354
+ if uploaded_file:
355
+ extracted = extract_text_from_file(uploaded_file)
356
+ combined_text += "\n" + extracted
357
+
358
+ if not combined_text.strip():
359
+ st.warning("⚠️ Please enter some text or upload a file to analyze.")
360
+ else:
361
+ label, score, threat_type = analyze_with_huggingface(combined_text)
362
+ translated_threat = translate_label(threat_type)
363
+
364
+ st.subheader("🔍 AI Threat Detection Result")
365
+ st.markdown(f"<div class='report-container'>"
366
+ f"<p><span class='highlight'>Prediction:</span> {label}</p>"
367
+ f"<p><span class='highlight'>Threat Type:</span> {threat_type} ({translated_threat})</p>"
368
+ f"<p><span class='highlight'>Confidence:</span> {score}%</p>"
369
+ f"</div>", unsafe_allow_html=True)
370
+
371
+ summary = ""
372
+ if threat_type.lower() != "safe":
373
+ with st.expander("🧠 Semantic Reanalysis by LLaMA"):
374
+ summary = semantic_analysis(combined_text)
375
+ st.write(summary)
376
+
377
+ if st.button("🔊 Play Explanation as Audio"):
378
+ audio_path = text_to_speech(summary)
379
+ with open(audio_path, "rb") as f:
380
+ st.audio(f.read(), format="audio/mp3")
381
+
382
+ # Save history
383
+ st.session_state.history.append({
384
+ "input": combined_text,
385
+ "threat": threat_type,
386
+ "score": score,
387
+ "summary": summary
388
+ })
389
+
390
+ with st.expander("📜 Glossary Help"):
391
+ for term, definition in GLOSSARY.items():
392
+ st.markdown(f"**{term.capitalize()}**: {definition}")
393
+
394
+ render_history()
395
 
396
  #App v 3
397
  # app.py