Spaces:
Sleeping
Sleeping
import streamlit as st | |
import torch | |
import pandas as pd | |
import numpy as np | |
from pathlib import Path | |
import sys | |
import plotly.express as px | |
import plotly.graph_objects as go | |
from transformers import BertTokenizer | |
import nltk | |
# Download required NLTK data | |
try: | |
nltk.data.find('tokenizers/punkt') | |
except LookupError: | |
nltk.download('punkt') | |
try: | |
nltk.data.find('corpora/stopwords') | |
except LookupError: | |
nltk.download('stopwords') | |
try: | |
nltk.data.find('tokenizers/punkt_tab') | |
except LookupError: | |
nltk.download('punkt_tab') | |
try: | |
nltk.data.find('corpora/wordnet') | |
except LookupError: | |
nltk.download('wordnet') | |
# Add project root to Python path | |
project_root = Path(__file__).parent.parent | |
sys.path.append(str(project_root)) | |
from src.models.hybrid_model import HybridFakeNewsDetector | |
from src.config.config import * | |
from src.data.preprocessor import TextPreprocessor | |
# Custom CSS for modern, enhanced styling | |
st.markdown(""" | |
<style> | |
/* Import Google Fonts */ | |
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&family=Inter:wght@300;400;500;600;700&display=swap'); | |
/* Global Styles */ | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
.main { | |
padding: 0 !important; | |
max-width: 100% !important; | |
} | |
.stApp { | |
font-family: 'Inter', 'Poppins', sans-serif; | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #6B73FF 100%); | |
min-height: 100vh; | |
color: #2d3748; | |
} | |
/* Hide Streamlit elements */ | |
#MainMenu {visibility: hidden;} | |
footer {visibility: hidden;} | |
.stDeployButton {display: none;} | |
header {visibility: hidden;} | |
.stApp > header {visibility: hidden;} | |
/* Header Navigation */ | |
.header-nav { | |
background: rgba(255, 255, 255, 0.95); | |
backdrop-filter: blur(20px); | |
border-bottom: 1px solid rgba(255, 255, 255, 0.2); | |
padding: 1rem 2rem; | |
position: sticky; | |
top: 0; | |
z-index: 1000; | |
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); | |
} | |
.nav-brand { | |
font-family: 'Poppins', sans-serif; | |
font-size: 1.8rem; | |
font-weight: 800; | |
background: linear-gradient(135deg, #667eea, #764ba2); | |
-webkit-background-clip: text; | |
-webkit-text-fill-color: transparent; | |
background-clip: text; | |
display: inline-flex; | |
align-items: center; | |
gap: 0.5rem; | |
} | |
/* Hero Section */ | |
.hero-container { | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #6B73FF 100%); | |
padding: 6rem 2rem; | |
text-align: center; | |
color: white; | |
position: relative; | |
overflow: hidden; | |
} | |
.hero-container::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"><defs><radialGradient id="a" cx="50%" cy="50%"><stop offset="0%" stop-color="%23fff" stop-opacity="0.1"/><stop offset="100%" stop-color="%23fff" stop-opacity="0"/></radialGradient></defs><circle cx="200" cy="200" r="100" fill="url(%23a)"/><circle cx="800" cy="300" r="150" fill="url(%23a)"/><circle cx="400" cy="700" r="120" fill="url(%23a)"/></svg>'); | |
pointer-events: none; | |
} | |
.hero-content { | |
position: relative; | |
z-index: 2; | |
max-width: 800px; | |
margin: 0 auto; | |
} | |
.hero-badge { | |
display: inline-flex; | |
align-items: center; | |
gap: 0.5rem; | |
background: rgba(255, 255, 255, 0.2); | |
padding: 0.5rem 1.5rem; | |
border-radius: 50px; | |
font-size: 0.9rem; | |
font-weight: 500; | |
margin-bottom: 2rem; | |
backdrop-filter: blur(10px); | |
border: 1px solid rgba(255, 255, 255, 0.3); | |
} | |
.hero-title { | |
font-family: 'Poppins', sans-serif; | |
font-size: 4.5rem; | |
font-weight: 900; | |
margin-bottom: 1.5rem; | |
text-shadow: 2px 2px 4px rgba(0,0,0,0.3); | |
background: linear-gradient(45deg, #fff, #e0e7ff, #fff); | |
-webkit-background-clip: text; | |
-webkit-text-fill-color: transparent; | |
background-clip: text; | |
line-height: 1.1; | |
} | |
.hero-subtitle { | |
font-size: 1.4rem; | |
font-weight: 400; | |
margin-bottom: 3rem; | |
opacity: 0.95; | |
line-height: 1.7; | |
max-width: 700px; | |
margin-left: auto; | |
margin-right: auto; | |
} | |
.hero-stats { | |
display: flex; | |
justify-content: center; | |
gap: 3rem; | |
margin-top: 2rem; | |
} | |
.stat-item { | |
text-align: center; | |
} | |
.stat-number { | |
font-size: 2.5rem; | |
font-weight: 700; | |
display: block; | |
} | |
.stat-label { | |
font-size: 0.9rem; | |
opacity: 0.8; | |
} | |
/* Features Section */ | |
.features-section { | |
padding: 5rem 2rem; | |
background: #f8fafc; | |
position: relative; | |
} | |
.section-header { | |
text-align: center; | |
margin-bottom: 4rem; | |
} | |
.section-badge { | |
display: inline-flex; | |
align-items: center; | |
gap: 0.5rem; | |
background: linear-gradient(135deg, #667eea, #764ba2); | |
color: white; | |
padding: 0.5rem 1.5rem; | |
border-radius: 50px; | |
font-size: 0.85rem; | |
font-weight: 600; | |
margin-bottom: 1rem; | |
text-transform: uppercase; | |
letter-spacing: 0.5px; | |
} | |
.section-title { | |
font-family: 'Poppins', sans-serif; | |
font-size: 3rem; | |
font-weight: 700; | |
color: #1a202c; | |
margin-bottom: 1rem; | |
line-height: 1.2; | |
} | |
.section-description { | |
font-size: 1.2rem; | |
color: #4a5568; | |
max-width: 600px; | |
margin: 0 auto; | |
line-height: 1.6; | |
} | |
.features-grid { | |
display: grid; | |
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); | |
gap: 2rem; | |
max-width: 1200px; | |
margin: 0 auto; | |
} | |
.feature-card { | |
background: white; | |
padding: 2.5rem; | |
border-radius: 20px; | |
text-align: center; | |
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | |
border: 1px solid #e2e8f0; | |
position: relative; | |
overflow: hidden; | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); | |
} | |
.feature-card::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
height: 4px; | |
background: linear-gradient(135deg, #667eea, #764ba2); | |
} | |
.feature-card:hover { | |
transform: translateY(-12px); | |
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15); | |
border-color: #667eea; | |
} | |
.feature-icon { | |
font-size: 3.5rem; | |
margin-bottom: 1.5rem; | |
display: block; | |
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.1)); | |
} | |
.feature-title { | |
font-family: 'Poppins', sans-serif; | |
font-size: 1.4rem; | |
font-weight: 600; | |
color: #1a202c; | |
margin-bottom: 1rem; | |
} | |
.feature-description { | |
color: #4a5568; | |
line-height: 1.6; | |
font-size: 1rem; | |
} | |
/* Main Content Section */ | |
.main-content { | |
background: white; | |
margin: 3rem 2rem; | |
padding: 4rem; | |
border-radius: 24px; | |
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1); | |
position: relative; | |
overflow: hidden; | |
} | |
.main-content::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
height: 6px; | |
background: linear-gradient(135deg, #667eea, #764ba2, #6B73FF); | |
} | |
/* Input Section Styling */ | |
.input-container { | |
max-width: 800px; | |
margin: 0 auto; | |
} | |
.stTextArea > div > div > textarea { | |
border-radius: 16px !important; | |
border: 2px solid #e2e8f0 !important; | |
padding: 1.5rem !important; | |
font-size: 1.1rem !important; | |
font-family: 'Inter', sans-serif !important; | |
transition: all 0.3s ease !important; | |
background: #fafafa !important; | |
resize: vertical !important; | |
min-height: 200px !important; | |
} | |
.stTextArea > div > div > textarea:focus { | |
border-color: #667eea !important; | |
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1) !important; | |
background: white !important; | |
outline: none !important; | |
} | |
.stTextArea > div > div > textarea::placeholder { | |
color: #a0aec0 !important; | |
font-style: italic !important; | |
} | |
/* Enhanced Button Styling */ | |
.stButton > button { | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; | |
color: white !important; | |
border: none !important; | |
border-radius: 16px !important; | |
padding: 1rem 3rem !important; | |
font-size: 1.2rem !important; | |
font-weight: 600 !important; | |
font-family: 'Poppins', sans-serif !important; | |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; | |
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4) !important; | |
width: 100% !important; | |
position: relative !important; | |
overflow: hidden !important; | |
} | |
.stButton > button:hover { | |
transform: translateY(-3px) !important; | |
box-shadow: 0 15px 35px rgba(102, 126, 234, 0.6) !important; | |
background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%) !important; | |
} | |
.stButton > button:active { | |
transform: translateY(-1px) !important; | |
} | |
/* Results Section */ | |
.results-container { | |
margin-top: 3rem; | |
padding: 2rem; | |
background: linear-gradient(135deg, #f7fafc 0%, #edf2f7 100%); | |
border-radius: 20px; | |
border: 1px solid #e2e8f0; | |
} | |
.result-card { | |
background: white; | |
padding: 2.5rem; | |
border-radius: 20px; | |
margin: 1.5rem 0; | |
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08); | |
border-left: 6px solid transparent; | |
transition: all 0.3s ease; | |
} | |
.result-card:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 12px 35px rgba(0, 0, 0, 0.12); | |
} | |
.prediction-badge { | |
display: inline-flex; | |
align-items: center; | |
gap: 0.75rem; | |
padding: 1rem 2rem; | |
border-radius: 50px; | |
font-weight: 700; | |
font-size: 1.1rem; | |
margin-bottom: 1rem; | |
} | |
.fake-news { | |
background: linear-gradient(135deg, #fed7d7 0%, #feb2b2 100%); | |
color: #c53030; | |
border-left-color: #e53e3e; | |
} | |
.real-news { | |
background: linear-gradient(135deg, #c6f6d5 0%, #9ae6b4 100%); | |
color: #2f855a; | |
border-left-color: #38a169; | |
} | |
.confidence-score { | |
font-size: 1.4rem; | |
font-weight: 700; | |
margin-left: auto; | |
} | |
/* Analysis Cards */ | |
.analysis-grid { | |
display: grid; | |
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
gap: 2rem; | |
margin: 2rem 0; | |
} | |
.analysis-card { | |
background: white; | |
padding: 2rem; | |
border-radius: 16px; | |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); | |
border-top: 4px solid #667eea; | |
} | |
.analysis-title { | |
font-family: 'Poppins', sans-serif; | |
font-size: 1.3rem; | |
font-weight: 600; | |
color: #1a202c; | |
margin-bottom: 1rem; | |
display: flex; | |
align-items: center; | |
gap: 0.5rem; | |
} | |
.analysis-content { | |
color: #4a5568; | |
line-height: 1.6; | |
} | |
.analysis-list { | |
list-style: none; | |
padding: 0; | |
} | |
.analysis-list li { | |
padding: 0.5rem 0; | |
padding-left: 1.5rem; | |
position: relative; | |
border-bottom: 1px solid #f1f5f9; | |
} | |
.analysis-list li:before { | |
content: 'β'; | |
position: absolute; | |
left: 0; | |
color: #667eea; | |
font-weight: bold; | |
} | |
.analysis-list li:last-child { | |
border-bottom: none; | |
} | |
/* Chart Containers */ | |
.chart-container { | |
background: white; | |
padding: 2rem; | |
border-radius: 16px; | |
margin: 1rem 0; | |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05); | |
border: 1px solid #f1f5f9; | |
} | |
/* Footer */ | |
.footer { | |
background: linear-gradient(135deg, #1a202c 0%, #2d3748 100%); | |
color: white; | |
padding: 4rem 2rem 2rem; | |
text-align: center; | |
margin-top: 5rem; | |
position: relative; | |
overflow: hidden; | |
} | |
.footer::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
height: 6px; | |
background: linear-gradient(135deg, #667eea, #764ba2, #6B73FF); | |
} | |
.footer-content { | |
max-width: 1200px; | |
margin: 0 auto; | |
position: relative; | |
z-index: 2; | |
} | |
.footer-title { | |
font-family: 'Poppins', sans-serif; | |
font-size: 2rem; | |
font-weight: 700; | |
margin-bottom: 1rem; | |
background: linear-gradient(135deg, #667eea, #764ba2); | |
-webkit-background-clip: text; | |
-webkit-text-fill-color: transparent; | |
background-clip: text; | |
} | |
.footer-text { | |
color: #cbd5e0; | |
margin-bottom: 2rem; | |
line-height: 1.7; | |
font-size: 1.1rem; | |
} | |
.footer-links { | |
display: flex; | |
justify-content: center; | |
gap: 3rem; | |
margin-bottom: 3rem; | |
flex-wrap: wrap; | |
} | |
.footer-link { | |
color: #cbd5e0; | |
text-decoration: none; | |
transition: all 0.3s ease; | |
font-weight: 500; | |
padding: 0.5rem 1rem; | |
border-radius: 8px; | |
} | |
.footer-link:hover { | |
color: white; | |
background: rgba(102, 126, 234, 0.2); | |
transform: translateY(-2px); | |
} | |
.footer-bottom { | |
border-top: 1px solid #4a5568; | |
padding-top: 2rem; | |
color: #a0aec0; | |
font-size: 0.95rem; | |
line-height: 1.6; | |
} | |
/* Loading Spinner Custom */ | |
.stSpinner > div { | |
border-color: #667eea transparent #667eea transparent !important; | |
} | |
/* Responsive Design */ | |
@media (max-width: 768px) { | |
.hero-title { | |
font-size: 3rem; | |
} | |
.hero-stats { | |
flex-direction: column; | |
gap: 1.5rem; | |
} | |
.features-grid { | |
grid-template-columns: 1fr; | |
} | |
.main-content { | |
margin: 2rem 1rem; | |
padding: 2rem; | |
} | |
.section-title { | |
font-size: 2.2rem; | |
} | |
.footer-links { | |
flex-direction: column; | |
gap: 1rem; | |
} | |
.analysis-grid { | |
grid-template-columns: 1fr; | |
} | |
} | |
@media (max-width: 480px) { | |
.hero-title { | |
font-size: 2.5rem; | |
} | |
.section-title { | |
font-size: 2rem; | |
} | |
.feature-card { | |
padding: 2rem 1.5rem; | |
} | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
def load_model_and_tokenizer(): | |
"""Load the model and tokenizer (cached).""" | |
model = HybridFakeNewsDetector( | |
bert_model_name=BERT_MODEL_NAME, | |
lstm_hidden_size=LSTM_HIDDEN_SIZE, | |
lstm_num_layers=LSTM_NUM_LAYERS, | |
dropout_rate=DROPOUT_RATE | |
) | |
state_dict = torch.load(SAVED_MODELS_DIR / "final_model.pt", map_location=torch.device('cpu')) | |
model_state_dict = model.state_dict() | |
filtered_state_dict = {k: v for k, v in state_dict.items() if k in model_state_dict} | |
model.load_state_dict(filtered_state_dict, strict=False) | |
model.eval() | |
tokenizer = BertTokenizer.from_pretrained(BERT_MODEL_NAME) | |
return model, tokenizer | |
def get_preprocessor(): | |
"""Get the text preprocessor (cached).""" | |
return TextPreprocessor() | |
def predict_news(text): | |
"""Predict if the given news is fake or real.""" | |
model, tokenizer = load_model_and_tokenizer() | |
preprocessor = get_preprocessor() | |
processed_text = preprocessor.preprocess_text(text) | |
encoding = tokenizer.encode_plus( | |
processed_text, | |
add_special_tokens=True, | |
max_length=MAX_SEQUENCE_LENGTH, | |
padding='max_length', | |
truncation=True, | |
return_attention_mask=True, | |
return_tensors='pt' | |
) | |
with torch.no_grad(): | |
outputs = model( | |
encoding['input_ids'], | |
encoding['attention_mask'] | |
) | |
probabilities = torch.softmax(outputs['logits'], dim=1) | |
prediction = torch.argmax(outputs['logits'], dim=1) | |
attention_weights = outputs['attention_weights'] | |
attention_weights_np = attention_weights[0].cpu().numpy() | |
return { | |
'prediction': prediction.item(), | |
'label': 'FAKE' if prediction.item() == 1 else 'REAL', | |
'confidence': torch.max(probabilities, dim=1)[0].item(), | |
'probabilities': { | |
'REAL': probabilities[0][0].item(), | |
'FAKE': probabilities[0][1].item() | |
}, | |
'attention_weights': attention_weights_np | |
} | |
def plot_confidence(probabilities): | |
"""Plot prediction confidence with enhanced styling.""" | |
colors = ['#22c55e', '#ef4444'] | |
fig = go.Figure(data=[ | |
go.Bar( | |
x=list(probabilities.keys()), | |
y=list(probabilities.values()), | |
text=[f'{p:.1%}' for p in probabilities.values()], | |
textposition='auto', | |
textfont=dict(size=16, family="Poppins", color="white"), | |
marker=dict( | |
color=colors, | |
line=dict(color='rgba(255,255,255,0.3)', width=2), | |
pattern_shape="", | |
), | |
hovertemplate='<b>%{x}</b><br>Confidence: %{y:.1%}<extra></extra>', | |
width=[0.6, 0.6] | |
) | |
]) | |
fig.update_layout( | |
title={ | |
'text': 'π Prediction Confidence', | |
'x': 0.5, | |
'xanchor': 'center', | |
'font': {'size': 24, 'family': 'Poppins', 'color': '#1a202c'} | |
}, | |
xaxis=dict( | |
title='Classification', | |
titlefont=dict(size=16, family='Inter', color='#4a5568'), | |
tickfont=dict(size=14, family='Inter', color='#4a5568'), | |
showgrid=False, | |
), | |
yaxis=dict( | |
title='Probability', | |
titlefont=dict(size=16, family='Inter', color='#4a5568'), | |
tickfont=dict(size=14, family='Inter', color='#4a5568'), | |
range=[0, 1], | |
tickformat='.0%', | |
showgrid=True, | |
gridcolor='rgba(0,0,0,0.05)', | |
), | |
template='plotly_white', | |
plot_bgcolor='rgba(0,0,0,0)', | |
paper_bgcolor='rgba(0,0,0,0)', | |
font={'family': 'Inter'}, | |
margin=dict(l=50, r=50, t=80, b=50), | |
height=400 | |
) | |
return fig | |
def plot_attention(text, attention_weights): | |
"""Plot attention weights with enhanced styling.""" | |
tokens = text.split()[:20] # Limit to first 20 tokens for better visualization | |
attention_weights = attention_weights[:len(tokens)] | |
if isinstance(attention_weights, (list, np.ndarray)): | |
attention_weights = np.array(attention_weights).flatten() | |
# Normalize attention weights | |
if len(attention_weights) > 0 and max(attention_weights) > 0: | |
normalized_weights = attention_weights / max(attention_weights) | |
else: | |
normalized_weights = attention_weights | |
# Create gradient colors | |
colors = [f'rgba(102, 126, 234, {0.3 + 0.7 * float(w)})' for w in normalized_weights] | |
fig = go.Figure(data=[ | |
go.Bar( | |
x=tokens, | |
y=attention_weights, | |
text=[f'{float(w):.3f}' for w in attention_weights], | |
textposition='auto', | |
textfont=dict(size=12, family="Inter", color="white"), | |
marker=dict( | |
color=colors, | |
line=dict(color='rgba(102, 126, 234, 0.8)', width=1), | |
), | |
hovertemplate='<b>%{x}</b><br>Attention: %{y:.3f}<extra></extra>', | |
) | |
]) | |
fig.update_layout( | |
title={ | |
'text': 'π― Attention Weights Analysis', | |
'x': 0.5, | |
'xanchor': 'center', | |
'font': {'size': 24, 'family': 'Poppins', 'color': '#1a202c'} | |
}, | |
xaxis=dict( | |
title='Words/Tokens', | |
titlefont=dict(size=16, family='Inter', color='#4a5568'), | |
tickfont=dict(size=12, family='Inter', color='#4a5568'), | |
tickangle=45, | |
showgrid=False, | |
), | |
yaxis=dict( | |
title='Attention Score', | |
titlefont=dict(size=16, family='Inter', color='#4a5568'), | |
tickfont=dict(size=14, family='Inter', color='#4a5568'), | |
showgrid=True, | |
gridcolor='rgba(0,0,0,0.05)', | |
), | |
template='plotly_white', | |
plot_bgcolor='rgba(0,0,0,0)', | |
paper_bgcolor='rgba(0,0,0,0)', | |
font={'family': 'Inter'}, | |
margin=dict(l=50, r=50, t=80, b=100), | |
height=450 | |
) | |
return fig | |
def main(): | |
# Header Navigation | |
st.markdown(""" | |
<div class="header-nav"> | |
<div class="nav-brand"> | |
π‘οΈ TruthCheck | |
</div> | |
</div> | |
""", unsafe_allow_html=True) | |
# Hero Section | |
st.markdown(""" | |
<div class="hero-container"> | |
<div class="hero-content"> | |
<div class="hero-badge"> | |
β‘ Powered by Advanced AI Technology | |
</div> | |
<h1 class="hero-title">π‘οΈ TruthCheck</h1> | |
<h2 style="font-size: 1.8rem; font-weight: 600; margin-bottom: 1rem; opacity: 0.9;">Advanced Fake News Detector</h2> | |
<p class="hero-subtitle"> | |
π Leverage cutting-edge deep learning technology to instantly analyze and verify news articles. | |
Our hybrid BERT-BiLSTM model delivers precise, trustworthy results with detailed explanations. | |
</p> | |
<div class="hero-stats"> | |
<div class="stat-item"> | |
<span class="stat-number">95%+</span> | |
<span class="stat-label">Accuracy</span> | |
</div> | |
<div class="stat-item"> | |
<span class="stat-number"><3s</span> | |
<span class="stat-label">Analysis Time</span> | |
</div> | |
<div class="stat-item"> | |
<span class="stat-number">24/7</span> | |
<span class="stat-label">Available</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
""", unsafe_allow_html=True) | |
# Features Section | |
st.markdown(""" | |
<div class="features-section"> | |
<div class="section-header"> | |
<div class="section-badge"> | |
π Advanced Features | |
</div> | |
<h2 class="section-title">Why Choose TruthCheck?</h2> | |
<p class="section-description"> | |
Our state-of-the-art AI combines multiple advanced technologies to deliver unparalleled accuracy in fake news detection | |
</p> | |
</div> | |
<div class="features-grid"> | |
<div class="feature-card"> | |
<span class="feature-icon">π€</span> | |
<h3 class="feature-title">BERT Transformer</h3> | |
<p class="feature-description"> | |
Utilizes state-of-the-art BERT transformer architecture for deep contextual understanding and semantic analysis of news content with unprecedented accuracy. | |
</p> | |
</div> | |
<div class="feature-card"> | |
<span class="feature-icon">π§ </span> | |
<h3 class="feature-title">BiLSTM Networks</h3> | |
<p class="feature-description"> | |
Advanced bidirectional LSTM networks capture sequential patterns, temporal dependencies, and linguistic structures in news articles for comprehensive analysis. | |
</p> | |
</div> | |
<div class="feature-card"> | |
<span class="feature-icon">ποΈ</span> | |
<h3 class="feature-title">Attention Mechanism</h3> | |
<p class="feature-description"> | |
Sophisticated attention layers provide transparent insights into model decision-making, highlighting key phrases and suspicious content patterns. | |
</p> | |
</div> | |
<div class="feature-card"> | |
<span class="feature-icon">β‘</span> | |
<h3 class="feature-title">Real-time Processing</h3> | |
<p class="feature-description"> | |
Lightning-fast analysis delivers results in seconds, enabling immediate verification of news content without compromising accuracy or detail. | |
</p> | |
</div> | |
<div class="feature-card"> | |
<span class="feature-icon">π</span> | |
<h3 class="feature-title">Confidence Scoring</h3> | |
<p class="feature-description"> | |
Detailed confidence metrics and probability distributions provide clear insights into prediction reliability and uncertainty levels. | |
</p> | |
</div> | |
<div class="feature-card"> | |
<span class="feature-icon">π</span> | |
<h3 class="feature-title">Privacy Protected</h3> | |
<p class="feature-description"> | |
Your data is processed securely with no storage or tracking. Complete privacy protection ensures your news analysis remains confidential. | |
</p> | |
</div> | |
</div> | |
</div> | |
""", unsafe_allow_html=True) | |
# Main Content Section | |
st.markdown(""" | |
<div class="main-content"> | |
<div class="section-header"> | |
<div class="section-badge"> | |
π AI Analysis | |
</div> | |
<h2 class="section-title">Analyze News Article</h2> | |
<p class="section-description"> | |
π Simply paste any news article below and our advanced AI will provide instant, detailed analysis with confidence scores, attention weights, and comprehensive insights. | |
</p> | |
</div> | |
<div class="input-container"> | |
""", unsafe_allow_html=True) | |
# Input Section | |
news_text = st.text_area( | |
"", | |
height=250, | |
placeholder="π° Paste your news article here for comprehensive AI analysis...\n\nπ‘ Tip: Longer articles (100+ words) typically provide more accurate results.\n\nπ Our AI will analyze linguistic patterns, factual consistency, and content structure to determine authenticity.", | |
key="news_input", | |
help="Enter the full text of a news article for analysis. The more complete the article, the more accurate the analysis will be." | |
) | |
st.markdown("</div>", unsafe_allow_html=True) | |
# Enhanced Button Section | |
col1, col2, col3 = st.columns([1, 2, 1]) | |
with col2: | |
analyze_button = st.button( | |
"π Analyze Article with AI", | |
key="analyze_button", | |
help="Click to start AI-powered analysis of the news article" | |
) | |
if analyze_button: | |
if news_text and len(news_text.strip()) > 10: | |
with st.spinner("π€ AI is analyzing the article... Please wait"): | |
try: | |
result = predict_news(news_text) | |
# Results Container | |
st.markdown('<div class="results-container">', unsafe_allow_html=True) | |
# Main Prediction Result | |
col1, col2 = st.columns([1, 1], gap="large") | |
with col1: | |
st.markdown("### π― AI Prediction Result") | |
if result['label'] == 'FAKE': | |
st.markdown(f''' | |
<div class="result-card fake-news"> | |
<div class="prediction-badge"> | |
π¨ FAKE NEWS DETECTED | |
<span class="confidence-score">{result["confidence"]:.1%}</span> | |
</div> | |
<div style="font-size: 1.1rem; color: #c53030; line-height: 1.6;"> | |
<strong>β οΈ Warning:</strong> Our AI model has identified this content as likely misinformation based on linguistic patterns, structural analysis, and content inconsistencies. | |
</div> | |
</div> | |
''', unsafe_allow_html=True) | |
else: | |
st.markdown(f''' | |
<div class="result-card real-news"> | |
<div class="prediction-badge"> | |
β AUTHENTIC NEWS | |
<span class="confidence-score">{result["confidence"]:.1%}</span> | |
</div> | |
<div style="font-size: 1.1rem; color: #2f855a; line-height: 1.6;"> | |
<strong>β Verified:</strong> This content appears to be legitimate news based on professional writing style, factual consistency, and structural integrity. | |
</div> | |
</div> | |
''', unsafe_allow_html=True) | |
with col2: | |
st.markdown("### π Confidence Breakdown") | |
st.markdown('<div class="chart-container">', unsafe_allow_html=True) | |
st.plotly_chart(plot_confidence(result['probabilities']), use_container_width=True) | |
st.markdown('</div>', unsafe_allow_html=True) | |
# Attention Analysis | |
st.markdown("### π― AI Attention Analysis") | |
st.markdown(""" | |
<p style="color: #4a5568; text-align: center; margin-bottom: 2rem; font-size: 1.1rem; line-height: 1.6;"> | |
π§ The visualization below reveals which words and phrases our AI model focused on during analysis. | |
<strong>Higher attention scores</strong> (darker colors) indicate words that significantly influenced the prediction. | |
</p> | |
""", unsafe_allow_html=True) | |
st.markdown('<div class="chart-container">', unsafe_allow_html=True) | |
st.plotly_chart(plot_attention(news_text, result['attention_weights']), use_container_width=True) | |
st.markdown('</div>', unsafe_allow_html=True) | |
# Detailed Analysis | |
st.markdown("### π Comprehensive AI Analysis") | |
if result['label'] == 'FAKE': | |
st.markdown(""" | |
<div class="analysis-grid"> | |
<div class="analysis-card"> | |
<h4 class="analysis-title">β οΈ Misinformation Indicators</h4> | |
<div class="analysis-content"> | |
<ul class="analysis-list"> | |
<li><strong>Linguistic Anomalies:</strong> Detected language patterns commonly associated with fabricated content and misinformation campaigns</li> | |
<li><strong>Structural Inconsistencies:</strong> Identified irregular text flow, unusual formatting, or non-standard journalistic structure</li> | |
<li><strong>Content Reliability:</strong> Found potential factual inconsistencies, exaggerated claims, or misleading statements</li> | |
<li><strong>Emotional Manipulation:</strong> High attention on emotionally charged language designed to provoke strong reactions</li> | |
<li><strong>Source Credibility:</strong> Writing style and presentation lack hallmarks of professional journalism</li> | |
</ul> | |
</div> | |
</div> | |
<div class="analysis-card"> | |
<h4 class="analysis-title">π‘οΈ Recommended Actions</h4> | |
<div class="analysis-content"> | |
<ul class="analysis-list"> | |
<li><strong>Verify Sources:</strong> Cross-reference information with multiple reputable news outlets and official sources</li> | |
<li><strong>Check Facts:</strong> Use fact-checking websites like Snopes, PolitiFact, or FactCheck.org for verification</li> | |
<li><strong>Avoid Sharing:</strong> Do not share this content until authenticity is confirmed through reliable sources</li> | |
<li><strong>Report Misinformation:</strong> Consider reporting to platform moderators if shared on social media</li> | |
<li><strong>Stay Informed:</strong> Follow trusted news sources for accurate information on this topic</li> | |
</ul> | |
</div> | |
</div> | |
</div> | |
""", unsafe_allow_html=True) | |
else: | |
st.markdown(""" | |
<div class="analysis-grid"> | |
<div class="analysis-card"> | |
<h4 class="analysis-title">β Authenticity Indicators</h4> | |
<div class="analysis-content"> | |
<ul class="analysis-list"> | |
<li><strong>Professional Language:</strong> Demonstrates standard journalistic writing style with balanced, objective reporting tone</li> | |
<li><strong>Structural Integrity:</strong> Follows conventional news article format with proper introduction, body, and conclusion</li> | |
<li><strong>Factual Consistency:</strong> Information appears coherent, logically structured, and factually consistent throughout</li> | |
<li><strong>Neutral Presentation:</strong> Maintains objectivity without excessive emotional language or bias indicators</li> | |
<li><strong>Credible Content:</strong> Contains specific details, proper context, and verifiable information patterns</li> | |
</ul> | |
</div> | |
</div> | |
<div class="analysis-card"> | |
<h4 class="analysis-title">π Best Practices</h4> | |
<div class="analysis-content"> | |
<ul class="analysis-list"> | |
<li><strong>Continue Verification:</strong> While likely authentic, always cross-reference important news from multiple sources</li> | |
<li><strong>Check Publication Date:</strong> Ensure the information is current and hasn't been superseded by newer developments</li> | |
<li><strong>Verify Author Credentials:</strong> Research the author's background and expertise in the subject matter</li> | |
<li><strong>Review Source Reputation:</strong> Confirm the publication's credibility and editorial standards</li> | |
<li><strong>Stay Updated:</strong> Monitor for any corrections, updates, or follow-up reporting on the topic</li> | |
</ul> | |
</div> | |
</div> | |
</div> | |
""", unsafe_allow_html=True) | |
# Technical Details | |
with st.expander("π§ Technical Analysis Details", expanded=False): | |
col1, col2, col3 = st.columns(3) | |
with col1: | |
st.metric( | |
label="π― Prediction Confidence", | |
value=f"{result['confidence']:.2%}", | |
help="Overall confidence in the AI's prediction" | |
) | |
with col2: | |
st.metric( | |
label="π REAL Probability", | |
value=f"{result['probabilities']['REAL']:.2%}", | |
help="Probability that the content is authentic news" | |
) | |
with col3: | |
st.metric( | |
label="β οΈ FAKE Probability", | |
value=f"{result['probabilities']['FAKE']:.2%}", | |
help="Probability that the content is fake news" | |
) | |
st.markdown("---") | |
st.markdown(""" | |
**π€ Model Information:** | |
- **Architecture:** Hybrid BERT + BiLSTM with Attention Mechanism | |
- **Training Data:** Extensive dataset of verified real and fake news articles | |
- **Features:** Contextual embeddings, sequential patterns, attention weights | |
- **Performance:** 95%+ accuracy on validation datasets | |
""") | |
st.markdown('</div>', unsafe_allow_html=True) | |
except Exception as e: | |
st.error(f""" | |
π¨ **Analysis Error Occurred** | |
We encountered an issue while analyzing your article. This might be due to: | |
- Technical server issues | |
- Content formatting problems | |
- Model loading difficulties | |
**Error Details:** {str(e)} | |
Please try again in a few moments or contact support if the issue persists. | |
""") | |
else: | |
st.markdown(''' | |
<div class="main-content"> | |
<div style="background: linear-gradient(135deg, #fef2f2 0%, #fecaca 100%); color: #991b1b; padding: 2rem; border-radius: 16px; text-align: center; border-left: 6px solid #ef4444;"> | |
<h3 style="margin-bottom: 1rem;">β οΈ Input Required</h3> | |
<p style="font-size: 1.1rem; line-height: 1.6;"> | |
Please enter a news article (at least 10 words) to perform AI analysis. | |
<br><strong>π‘ Tip:</strong> Longer, complete articles provide more accurate results. | |
</p> | |
</div> | |
</div> | |
''', unsafe_allow_html=True) | |
st.markdown('</div>', unsafe_allow_html=True) | |
# Footer | |
st.markdown(""" | |
<div class="footer"> | |
<div class="footer-content"> | |
<h3 class="footer-title">π‘οΈ TruthCheck AI</h3> | |
<p class="footer-text"> | |
π Empowering global communities with cutting-edge AI-driven news verification technology. | |
Built with advanced deep learning models, natural language processing, and transparent machine learning practices | |
to combat misinformation and promote media literacy worldwide. | |
</p> | |
<div class="footer-links"> | |
<a href="#" class="footer-link">π About TruthCheck</a> | |
<a href="#" class="footer-link">π¬ How It Works</a> | |
<a href="#" class="footer-link">π Accuracy Reports</a> | |
<a href="#" class="footer-link">π Privacy Policy</a> | |
<a href="#" class="footer-link">π Contact Support</a> | |
<a href="#" class="footer-link">π Report Issues</a> | |
</div> | |
<div class="footer-bottom"> | |
<p style="margin-bottom: 1rem;"> | |
© 2025 TruthCheck AI. Built with β€οΈ using Streamlit, BERT, PyTorch, and Advanced Machine Learning. | |
</p> | |
<p> | |
<strong>π Disclaimer:</strong> This tool provides AI-based analysis for informational purposes. | |
Always verify important information through multiple reliable sources and exercise critical thinking. | |
Our AI model achieves high accuracy but is not infallible - human judgment remains essential. | |
</p> | |
</div> | |
</div> | |
</div> | |
""", unsafe_allow_html=True) | |
if __name__ == "__main__": | |
main() |