Files changed (1) hide show
  1. src/app.py +267 -44
src/app.py CHANGED
@@ -164,32 +164,251 @@ def plot_attention(text, attention_weights):
164
  return fig
165
 
166
  def main():
167
- st.title("πŸ“° Fake News Detection System")
168
- st.write("""
169
- This application uses a hybrid deep learning model (BERT + BiLSTM + Attention)
170
- to detect fake news articles. Enter a news article below to analyze it.
171
- """)
172
-
173
- # Sidebar
174
- st.sidebar.title("About")
175
- st.sidebar.info("""
176
-
177
- The model combines:
178
- - BERT for contextual embeddings
179
- - BiLSTM for sequence modeling
180
- - Attention mechanism for interpretability
181
- """)
182
-
183
- # Main content
184
- st.header("News Analysis")
185
-
186
- # Text input
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  news_text = st.text_area(
188
  "Enter the news article to analyze:",
189
  height=200,
190
  placeholder="Paste your news article here..."
191
  )
192
-
 
193
  if st.button("Analyze"):
194
  if news_text:
195
  with st.spinner("Analyzing the news article..."):
@@ -200,42 +419,46 @@ def main():
200
  col1, col2 = st.columns(2)
201
 
202
  with col1:
203
- st.subheader("Prediction")
 
204
  if result['label'] == 'FAKE':
205
- st.error(f"πŸ”΄ This news is likely FAKE (Confidence: {result['confidence']:.2%})")
206
  else:
207
- st.success(f"🟒 This news is likely REAL (Confidence: {result['confidence']:.2%})")
 
208
 
209
  with col2:
210
- st.subheader("Confidence Scores")
 
211
  st.plotly_chart(plot_confidence(result['probabilities']), use_container_width=True)
 
212
 
213
  # Show attention visualization
214
- st.subheader("Attention Analysis")
215
- st.write("""
216
- The attention weights show which parts of the text the model focused on
217
- while making its prediction. Higher weights indicate more important tokens.
218
- """)
219
  st.plotly_chart(plot_attention(news_text, result['attention_weights']), use_container_width=True)
 
220
 
221
  # Show model explanation
222
- st.subheader("Model Explanation")
 
223
  if result['label'] == 'FAKE':
224
- st.write("""
225
- The model identified this as fake news based on:
226
- - Linguistic patterns typical of fake news
227
- - Inconsistencies in the content
228
- - Attention weights on suspicious phrases
229
- """)
230
  else:
231
- st.write("""
232
- The model identified this as real news based on:
233
- - Credible language patterns
234
- - Consistent information
235
- - Attention weights on factual statements
236
- """)
237
  else:
238
  st.warning("Please enter a news article to analyze.")
239
 
 
 
 
 
 
 
 
 
 
240
  if __name__ == "__main__":
241
- main()
 
164
  return fig
165
 
166
  def main():
