Update app/streamlit_app.py
Browse files- app/streamlit_app.py +25 -79
app/streamlit_app.py
CHANGED
|
@@ -65,7 +65,7 @@ logger.info(f"Streamlit starting in {path_manager.environment} environment")
|
|
| 65 |
# Page configuration - MUST be first Streamlit command
|
| 66 |
st.set_page_config(
|
| 67 |
page_title="Fake News Detection System | MLOps Dashboard",
|
| 68 |
-
page_icon="
|
| 69 |
layout="wide",
|
| 70 |
initial_sidebar_state="expanded",
|
| 71 |
menu_items={
|
|
@@ -188,51 +188,6 @@ class EnhancedStreamlitApp:
|
|
| 188 |
min-height: 100vh;
|
| 189 |
color: #f39c12;
|
| 190 |
}
|
| 191 |
-
|
| 192 |
-
.stRadio > label > div[data-baseweb="radio"] > label > div > p {
|
| 193 |
-
color: #FFFFFF !important;
|
| 194 |
-
}
|
| 195 |
-
|
| 196 |
-
/*.stMarkdown h2 {
|
| 197 |
-
color: #FFFFFF !important;
|
| 198 |
-
}*/
|
| 199 |
-
|
| 200 |
-
.stMarkdown h1,
|
| 201 |
-
.stMarkdown h2,
|
| 202 |
-
.stMarkdown h3,
|
| 203 |
-
.stMarkdown h4,
|
| 204 |
-
.stMarkdown h5,
|
| 205 |
-
.stMarkdown h6 {
|
| 206 |
-
color: #FFFFFF !important;
|
| 207 |
-
}
|
| 208 |
-
|
| 209 |
-
/* Force widget labels & option text to white */
|
| 210 |
-
.stRadio label,
|
| 211 |
-
.stRadio div,
|
| 212 |
-
.stCheckbox label,
|
| 213 |
-
.stCheckbox div,
|
| 214 |
-
.stSelectbox label,
|
| 215 |
-
.stSelectbox div,
|
| 216 |
-
.stMultiSelect label,
|
| 217 |
-
.stMultiSelect div,
|
| 218 |
-
.stFileUploader label,
|
| 219 |
-
.stFileUploader div,
|
| 220 |
-
.stDownloadButton label,
|
| 221 |
-
.stDownloadButton div,
|
| 222 |
-
.stTextInput label,
|
| 223 |
-
.stTextArea label,
|
| 224 |
-
.stSlider label,
|
| 225 |
-
.stSlider div {
|
| 226 |
-
color: #FFFFFF !important;
|
| 227 |
-
}
|
| 228 |
-
|
| 229 |
-
/* Ensure radio/checkbox options are also white */
|
| 230 |
-
div[role="radiogroup"] label span,
|
| 231 |
-
div[role="checkbox"] span {
|
| 232 |
-
color: #FFFFFF !important;
|
| 233 |
-
}
|
| 234 |
-
|
| 235 |
-
|
| 236 |
|
| 237 |
/* Header Styling */
|
| 238 |
.main-header {
|
|
@@ -807,7 +762,7 @@ class EnhancedStreamlitApp:
|
|
| 807 |
|
| 808 |
def render_system_health_dashboard(self):
|
| 809 |
"""Render comprehensive system health dashboard"""
|
| 810 |
-
st.markdown("##
|
| 811 |
|
| 812 |
# Get health data
|
| 813 |
try:
|
|
@@ -822,31 +777,31 @@ class EnhancedStreamlitApp:
|
|
| 822 |
with col1:
|
| 823 |
status = health_data.get('status', 'unknown')
|
| 824 |
if status == 'healthy':
|
| 825 |
-
st.markdown('<div class="metric-card"><h3
|
| 826 |
unsafe_allow_html=True)
|
| 827 |
else:
|
| 828 |
-
st.markdown('<div class="metric-card"><h3
|
| 829 |
unsafe_allow_html=True)
|
| 830 |
|
| 831 |
with col2:
|
| 832 |
model_health = health_data.get('model_health', {})
|
| 833 |
model_status = model_health.get('status', 'unknown')
|
| 834 |
-
st.markdown(f'<div class="metric-card"><h3
|
| 835 |
unsafe_allow_html=True)
|
| 836 |
|
| 837 |
with col3:
|
| 838 |
system_health = health_data.get('system_health', {})
|
| 839 |
cpu_percent = system_health.get('cpu_percent', 0)
|
| 840 |
-
st.markdown(f'<div class="metric-card"><h3
|
| 841 |
unsafe_allow_html=True)
|
| 842 |
|
| 843 |
with col4:
|
| 844 |
memory_percent = system_health.get('memory_percent', 0)
|
| 845 |
-
st.markdown(f'<div class="metric-card"><h3
|
| 846 |
unsafe_allow_html=True)
|
| 847 |
|
| 848 |
# Detailed health information
|
| 849 |
-
with st.expander("
|
| 850 |
st.json(health_data)
|
| 851 |
|
| 852 |
else:
|
|
@@ -867,10 +822,10 @@ def main():
|
|
| 867 |
# Custom header
|
| 868 |
st.markdown("""
|
| 869 |
<div class="main-header">
|
| 870 |
-
<h1
|
| 871 |
<div class="subtitle">Production-Grade MLOps Pipeline with Statistical Rigor</div>
|
| 872 |
<br>
|
| 873 |
-
<div class="environment-badge"
|
| 874 |
</div>
|
| 875 |
""", unsafe_allow_html=True)
|
| 876 |
|
|
@@ -879,28 +834,19 @@ def main():
|
|
| 879 |
with col2:
|
| 880 |
if app.api_available:
|
| 881 |
st.markdown(
|
| 882 |
-
'<div
|
| 883 |
-
'<div class="status-indicator status-online">Γ°ΕΈΕΈΒ’ API Service: Online & Ready</div>'
|
| 884 |
-
'</div>',
|
| 885 |
unsafe_allow_html=True
|
| 886 |
)
|
| 887 |
-
st.divider()
|
| 888 |
else:
|
| 889 |
st.markdown(
|
| 890 |
-
|
| 891 |
-
|
| 892 |
-
<div class="status-indicator status-offline">Γ°ΕΈβΒ΄ API Service: Offline</div>
|
| 893 |
-
</div>
|
| 894 |
-
""",
|
| 895 |
-
unsafe_allow_html=True
|
| 896 |
)
|
| 897 |
-
st.divider()
|
| 898 |
-
|
| 899 |
|
| 900 |
# Enhanced Navigation
|
| 901 |
tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8 = st.tabs([
|
| 902 |
-
"
|
| 903 |
-
"
|
| 904 |
])
|
| 905 |
|
| 906 |
with tab1:
|
|
@@ -929,7 +875,7 @@ def main():
|
|
| 929 |
|
| 930 |
def render_prediction_interface():
|
| 931 |
"""Enhanced prediction interface with professional styling"""
|
| 932 |
-
st.markdown("##
|
| 933 |
st.markdown("*Analyze individual news articles with statistical confidence intervals*")
|
| 934 |
|
| 935 |
# Input method selection with enhanced UI
|
|
@@ -937,16 +883,16 @@ def render_prediction_interface():
|
|
| 937 |
with col1:
|
| 938 |
input_method = st.radio(
|
| 939 |
"Choose input method:",
|
| 940 |
-
["
|
| 941 |
horizontal=True
|
| 942 |
)
|
| 943 |
|
| 944 |
with col2:
|
| 945 |
-
show_advanced = st.checkbox("
|
| 946 |
|
| 947 |
user_text = ""
|
| 948 |
|
| 949 |
-
if input_method == "
|
| 950 |
user_text = st.text_area(
|
| 951 |
"Enter news article text:",
|
| 952 |
height=200,
|
|
@@ -1475,7 +1421,7 @@ def render_cv_results_dashboard():
|
|
| 1475 |
st.metric(
|
| 1476 |
f"{metric.upper()}",
|
| 1477 |
f"{mean_val:.4f}",
|
| 1478 |
-
delta=f"
|
| 1479 |
)
|
| 1480 |
|
| 1481 |
# Model quality indicators
|
|
@@ -1854,14 +1800,14 @@ def render_health_monitoring():
|
|
| 1854 |
st.markdown("**Available Datasets:**")
|
| 1855 |
datasets = env_info.get('available_datasets', {})
|
| 1856 |
for name, exists in datasets.items():
|
| 1857 |
-
status = "
|
| 1858 |
st.markdown(f"{status} {name}")
|
| 1859 |
|
| 1860 |
with col2:
|
| 1861 |
st.markdown("**Available Models:**")
|
| 1862 |
models = env_info.get('available_models', {})
|
| 1863 |
for name, exists in models.items():
|
| 1864 |
-
status = "
|
| 1865 |
st.markdown(f"{status} {name}")
|
| 1866 |
|
| 1867 |
# Model performance monitoring
|
|
@@ -2054,11 +2000,11 @@ def render_realtime_metrics():
|
|
| 2054 |
|
| 2055 |
for alert in alerts:
|
| 2056 |
if alert["level"] == "info":
|
| 2057 |
-
st.info(f"
|
| 2058 |
elif alert["level"] == "warning":
|
| 2059 |
-
st.warning(f"
|
| 2060 |
elif alert["level"] == "error":
|
| 2061 |
-
st.error(f"
|
| 2062 |
|
| 2063 |
else:
|
| 2064 |
st.warning("Real-time metrics not available. API monitoring service may be offline.")
|
|
|
|
| 65 |
# Page configuration - MUST be first Streamlit command
|
| 66 |
st.set_page_config(
|
| 67 |
page_title="Fake News Detection System | MLOps Dashboard",
|
| 68 |
+
page_icon="π°",
|
| 69 |
layout="wide",
|
| 70 |
initial_sidebar_state="expanded",
|
| 71 |
menu_items={
|
|
|
|
| 188 |
min-height: 100vh;
|
| 189 |
color: #f39c12;
|
| 190 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
|
| 192 |
/* Header Styling */
|
| 193 |
.main-header {
|
|
|
|
| 762 |
|
| 763 |
def render_system_health_dashboard(self):
|
| 764 |
"""Render comprehensive system health dashboard"""
|
| 765 |
+
st.markdown("## π₯ System Health Dashboard")
|
| 766 |
|
| 767 |
# Get health data
|
| 768 |
try:
|
|
|
|
| 777 |
with col1:
|
| 778 |
status = health_data.get('status', 'unknown')
|
| 779 |
if status == 'healthy':
|
| 780 |
+
st.markdown('<div class="metric-card"><h3>π’ System Status</h3><p>Healthy</p></div>',
|
| 781 |
unsafe_allow_html=True)
|
| 782 |
else:
|
| 783 |
+
st.markdown('<div class="metric-card"><h3>π΄ System Status</h3><p>Issues Detected</p></div>',
|
| 784 |
unsafe_allow_html=True)
|
| 785 |
|
| 786 |
with col2:
|
| 787 |
model_health = health_data.get('model_health', {})
|
| 788 |
model_status = model_health.get('status', 'unknown')
|
| 789 |
+
st.markdown(f'<div class="metric-card"><h3>π€ Model Health</h3><p>{model_status.title()}</p></div>',
|
| 790 |
unsafe_allow_html=True)
|
| 791 |
|
| 792 |
with col3:
|
| 793 |
system_health = health_data.get('system_health', {})
|
| 794 |
cpu_percent = system_health.get('cpu_percent', 0)
|
| 795 |
+
st.markdown(f'<div class="metric-card"><h3>π» CPU Usage</h3><p>{cpu_percent:.1f}%</p></div>',
|
| 796 |
unsafe_allow_html=True)
|
| 797 |
|
| 798 |
with col4:
|
| 799 |
memory_percent = system_health.get('memory_percent', 0)
|
| 800 |
+
st.markdown(f'<div class="metric-card"><h3>π§ Memory Usage</h3><p>{memory_percent:.1f}%</p></div>',
|
| 801 |
unsafe_allow_html=True)
|
| 802 |
|
| 803 |
# Detailed health information
|
| 804 |
+
with st.expander("π Detailed Health Information", expanded=False):
|
| 805 |
st.json(health_data)
|
| 806 |
|
| 807 |
else:
|
|
|
|
| 822 |
# Custom header
|
| 823 |
st.markdown("""
|
| 824 |
<div class="main-header">
|
| 825 |
+
<h1>π° Fake News Detection System</h1>
|
| 826 |
<div class="subtitle">Production-Grade MLOps Pipeline with Statistical Rigor</div>
|
| 827 |
<br>
|
| 828 |
+
<div class="environment-badge">π Environment: """ + path_manager.environment.title() + """</div>
|
| 829 |
</div>
|
| 830 |
""", unsafe_allow_html=True)
|
| 831 |
|
|
|
|
| 834 |
with col2:
|
| 835 |
if app.api_available:
|
| 836 |
st.markdown(
|
| 837 |
+
'<div class="status-indicator status-online">π’ API Service: Online & Ready</div>',
|
|
|
|
|
|
|
| 838 |
unsafe_allow_html=True
|
| 839 |
)
|
|
|
|
| 840 |
else:
|
| 841 |
st.markdown(
|
| 842 |
+
'<div class="status-indicator status-offline">π΄ API Service: Offline</div>',
|
| 843 |
+
unsafe_allow_html=True
|
|
|
|
|
|
|
|
|
|
|
|
|
| 844 |
)
|
|
|
|
|
|
|
| 845 |
|
| 846 |
# Enhanced Navigation
|
| 847 |
tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8 = st.tabs([
|
| 848 |
+
"π Prediction", "π Batch Analysis", "π Analytics", "π― Cross-Validation",
|
| 849 |
+
"π€ Model Training", "π System Logs", "π₯ Health Monitor", "β‘ Real-time Metrics"
|
| 850 |
])
|
| 851 |
|
| 852 |
with tab1:
|
|
|
|
| 875 |
|
| 876 |
def render_prediction_interface():
|
| 877 |
"""Enhanced prediction interface with professional styling"""
|
| 878 |
+
st.markdown("## π Single Text Analysis")
|
| 879 |
st.markdown("*Analyze individual news articles with statistical confidence intervals*")
|
| 880 |
|
| 881 |
# Input method selection with enhanced UI
|
|
|
|
| 883 |
with col1:
|
| 884 |
input_method = st.radio(
|
| 885 |
"Choose input method:",
|
| 886 |
+
["π Type Text", "π Upload File"],
|
| 887 |
horizontal=True
|
| 888 |
)
|
| 889 |
|
| 890 |
with col2:
|
| 891 |
+
show_advanced = st.checkbox("π¬ Show Advanced Options", value=False)
|
| 892 |
|
| 893 |
user_text = ""
|
| 894 |
|
| 895 |
+
if input_method == "π Type Text":
|
| 896 |
user_text = st.text_area(
|
| 897 |
"Enter news article text:",
|
| 898 |
height=200,
|
|
|
|
| 1421 |
st.metric(
|
| 1422 |
f"{metric.upper()}",
|
| 1423 |
f"{mean_val:.4f}",
|
| 1424 |
+
delta=f"Β±{std_val:.4f}"
|
| 1425 |
)
|
| 1426 |
|
| 1427 |
# Model quality indicators
|
|
|
|
| 1800 |
st.markdown("**Available Datasets:**")
|
| 1801 |
datasets = env_info.get('available_datasets', {})
|
| 1802 |
for name, exists in datasets.items():
|
| 1803 |
+
status = "β
" if exists else "β"
|
| 1804 |
st.markdown(f"{status} {name}")
|
| 1805 |
|
| 1806 |
with col2:
|
| 1807 |
st.markdown("**Available Models:**")
|
| 1808 |
models = env_info.get('available_models', {})
|
| 1809 |
for name, exists in models.items():
|
| 1810 |
+
status = "β
" if exists else "β"
|
| 1811 |
st.markdown(f"{status} {name}")
|
| 1812 |
|
| 1813 |
# Model performance monitoring
|
|
|
|
| 2000 |
|
| 2001 |
for alert in alerts:
|
| 2002 |
if alert["level"] == "info":
|
| 2003 |
+
st.info(f"βΉοΈ {alert['message']} - {alert['timestamp'].strftime('%H:%M:%S')}")
|
| 2004 |
elif alert["level"] == "warning":
|
| 2005 |
+
st.warning(f"β οΈ {alert['message']} - {alert['timestamp'].strftime('%H:%M:%S')}")
|
| 2006 |
elif alert["level"] == "error":
|
| 2007 |
+
st.error(f"π¨ {alert['message']} - {alert['timestamp'].strftime('%H:%M:%S')}")
|
| 2008 |
|
| 2009 |
else:
|
| 2010 |
st.warning("Real-time metrics not available. API monitoring service may be offline.")
|