Update app/streamlit_app.py
Browse files- app/streamlit_app.py +68 -185
app/streamlit_app.py
CHANGED
|
@@ -253,21 +253,20 @@ st.set_page_config(
|
|
| 253 |
initial_sidebar_state="expanded"
|
| 254 |
)
|
| 255 |
|
| 256 |
-
# Professional Color Scheme -
|
| 257 |
COLORS = {
|
| 258 |
-
'primary': '#
|
| 259 |
-
'secondary': '#
|
| 260 |
'accent': '#F8F9FA', # Light Grey/White
|
| 261 |
-
'success': '#
|
| 262 |
-
'warning': '#
|
| 263 |
'danger': '#E74C3C', # Red
|
| 264 |
-
'info': '#3498DB', #
|
| 265 |
-
'dark': '#
|
| 266 |
-
'light': '#
|
| 267 |
'white': '#FFFFFF', # Pure White
|
| 268 |
-
'text_primary': '#
|
| 269 |
-
'text_secondary': '#
|
| 270 |
-
'blue_hover': '#1E40AF' # Darker blue for hover states
|
| 271 |
}
|
| 272 |
|
| 273 |
# Enhanced Custom CSS with Professional Styling
|
|
@@ -288,18 +287,21 @@ st.markdown(f"""
|
|
| 288 |
font-size: 3.5rem;
|
| 289 |
font-weight: 700;
|
| 290 |
text-align: center;
|
| 291 |
-
|
|
|
|
|
|
|
|
|
|
| 292 |
margin: 2rem 0;
|
| 293 |
-
text-shadow: 0
|
| 294 |
}}
|
| 295 |
|
| 296 |
/* Subtitle */
|
| 297 |
.subtitle {{
|
| 298 |
font-family: 'Inter', sans-serif;
|
| 299 |
font-size: 1.2rem;
|
| 300 |
-
font-weight:
|
| 301 |
text-align: center;
|
| 302 |
-
color: {COLORS['
|
| 303 |
margin-bottom: 2rem;
|
| 304 |
line-height: 1.6;
|
| 305 |
}}
|
|
@@ -373,13 +375,13 @@ st.markdown(f"""
|
|
| 373 |
|
| 374 |
/* Environment Info */
|
| 375 |
.environment-info {{
|
| 376 |
-
background: {COLORS['
|
| 377 |
color: {COLORS['dark']};
|
| 378 |
padding: 1.5rem;
|
| 379 |
border-radius: 16px;
|
| 380 |
-
border: 1px solid {COLORS['primary']};
|
| 381 |
margin: 1rem 0;
|
| 382 |
-
box-shadow: 0 4px 16px rgba(
|
| 383 |
}}
|
| 384 |
|
| 385 |
.environment-info h4 {{
|
|
@@ -390,7 +392,7 @@ st.markdown(f"""
|
|
| 390 |
|
| 391 |
/* Button Styling */
|
| 392 |
.stButton > button {{
|
| 393 |
-
background: {COLORS['primary']};
|
| 394 |
color: {COLORS['white']};
|
| 395 |
border: none;
|
| 396 |
border-radius: 12px;
|
|
@@ -398,13 +400,12 @@ st.markdown(f"""
|
|
| 398 |
font-weight: 600;
|
| 399 |
font-family: 'Inter', sans-serif;
|
| 400 |
transition: all 0.3s ease;
|
| 401 |
-
box-shadow: 0 4px 16px rgba(
|
| 402 |
}}
|
| 403 |
|
| 404 |
.stButton > button:hover {{
|
| 405 |
-
background: {COLORS['blue_hover']};
|
| 406 |
transform: translateY(-2px);
|
| 407 |
-
box-shadow: 0 6px 24px rgba(
|
| 408 |
}}
|
| 409 |
|
| 410 |
/* Tab Styling */
|
|
@@ -413,35 +414,22 @@ st.markdown(f"""
|
|
| 413 |
border-radius: 12px;
|
| 414 |
padding: 0.5rem;
|
| 415 |
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
| 416 |
-
border: 1px solid {COLORS['light']};
|
| 417 |
}}
|
| 418 |
|
| 419 |
.stTabs [data-baseweb="tab"] {{
|
| 420 |
-
background:
|
| 421 |
-
border: 2px solid {COLORS['light']};
|
| 422 |
border-radius: 8px;
|
| 423 |
color: {COLORS['text_secondary']};
|
| 424 |
font-weight: 500;
|
| 425 |
padding: 0.75rem 1.5rem;
|
| 426 |
margin: 0 0.25rem;
|
| 427 |
transition: all 0.3s ease;
|
| 428 |
-
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
| 429 |
-
}}
|
| 430 |
-
|
| 431 |
-
.stTabs [data-baseweb="tab"]:hover {{
|
| 432 |
-
border-color: {COLORS['primary']};
|
| 433 |
-
background: rgba(218, 165, 32, 0.1);
|
| 434 |
-
transform: translateY(-1px);
|
| 435 |
-
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
| 436 |
}}
|
| 437 |
|
| 438 |
.stTabs [data-baseweb="tab"][data-state="active"] {{
|
| 439 |
-
background: {COLORS['primary']};
|
| 440 |
-
border: 2px solid {COLORS['primary']};
|
| 441 |
color: {COLORS['white']};
|
| 442 |
font-weight: 600;
|
| 443 |
-
transform: translateY(-2px);
|
| 444 |
-
box-shadow: 0 4px 12px rgba(218, 165, 32, 0.3);
|
| 445 |
}}
|
| 446 |
|
| 447 |
/* Sidebar Styling */
|
|
@@ -489,26 +477,10 @@ st.markdown(f"""
|
|
| 489 |
|
| 490 |
/* Progress Bar */
|
| 491 |
.stProgress > div > div > div > div {{
|
| 492 |
-
background: {COLORS['primary']};
|
| 493 |
border-radius: 8px;
|
| 494 |
}}
|
| 495 |
|
| 496 |
-
/* Style widget containers instead of hiding them */
|
| 497 |
-
.stRadio, .stCheckbox, .stFileUploader, .stTextInput, .stTextArea, .stSelectbox {{
|
| 498 |
-
background-color: {COLORS['accent']} !important;
|
| 499 |
-
border: 1px solid {COLORS['light']} !important;
|
| 500 |
-
border-radius: 8px !important;
|
| 501 |
-
padding: 0.5rem !important;
|
| 502 |
-
margin: 0.5rem 0 !important;
|
| 503 |
-
}}
|
| 504 |
-
|
| 505 |
-
/* Style nested containers to match */
|
| 506 |
-
.stRadio > div, .stCheckbox > div, .stFileUploader > div,
|
| 507 |
-
.stTextInput > div, .stTextArea > div, .stSelectbox > div {{
|
| 508 |
-
background-color: transparent !important;
|
| 509 |
-
border: none !important;
|
| 510 |
-
}}
|
| 511 |
-
|
| 512 |
/* Alert Styling */
|
| 513 |
.alert-critical {{
|
| 514 |
background: linear-gradient(135deg, {COLORS['danger']}20 0%, {COLORS['danger']}10 100%);
|
|
@@ -561,7 +533,7 @@ st.markdown(f"""
|
|
| 561 |
display: inline-block;
|
| 562 |
width: 4px;
|
| 563 |
height: 24px;
|
| 564 |
-
background: {COLORS['primary']};
|
| 565 |
margin-right: 12px;
|
| 566 |
border-radius: 2px;
|
| 567 |
}}
|
|
@@ -732,8 +704,8 @@ def create_confidence_gauge(confidence: float, prediction: str):
|
|
| 732 |
'bar': {'color': COLORS['danger'] if prediction == "Fake" else COLORS['success']},
|
| 733 |
'steps': [
|
| 734 |
{'range': [0, 50], 'color': COLORS['light']},
|
| 735 |
-
{'range': [50, 80], 'color': '
|
| 736 |
-
{'range': [80, 100], 'color': '
|
| 737 |
],
|
| 738 |
'threshold': {
|
| 739 |
'line': {'color': COLORS['primary'], 'width': 4},
|
|
@@ -843,19 +815,17 @@ def main():
|
|
| 843 |
with tab1:
|
| 844 |
st.markdown('<h2 class="section-header">π― Single Text Analysis</h2>', unsafe_allow_html=True)
|
| 845 |
|
| 846 |
-
# Input methods with
|
| 847 |
col1, col2 = st.columns([3, 1])
|
| 848 |
with col1:
|
| 849 |
st.markdown('<h3 class="subsection-header">Input Method</h3>', unsafe_allow_html=True)
|
| 850 |
with col2:
|
| 851 |
-
st.markdown('<div style="background: transparent; padding: 0;">', unsafe_allow_html=True)
|
| 852 |
input_method = st.radio(
|
| 853 |
"Choose input method:",
|
| 854 |
["Type Text", "Upload File"],
|
| 855 |
horizontal=True,
|
| 856 |
label_visibility="collapsed"
|
| 857 |
)
|
| 858 |
-
st.markdown('</div>', unsafe_allow_html=True)
|
| 859 |
|
| 860 |
user_text = ""
|
| 861 |
|
|
@@ -1645,14 +1615,16 @@ def render_logs_tab():
|
|
| 1645 |
"Alerts Log": path_manager.get_logs_path("monitor/alerts.json")
|
| 1646 |
}
|
| 1647 |
|
| 1648 |
-
|
| 1649 |
-
|
| 1650 |
-
|
| 1651 |
-
|
| 1652 |
-
|
| 1653 |
-
|
| 1654 |
-
|
| 1655 |
-
|
|
|
|
|
|
|
| 1656 |
|
| 1657 |
if st.button("π Load Log", type="primary", use_container_width=True) or auto_refresh_logs:
|
| 1658 |
log_path = log_files[selected_log]
|
|
@@ -1760,130 +1732,41 @@ def render_system_status_tab():
|
|
| 1760 |
</div>
|
| 1761 |
""", unsafe_allow_html=True)
|
| 1762 |
|
| 1763 |
-
#
|
| 1764 |
model_health = health_data.get('model_health', {})
|
| 1765 |
system_health = health_data.get('system_health', {})
|
| 1766 |
api_health = health_data.get('api_health', {})
|
| 1767 |
|
| 1768 |
-
# Create professional health cards
|
| 1769 |
col1, col2, col3 = st.columns(3)
|
| 1770 |
|
| 1771 |
with col1:
|
| 1772 |
-
st.markdown(
|
| 1773 |
-
|
| 1774 |
-
|
| 1775 |
-
|
| 1776 |
-
|
| 1777 |
-
|
| 1778 |
-
|
| 1779 |
-
|
| 1780 |
-
|
| 1781 |
-
if status_val == 'healthy':
|
| 1782 |
-
st.markdown(f'<div style="color: {COLORS["success"]}; font-weight: 600; margin: 0.5rem 0;">Status: β
Healthy</div>', unsafe_allow_html=True)
|
| 1783 |
-
else:
|
| 1784 |
-
st.markdown(f'<div style="color: {COLORS["danger"]}; font-weight: 600; margin: 0.5rem 0;">Status: β Unhealthy</div>', unsafe_allow_html=True)
|
| 1785 |
-
|
| 1786 |
-
# Key model metrics
|
| 1787 |
-
last_check = model_health.get('last_check', 'Unknown')
|
| 1788 |
-
if last_check != 'Unknown':
|
| 1789 |
-
try:
|
| 1790 |
-
from datetime import datetime
|
| 1791 |
-
check_time = datetime.fromisoformat(last_check.replace('Z', '+00:00'))
|
| 1792 |
-
formatted_time = check_time.strftime('%H:%M:%S')
|
| 1793 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 0.9rem;">Last Check: {formatted_time}</div>', unsafe_allow_html=True)
|
| 1794 |
-
except:
|
| 1795 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 0.9rem;">Last Check: {last_check}</div>', unsafe_allow_html=True)
|
| 1796 |
-
|
| 1797 |
-
model_available = model_health.get('model_available', False)
|
| 1798 |
-
pipeline_available = model_health.get('pipeline_available', False)
|
| 1799 |
-
vectorizer_available = model_health.get('vectorizer_available', False)
|
| 1800 |
-
|
| 1801 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 0.9rem;">Model Available: {"β
" if model_available else "β"}</div>', unsafe_allow_html=True)
|
| 1802 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 0.9rem;">Pipeline Available: {"β
" if pipeline_available else "β"}</div>', unsafe_allow_html=True)
|
| 1803 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 0.9rem;">Vectorizer Available: {"β
" if vectorizer_available else "β"}</div>', unsafe_allow_html=True)
|
| 1804 |
-
|
| 1805 |
-
# Model paths
|
| 1806 |
-
vectorizer_path = model_health.get('vectorizer_path', 'Unknown')
|
| 1807 |
-
pipeline_path = model_health.get('pipeline_path', 'Unknown')
|
| 1808 |
-
if vectorizer_path != 'Unknown':
|
| 1809 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 0.8rem; margin-top: 0.5rem;">Vectorizer Path: {vectorizer_path}</div>', unsafe_allow_html=True)
|
| 1810 |
-
if pipeline_path != 'Unknown':
|
| 1811 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 0.8rem;">Pipeline Path: {pipeline_path}</div>', unsafe_allow_html=True)
|
| 1812 |
-
|
| 1813 |
-
st.markdown("""
|
| 1814 |
-
</div>
|
| 1815 |
-
</div>
|
| 1816 |
-
</div>
|
| 1817 |
-
""", unsafe_allow_html=True)
|
| 1818 |
|
| 1819 |
with col2:
|
| 1820 |
-
st.markdown(
|
| 1821 |
-
|
| 1822 |
-
|
| 1823 |
-
|
| 1824 |
-
|
| 1825 |
-
|
| 1826 |
-
|
| 1827 |
-
|
| 1828 |
-
|
| 1829 |
-
|
| 1830 |
-
disk_percent = system_health.get('disk_percent', 0)
|
| 1831 |
-
|
| 1832 |
-
# CPU Usage
|
| 1833 |
-
cpu_color = COLORS['success'] if cpu_percent < 70 else COLORS['warning'] if cpu_percent < 85 else COLORS['danger']
|
| 1834 |
-
st.markdown(f'<div style="color: {cpu_color}; font-weight: 600; margin: 0.5rem 0;">CPU Percent</div>', unsafe_allow_html=True)
|
| 1835 |
-
st.markdown(f'<div style="color: {cpu_color}; font-size: 1.5rem; font-weight: 700;">{cpu_percent:.1f}%</div>', unsafe_allow_html=True)
|
| 1836 |
-
|
| 1837 |
-
# Memory Usage
|
| 1838 |
-
memory_color = COLORS['success'] if memory_percent < 70 else COLORS['warning'] if memory_percent < 85 else COLORS['danger']
|
| 1839 |
-
st.markdown(f'<div style="color: {memory_color}; font-weight: 600; margin: 0.5rem 0;">Memory Percent</div>', unsafe_allow_html=True)
|
| 1840 |
-
st.markdown(f'<div style="color: {memory_color}; font-size: 1.5rem; font-weight: 700;">{memory_percent:.1f}%</div>', unsafe_allow_html=True)
|
| 1841 |
-
|
| 1842 |
-
# Disk Usage
|
| 1843 |
-
disk_color = COLORS['success'] if disk_percent < 70 else COLORS['warning'] if disk_percent < 85 else COLORS['danger']
|
| 1844 |
-
st.markdown(f'<div style="color: {disk_color}; font-weight: 600; margin: 0.5rem 0;">Disk Percent</div>', unsafe_allow_html=True)
|
| 1845 |
-
st.markdown(f'<div style="color: {disk_color}; font-size: 1.5rem; font-weight: 700;">{disk_percent:.1f}%</div>', unsafe_allow_html=True)
|
| 1846 |
-
|
| 1847 |
-
# Uptime
|
| 1848 |
-
uptime = system_health.get('uptime', 0)
|
| 1849 |
-
uptime_hours = uptime / 3600 if uptime else 0
|
| 1850 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-weight: 600; margin: 0.5rem 0;">Uptime</div>', unsafe_allow_html=True)
|
| 1851 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 1.2rem; font-weight: 600;">{uptime_hours:.1f}h</div>', unsafe_allow_html=True)
|
| 1852 |
-
|
| 1853 |
-
st.markdown("""
|
| 1854 |
-
</div>
|
| 1855 |
-
</div>
|
| 1856 |
-
</div>
|
| 1857 |
-
""", unsafe_allow_html=True)
|
| 1858 |
|
| 1859 |
with col3:
|
| 1860 |
-
st.markdown(
|
| 1861 |
-
<div class="status-card" style="border: 2px solid {COLORS['secondary']};">
|
| 1862 |
-
<div style="text-align: center; padding: 1rem;">
|
| 1863 |
-
<div style="color: {COLORS['secondary']}; font-size: 2rem; margin-bottom: 0.5rem;">π</div>
|
| 1864 |
-
<h3 style="color: {COLORS['secondary']}; margin: 0.5rem 0; font-weight: 600;">API Health</h3>
|
| 1865 |
-
<div style="margin-top: 1rem;">
|
| 1866 |
-
""", unsafe_allow_html=True)
|
| 1867 |
-
|
| 1868 |
-
rate_limit_active = api_health.get('rate_limit_active', False)
|
| 1869 |
-
active_connections = api_health.get('active_connections', 0)
|
| 1870 |
-
|
| 1871 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-weight: 600; margin: 0.5rem 0;">Rate Limit Active: {"β
" if rate_limit_active else "β"}</div>', unsafe_allow_html=True)
|
| 1872 |
-
|
| 1873 |
-
st.markdown(f'<div style="color: {COLORS["secondary"]}; font-weight: 600; margin: 0.5rem 0;">Active Connections</div>', unsafe_allow_html=True)
|
| 1874 |
-
st.markdown(f'<div style="color: {COLORS["secondary"]}; font-size: 1.5rem; font-weight: 700;">{active_connections}</div>', unsafe_allow_html=True)
|
| 1875 |
-
|
| 1876 |
-
# Add more API health metrics if available
|
| 1877 |
for key, value in api_health.items():
|
| 1878 |
-
|
| 1879 |
-
|
| 1880 |
-
st.markdown(f'<div style="color: {COLORS["text_secondary"]}; font-size: 0.9rem; margin: 0.2rem 0;">{display_key}: {value}</div>', unsafe_allow_html=True)
|
| 1881 |
-
|
| 1882 |
-
st.markdown("""
|
| 1883 |
-
</div>
|
| 1884 |
-
</div>
|
| 1885 |
-
</div>
|
| 1886 |
-
""", unsafe_allow_html=True)
|
| 1887 |
|
| 1888 |
except Exception as e:
|
| 1889 |
st.markdown(f"""
|
|
@@ -2297,9 +2180,9 @@ def render_cv_results_section():
|
|
| 2297 |
if 'model_version' in cv_results:
|
| 2298 |
st.markdown(f"""
|
| 2299 |
<div class="info-message">
|
| 2300 |
-
|
| 2301 |
-
|
| 2302 |
-
|
| 2303 |
</div>
|
| 2304 |
""", unsafe_allow_html=True)
|
| 2305 |
|
|
@@ -2366,8 +2249,8 @@ def render_model_comparison_section():
|
|
| 2366 |
|
| 2367 |
st.markdown(f"""
|
| 2368 |
<div class="info-message">
|
| 2369 |
-
|
| 2370 |
-
|
| 2371 |
</div>
|
| 2372 |
""", unsafe_allow_html=True)
|
| 2373 |
|
|
|
|
| 253 |
initial_sidebar_state="expanded"
|
| 254 |
)
|
| 255 |
|
| 256 |
+
# Professional Color Scheme - Sophisticated Gold/Grey/White Theme
|
| 257 |
COLORS = {
|
| 258 |
+
'primary': '#D4AF37', # Gold
|
| 259 |
+
'secondary': '#2C3E50', # Dark Grey
|
| 260 |
'accent': '#F8F9FA', # Light Grey/White
|
| 261 |
+
'success': '#27AE60', # Green
|
| 262 |
+
'warning': '#F39C12', # Orange
|
| 263 |
'danger': '#E74C3C', # Red
|
| 264 |
+
'info': '#3498DB', # Blue
|
| 265 |
+
'dark': '#34495E', # Darker Grey
|
| 266 |
+
'light': '#ECF0F1', # Very Light Grey
|
| 267 |
'white': '#FFFFFF', # Pure White
|
| 268 |
+
'text_primary': '#2C3E50', # Dark Grey for main text
|
| 269 |
+
'text_secondary': '#7F8C8D' # Medium Grey for secondary text
|
|
|
|
| 270 |
}
|
| 271 |
|
| 272 |
# Enhanced Custom CSS with Professional Styling
|
|
|
|
| 287 |
font-size: 3.5rem;
|
| 288 |
font-weight: 700;
|
| 289 |
text-align: center;
|
| 290 |
+
background: linear-gradient(135deg, {COLORS['primary']} 0%, {COLORS['warning']} 100%);
|
| 291 |
+
-webkit-background-clip: text;
|
| 292 |
+
-webkit-text-fill-color: transparent;
|
| 293 |
+
background-clip: text;
|
| 294 |
margin: 2rem 0;
|
| 295 |
+
text-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
| 296 |
}}
|
| 297 |
|
| 298 |
/* Subtitle */
|
| 299 |
.subtitle {{
|
| 300 |
font-family: 'Inter', sans-serif;
|
| 301 |
font-size: 1.2rem;
|
| 302 |
+
font-weight: 400;
|
| 303 |
text-align: center;
|
| 304 |
+
color: {COLORS['text_secondary']};
|
| 305 |
margin-bottom: 2rem;
|
| 306 |
line-height: 1.6;
|
| 307 |
}}
|
|
|
|
| 375 |
|
| 376 |
/* Environment Info */
|
| 377 |
.environment-info {{
|
| 378 |
+
background: linear-gradient(135deg, {COLORS['primary']}20 0%, {COLORS['primary']}10 100%);
|
| 379 |
color: {COLORS['dark']};
|
| 380 |
padding: 1.5rem;
|
| 381 |
border-radius: 16px;
|
| 382 |
+
border: 1px solid {COLORS['primary']}40;
|
| 383 |
margin: 1rem 0;
|
| 384 |
+
box-shadow: 0 4px 16px rgba(212, 175, 55, 0.1);
|
| 385 |
}}
|
| 386 |
|
| 387 |
.environment-info h4 {{
|
|
|
|
| 392 |
|
| 393 |
/* Button Styling */
|
| 394 |
.stButton > button {{
|
| 395 |
+
background: linear-gradient(135deg, {COLORS['primary']} 0%, {COLORS['warning']} 100%);
|
| 396 |
color: {COLORS['white']};
|
| 397 |
border: none;
|
| 398 |
border-radius: 12px;
|
|
|
|
| 400 |
font-weight: 600;
|
| 401 |
font-family: 'Inter', sans-serif;
|
| 402 |
transition: all 0.3s ease;
|
| 403 |
+
box-shadow: 0 4px 16px rgba(212, 175, 55, 0.3);
|
| 404 |
}}
|
| 405 |
|
| 406 |
.stButton > button:hover {{
|
|
|
|
| 407 |
transform: translateY(-2px);
|
| 408 |
+
box-shadow: 0 6px 24px rgba(212, 175, 55, 0.4);
|
| 409 |
}}
|
| 410 |
|
| 411 |
/* Tab Styling */
|
|
|
|
| 414 |
border-radius: 12px;
|
| 415 |
padding: 0.5rem;
|
| 416 |
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
|
|
|
| 417 |
}}
|
| 418 |
|
| 419 |
.stTabs [data-baseweb="tab"] {{
|
| 420 |
+
background: transparent;
|
|
|
|
| 421 |
border-radius: 8px;
|
| 422 |
color: {COLORS['text_secondary']};
|
| 423 |
font-weight: 500;
|
| 424 |
padding: 0.75rem 1.5rem;
|
| 425 |
margin: 0 0.25rem;
|
| 426 |
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 427 |
}}
|
| 428 |
|
| 429 |
.stTabs [data-baseweb="tab"][data-state="active"] {{
|
| 430 |
+
background: linear-gradient(135deg, {COLORS['primary']} 0%, {COLORS['warning']} 100%);
|
|
|
|
| 431 |
color: {COLORS['white']};
|
| 432 |
font-weight: 600;
|
|
|
|
|
|
|
| 433 |
}}
|
| 434 |
|
| 435 |
/* Sidebar Styling */
|
|
|
|
| 477 |
|
| 478 |
/* Progress Bar */
|
| 479 |
.stProgress > div > div > div > div {{
|
| 480 |
+
background: linear-gradient(135deg, {COLORS['primary']} 0%, {COLORS['warning']} 100%);
|
| 481 |
border-radius: 8px;
|
| 482 |
}}
|
| 483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
/* Alert Styling */
|
| 485 |
.alert-critical {{
|
| 486 |
background: linear-gradient(135deg, {COLORS['danger']}20 0%, {COLORS['danger']}10 100%);
|
|
|
|
| 533 |
display: inline-block;
|
| 534 |
width: 4px;
|
| 535 |
height: 24px;
|
| 536 |
+
background: linear-gradient(135deg, {COLORS['primary']} 0%, {COLORS['warning']} 100%);
|
| 537 |
margin-right: 12px;
|
| 538 |
border-radius: 2px;
|
| 539 |
}}
|
|
|
|
| 704 |
'bar': {'color': COLORS['danger'] if prediction == "Fake" else COLORS['success']},
|
| 705 |
'steps': [
|
| 706 |
{'range': [0, 50], 'color': COLORS['light']},
|
| 707 |
+
{'range': [50, 80], 'color': COLORS['warning'] + '40'},
|
| 708 |
+
{'range': [80, 100], 'color': COLORS['success'] + '40'}
|
| 709 |
],
|
| 710 |
'threshold': {
|
| 711 |
'line': {'color': COLORS['primary'], 'width': 4},
|
|
|
|
| 815 |
with tab1:
|
| 816 |
st.markdown('<h2 class="section-header">π― Single Text Analysis</h2>', unsafe_allow_html=True)
|
| 817 |
|
| 818 |
+
# Input methods with professional styling
|
| 819 |
col1, col2 = st.columns([3, 1])
|
| 820 |
with col1:
|
| 821 |
st.markdown('<h3 class="subsection-header">Input Method</h3>', unsafe_allow_html=True)
|
| 822 |
with col2:
|
|
|
|
| 823 |
input_method = st.radio(
|
| 824 |
"Choose input method:",
|
| 825 |
["Type Text", "Upload File"],
|
| 826 |
horizontal=True,
|
| 827 |
label_visibility="collapsed"
|
| 828 |
)
|
|
|
|
| 829 |
|
| 830 |
user_text = ""
|
| 831 |
|
|
|
|
| 1615 |
"Alerts Log": path_manager.get_logs_path("monitor/alerts.json")
|
| 1616 |
}
|
| 1617 |
|
| 1618 |
+
# Group log controls in container
|
| 1619 |
+
with st.container():
|
| 1620 |
+
col1, col2, col3 = st.columns([2, 1, 1])
|
| 1621 |
+
|
| 1622 |
+
with col1:
|
| 1623 |
+
selected_log = st.selectbox("Select log file:", list(log_files.keys()))
|
| 1624 |
+
with col2:
|
| 1625 |
+
max_entries = st.number_input("Max entries:", min_value=10, max_value=1000, value=50)
|
| 1626 |
+
with col3:
|
| 1627 |
+
auto_refresh_logs = st.checkbox("Auto refresh", value=False)
|
| 1628 |
|
| 1629 |
if st.button("π Load Log", type="primary", use_container_width=True) or auto_refresh_logs:
|
| 1630 |
log_path = log_files[selected_log]
|
|
|
|
| 1732 |
</div>
|
| 1733 |
""", unsafe_allow_html=True)
|
| 1734 |
|
| 1735 |
+
# Health components
|
| 1736 |
model_health = health_data.get('model_health', {})
|
| 1737 |
system_health = health_data.get('system_health', {})
|
| 1738 |
api_health = health_data.get('api_health', {})
|
| 1739 |
|
|
|
|
| 1740 |
col1, col2, col3 = st.columns(3)
|
| 1741 |
|
| 1742 |
with col1:
|
| 1743 |
+
st.markdown('<h4>π€ Model Health</h4>', unsafe_allow_html=True)
|
| 1744 |
+
for key, value in model_health.items():
|
| 1745 |
+
if key not in ['test_prediction', 'model_path', 'data_path', 'environment', 'file_exists']:
|
| 1746 |
+
display_key = key.replace('_', ' ').title()
|
| 1747 |
+
if isinstance(value, bool):
|
| 1748 |
+
status_icon = "β
" if value else "β"
|
| 1749 |
+
st.write(f"**{display_key}:** {status_icon}")
|
| 1750 |
+
else:
|
| 1751 |
+
st.write(f"**{display_key}:** {value}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1752 |
|
| 1753 |
with col2:
|
| 1754 |
+
st.markdown('<h4>π» System Health</h4>', unsafe_allow_html=True)
|
| 1755 |
+
for key, value in system_health.items():
|
| 1756 |
+
display_key = key.replace('_', ' ').title()
|
| 1757 |
+
if 'percent' in key:
|
| 1758 |
+
st.metric(display_key, f"{value:.1f}%")
|
| 1759 |
+
elif 'uptime' in key:
|
| 1760 |
+
uptime_hours = value / 3600
|
| 1761 |
+
st.metric(display_key, f"{uptime_hours:.1f}h")
|
| 1762 |
+
else:
|
| 1763 |
+
st.write(f"**{display_key}:** {value}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1764 |
|
| 1765 |
with col3:
|
| 1766 |
+
st.markdown('<h4>π API Health</h4>', unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1767 |
for key, value in api_health.items():
|
| 1768 |
+
display_key = key.replace('_', ' ').title()
|
| 1769 |
+
st.write(f"**{display_key}:** {value}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1770 |
|
| 1771 |
except Exception as e:
|
| 1772 |
st.markdown(f"""
|
|
|
|
| 2180 |
if 'model_version' in cv_results:
|
| 2181 |
st.markdown(f"""
|
| 2182 |
<div class="info-message">
|
| 2183 |
+
**Model:** {cv_results.get('model_version', 'Unknown')} |
|
| 2184 |
+
**Type:** {cv_results.get('model_type', 'Unknown')} |
|
| 2185 |
+
**Trained:** {cv_results.get('training_timestamp', 'Unknown')}
|
| 2186 |
</div>
|
| 2187 |
""", unsafe_allow_html=True)
|
| 2188 |
|
|
|
|
| 2249 |
|
| 2250 |
st.markdown(f"""
|
| 2251 |
<div class="info-message">
|
| 2252 |
+
**Comparison:** {models_compared.get('model1_name', 'Model 1')} vs {models_compared.get('model2_name', 'Model 2')} |
|
| 2253 |
+
**Timestamp:** {comparison_results.get('comparison_timestamp', 'Unknown')}
|
| 2254 |
</div>
|
| 2255 |
""", unsafe_allow_html=True)
|
| 2256 |
|