167
+ # Main Container
168
+ st.markdown('<div class="main-container">', unsafe_allow_html=True)
169
+
170
+ # Custom CSS with Poppins font
171
+ st.markdown("""
172
+ <style>
173
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
174
+
175
+ * {
176
+ font-family: 'Poppins', sans-serif !important;
177
+ box-sizing: border-box;
178
+ }
179
+
180
+ .stApp {
181
+ background: #ffffff;
182
+ min-height: 100vh;
183
+ color: #1f2a44;
184
+ }
185
+
186
+ #MainMenu {visibility: hidden;}
187
+ footer {visibility: hidden;}
188
+ .stDeployButton {display: none;}
189
+ header {visibility: hidden;}
190
+ .stApp > header {visibility: hidden;}
191
+
192
+ /* Main Container */
193
+ .main-container {
194
+ max-width: 1200px;
195
+ margin: 0 auto;
196
+ padding: 1rem 2rem;
197
+ }
198
+
199
+ /* Header Section */
200
+ .header-section {
201
+ text-align: center;
202
+ margin-bottom: 2.5rem;
203
+ padding: 1.5rem 0;
204
+ }
205
+
206
+ .header-title {
207
+ font-size: 2.25rem;
208
+ font-weight: 700;
209
+ color: #1f2a44;
210
+ margin: 0;
211
+ }
212
+
213
+ /* Section Styling */
214
+ .section {
215
+ margin-bottom: 2.5rem;
216
+ max-width: 1200px;
217
+ margin-left: auto;
218
+ margin-right: auto;
219
+ padding: 0 1rem;
220
+ }
221
+
222
+ .section-title {
223
+ font-size: 1.5rem;
224
+ font-weight: 600;
225
+ color: #1f2a44;
226
+ margin-bottom: 1rem;
227
+ display: flex;
228
+ align-items: center;
229
+ gap: 0.5rem;
230
+ }
231
+
232
+ .section-text {
233
+ font-size: 0.95rem;
234
+ color: #6b7280;
235
+ line-height: 1.6;
236
+ max-width: 800px;
237
+ margin: 0 auto;
238
+ }
239
+
240
+ /* Sidebar */
241
+ .stSidebar {
242
+ background: #f4f7fa;
243
+ padding: 1rem;
244
+ }
245
+
246
+ /* Input Section */
247
+ .input-container {
248
+ max-width: 800px;
249
+ margin: 0 auto;
250
+ }
251
+
252
+ .stTextArea > div > div > textarea {
253
+ border-radius: 8px !important;
254
+ border: 1px solid #d1d5db !important;
255
+ padding: 1rem !important;
256
+ font-size: 1rem !important;
257
+ background: #ffffff !important;
258
+ min-height: 200px !important;
259
+ transition: all 0.2s ease !important;
260
+ }
261
+
262
+ .stTextArea > div > div > textarea:focus {
263
+ border-color: #6366f1 !important;
264
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.1) !important;
265
+ outline: none !important;
266
+ }
267
+
268
+ .stTextArea > div > div > textarea::placeholder {
269
+ color: #9ca3af !important;
270
+ }
271
+
272
+ /* Button Styling */
273
+ .stButton > button {
274
+ background: #6366f1 !important;
275
+ color: white !important;
276
+ border-radius: 8px !important;
277
+ padding: 0.75rem 2rem !important;
278
+ font-size: 1rem !important;
279
+ font-weight: 600 !important;
280
+ transition: all 0.2s ease !important;
281
+ border: none !important;
282
+ width: 100% !important;
283
+ max-width: 300px;
284
+ }
285
+
286
+ .stButton > button:hover {
287
+ background: #4f46e5 !important;
288
+ transform: translateY(-1px) !important;
289
+ }
290
+
291
+ /* Results Section */
292
+ .results-container {
293
+ margin-top: 1rem;
294
+ padding: 1rem;
295
+ border-radius: 8px;
296
+ max-width: 1200px;
297
+ margin-left: auto;
298
+ margin-right: auto;
299
+ }
300
+
301
+ .result-card {
302
+ padding: 1rem;
303
+ border-radius: 8px;
304
+ border-left: 4px solid transparent;
305
+ margin-bottom: 1rem;
306
+ }
307
+
308
+ .fake-news {
309
+ background: #fef2f2;
310
+ border-left-color: #ef4444;
311
+ }
312
+
313
+ .real-news {
314
+ background: #ecfdf5;
315
+ border-left-color: #10b981;
316
+ }
317
+
318
+ .prediction-badge {
319
+ font-weight: 600;
320
+ font-size: 1rem;
321
+ margin-bottom: 0.5rem;
322
+ display: flex;
323
+ align-items: center;
324
+ gap: 0.5rem;
325
+ }
326
+
327
+ .confidence-score {
328
+ font-weight: 600;
329
+ margin-left: auto;
330
+ font-size: 1rem;
331
+ }
332
+
333
+ /* Chart Containers */
334
+ .chart-container {
335
+ padding: 1rem;
336
+ border-radius: 8px;
337
+ margin: 1rem 0;
338
+ max-width: 1200px;
339
+ margin-left: auto;
340
+ margin-right: auto;
341
+ }
342
+
343
+ /* Footer */
344
+ .footer {
345
+ border-top: 1px solid #e5e7eb;
346
+ padding: 1.5rem 0;
347
+ text-align: center;
348
+ max-width: 1200px;
349
+ margin: 2rem auto 0;
350
+ }
351
+
352
+ /* Responsive Design */
353
+ @media (max-width: 1024px) {
354
+ .main-container {
355
+ padding: 1rem;
356
+ }
357
+ .section {
358
+ padding: 0 0.5rem;
359
+ }
360
+ }
361
+
362
+ @media (max-width: 768px) {
363
+ .header-title {
364
+ font-size: 1.75rem;
365
+ }
366
+ .section-title {
367
+ font-size: 1.25rem;
368
+ }
369
+ .section-text {
370
+ font-size: 0.9rem;
371
+ }
372
+ }
373
+
374
+ @media (max-width: 480px) {
375
+ .header-title {
376
+ font-size: 1.5rem;
377
+ }
378
+ .section-title {
379
+ font-size: 1.1rem;
380
+ }
381
+ .section-text {
382
+ font-size: 0.85rem;
383
+ }
384
+ }
385
+ </style>
386
+ """, unsafe_allow_html=True)
387
+
388
+ # Header Section
389
+ st.markdown('<div class="header-section">', unsafe_allow_html=True)
390
+ st.markdown('<h1 class="header-title">πŸ“° TruthCheck - Advanced Fake News Detection System</h1>', unsafe_allow_html=True)
391
+ st.markdown('</div>', unsafe_allow_html=True)
392
+
393
+ # Main Content
394
+ st.markdown('<div class="section">', unsafe_allow_html=True)
395
+ st.markdown('<p class="section-text">This application uses a hybrid deep learning model (BERT + BiLSTM + Attention) to detect fake news articles. Enter a news article below to analyze it.</p>', unsafe_allow_html=True)
396
+ st.markdown('</div>', unsafe_allow_html=True)
397
+
398
+
399
+ # News Analysis Section
400
+ st.markdown('<div class="section">', unsafe_allow_html=True)
401
+ st.markdown('<h2 class="section-title">πŸ“‹ News Analysis</h2>', unsafe_allow_html=True)
402
+
403
+ # Input Section
404
+ st.markdown('<div class="input-container">', unsafe_allow_html=True)
405
  news_text = st.text_area(
406
  "Enter the news article to analyze:",
407
  height=200,
408
  placeholder="Paste your news article here..."
409
  )
410
+ st.markdown('</div>', unsafe_allow_html=True)
411
+
412
  if st.button("Analyze"):
413
  if news_text:
414
  with st.spinner("Analyzing the news article..."):
 
419
  col1, col2 = st.columns(2)
420
 
421
  with col1:
422
+ st.markdown('<div class="results-container">', unsafe_allow_html=True)
423
+ st.markdown('<h3 class="section-title">πŸ” Prediction</h3>', unsafe_allow_html=True)
424
  if result['label'] == 'FAKE':
425
+ st.markdown(f'<div class="result-card fake-news"><div class="prediction-badge">🚨 Fake News Detected <span class="confidence-score">{result["confidence"]:.2%}</span></div></div>', unsafe_allow_html=True)
426
  else:
427
+ st.markdown(f'<div class="result-card real-news"><div class="prediction-badge">βœ… Authentic News <span class="confidence-score">{result["confidence"]:.2%}</span></div></div>', unsafe_allow_html=True)
428
+ st.markdown('</div>', unsafe_allow_html=True)
429
 
430
  with col2:
431
+ st.markdown('<div class="results-container">', unsafe_allow_html=True)
432
+ st.markdown('<h3 class="section-title">πŸ“Š Confidence Scores</h3>', unsafe_allow_html=True)
433
  st.plotly_chart(plot_confidence(result['probabilities']), use_container_width=True)
434
+ st.markdown('</div>', unsafe_allow_html=True)
435
 
436
  # Show attention visualization
437
+ st.markdown('<div class="section">', unsafe_allow_html=True)
438
+ st.markdown('<h3 class="section-title">πŸ‘οΈ Attention Analysis</h3>', unsafe_allow_html=True)
439
+ st.markdown('<p class="section-text">The attention weights show which parts of the text the model focused on while making its prediction. Higher weights indicate more important tokens.</p>', unsafe_allow_html=True)
 
 
440
  st.plotly_chart(plot_attention(news_text, result['attention_weights']), use_container_width=True)
441
+ st.markdown('</div>', unsafe_allow_html=True)
442
 
443
  # Show model explanation
444
+ st.markdown('<div class="section">', unsafe_allow_html=True)
445
+ st.markdown('<h3 class="section-title">πŸ“ Model Explanation</h3>', unsafe_allow_html=True)
446
  if result['label'] == 'FAKE':
447
+ st.markdown('<p class="section-text">The model identified this as fake news based on:<ul><li>Linguistic patterns typical of fake news</li><li>Inconsistencies in the content</li><li>Attention weights on suspicious phrases</li></ul></p>', unsafe_allow_html=True)
 
 
 
 
 
448
  else:
449
+ st.markdown('<p class="section-text">The model identified this as real news based on:<ul><li>Credible language patterns</li><li>Consistent information</li><li>Attention weights on factual statements</li></ul></p>', unsafe_allow_html=True)
450
+ st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
451
  else:
452
  st.warning("Please enter a news article to analyze.")
453
 
454
+ # Footer
455
+ st.markdown("---")
456
+ st.markdown(
457
+ '<div class="footer"><p style="text-align: center; font-weight: 600; font-size: 16px;">πŸ’» Developed with ❀️ using Streamlit | Β© 2025</p></div>',
458
+ unsafe_allow_html=True
459
+ )
460
+
461
+ st.markdown('</div>', unsafe_allow_html=True) # Close main-container
462
+
463
  if __name__ == "__main__":
464
+ main()