Spaces:
Build error
Build error
changes made
Browse files- .env +3 -0
- __pycache__/chatbot.cpython-313.pyc +0 -0
- app.py +702 -93
- chatbot.py +180 -0
- gif image.gif +0 -0
- istockphoto-1221348467-612x612.jpg +0 -0
- requirements.txt +3 -0
- samplegif.gif +0 -0
.env
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
SUPABASE_URL=https://qxvpaoeakhddzabctekw.supabase.co
|
| 2 |
+
SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InF4dnBhb2Vha2hkZHphYmN0ZWt3Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDEwNjU2MzEsImV4cCI6MjA1NjY0MTYzMX0.I3GsBjFRfuBKw-KxmSJ7R5iKn2cgGegqIls2Bf32UpI
|
| 3 |
+
|
__pycache__/chatbot.cpython-313.pyc
ADDED
|
Binary file (10.5 kB). View file
|
|
|
app.py
CHANGED
|
@@ -2,175 +2,551 @@ import streamlit as st
|
|
| 2 |
import requests
|
| 3 |
import pandas as pd
|
| 4 |
import plotly.express as px
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
# Backend API URL
|
| 7 |
API_BASE_URL = "https://logeswari-cap-backend.hf.space"
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
def fetch_data(endpoint, params=None):
|
| 10 |
-
"""Fetch data from the FastAPI backend with optional query parameters."""
|
| 11 |
url = f"{API_BASE_URL}{endpoint}"
|
| 12 |
-
|
|
|
|
| 13 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
response = requests.get(url, params=params)
|
| 15 |
response.raise_for_status()
|
| 16 |
data = response.json()
|
| 17 |
|
| 18 |
-
#
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
# Handle single scalar values (like correlation coefficients)
|
| 22 |
-
if isinstance(data, dict) and len(data) == 1 and isinstance(list(data.values())[0], (int, float)):
|
| 23 |
-
return pd.DataFrame([data]) # Convert dictionary to DataFrame
|
| 24 |
|
| 25 |
-
return pd.DataFrame(data)
|
|
|
|
| 26 |
except requests.exceptions.RequestException as e:
|
|
|
|
| 27 |
st.error(f"Error fetching data: {e}")
|
| 28 |
return None
|
| 29 |
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
-
#
|
| 39 |
if page == "π Home":
|
| 40 |
st.title("π Welcome to the HR Analytics Dashboard")
|
| 41 |
-
st.write("Explore different HR metrics and insights.")
|
| 42 |
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
elif page == "π Analytics Dashboard":
|
| 45 |
|
| 46 |
-
#
|
| 47 |
-
|
| 48 |
"Employee Satisfaction", "Department Performance", "Training Analytics",
|
| 49 |
"Engagement-Performance Correlation", "Cost-Benefit Analysis",
|
| 50 |
"Training Effectiveness", "Diversity & Inclusion", "Work-Life Balance Impact",
|
| 51 |
"Career Development Tracking"
|
| 52 |
])
|
| 53 |
|
| 54 |
-
def display_chart(data, chart_type, x_col, y_col, title):
|
| 55 |
-
"""Display different types of charts based on user selection."""
|
| 56 |
-
if data is None or data.empty:
|
| 57 |
-
st.warning(f"No data available for {title}")
|
| 58 |
-
return
|
| 59 |
-
|
| 60 |
-
st.title(title)
|
| 61 |
-
st.dataframe(data) # Show table before visualization
|
| 62 |
-
|
| 63 |
-
if chart_type == "bar":
|
| 64 |
-
fig = px.bar(data, x=x_col, y=y_col, color=y_col, title=title, height=500)
|
| 65 |
-
elif chart_type == "scatter":
|
| 66 |
-
fig = px.scatter(data, x=x_col, y=y_col, color=y_col, title=title, size=y_col, height=500)
|
| 67 |
-
elif chart_type == "line":
|
| 68 |
-
fig = px.line(data, x=x_col, y=y_col, markers=True, title=title, height=500)
|
| 69 |
-
elif chart_type == "pie":
|
| 70 |
-
fig = px.pie(data, names=x_col, values=y_col, title=title)
|
| 71 |
-
elif chart_type == "histogram":
|
| 72 |
-
fig = px.histogram(data, x=x_col, title=title, nbins=10, height=500)
|
| 73 |
-
else:
|
| 74 |
-
st.warning("Invalid chart type")
|
| 75 |
-
return
|
| 76 |
-
|
| 77 |
-
st.plotly_chart(fig, use_container_width=True)
|
| 78 |
-
|
| 79 |
-
|
| 80 |
# β
Employee Satisfaction Analysis
|
| 81 |
-
|
| 82 |
-
department = st.
|
| 83 |
params = {"department": department} if department else None
|
| 84 |
data = fetch_data("/satisfaction-analysis", params)
|
| 85 |
|
| 86 |
if data is not None and not data.empty:
|
| 87 |
st.subheader(f"π Employee Satisfaction in {department if department else 'All Departments'}")
|
| 88 |
-
display_chart(data, "bar", "DepartmentType", "Satisfaction Score", "π Employee Satisfaction by Department")
|
| 89 |
-
else:
|
| 90 |
-
st.warning(f"No data available for the selected department: {department}")
|
| 91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
|
| 93 |
# β
Department Performance Metrics
|
| 94 |
-
|
| 95 |
data = fetch_data("/department-performance")
|
| 96 |
-
display_chart(data, "scatter", "DepartmentType", "Performance Score", "π Departmental Performance Metrics")
|
| 97 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
# β
Training Program Analytics
|
| 100 |
-
|
| 101 |
-
program_name = st.
|
| 102 |
params = {"program_name": program_name} if program_name else None
|
| 103 |
data = fetch_data("/training-analytics", params)
|
| 104 |
|
| 105 |
if data is not None and not data.empty:
|
| 106 |
-
st.
|
| 107 |
-
st.dataframe(data)
|
| 108 |
|
| 109 |
-
|
| 110 |
-
melted_data = data.melt(id_vars="Training Program Name", var_name="Outcome", value_name="Percentage")
|
| 111 |
-
display_chart(melted_data, "bar", "Training Program Name", "Percentage", "π Training Outcomes by Program")
|
| 112 |
-
else:
|
| 113 |
-
st.warning("Training Program Name column missing in data.")
|
| 114 |
|
| 115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
# β
Engagement vs. Performance Correlation
|
| 117 |
-
|
| 118 |
data = fetch_data("/engagement-performance")
|
| 119 |
-
|
| 120 |
if data is not None and not data.empty:
|
| 121 |
-
st.
|
| 122 |
-
|
| 123 |
-
st.
|
| 124 |
|
| 125 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
# β
Cost-Benefit Analysis
|
| 127 |
-
|
| 128 |
data = fetch_data("/cost-benefit-analysis")
|
| 129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
|
| 131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
# β
Training Effectiveness Metrics
|
| 133 |
-
|
| 134 |
data = fetch_data("/training-effectiveness")
|
| 135 |
-
display_chart(data, "line", "Training Program Name", "Performance Score", "π Training Effectiveness")
|
| 136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
# β
Diversity and Inclusion
|
| 139 |
-
|
| 140 |
data = fetch_data("/diversity-inclusion")
|
| 141 |
|
| 142 |
if data is not None and not data.empty:
|
| 143 |
-
st.
|
| 144 |
-
st.dataframe(data)
|
| 145 |
|
| 146 |
-
|
| 147 |
-
melted_data = data.melt(id_vars="DepartmentType", var_name="Gender", value_name="Percentage")
|
| 148 |
|
| 149 |
-
# Bar chart for gender distribution by department
|
| 150 |
-
fig = px.bar(melted_data, x="DepartmentType", y="Percentage", color="Gender", barmode="group",
|
| 151 |
-
title="π Diversity Breakdown by Department", height=500)
|
| 152 |
-
st.plotly_chart(fig, use_container_width=True)
|
| 153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
|
| 155 |
# β
Work-Life Balance Impact
|
| 156 |
-
|
| 157 |
data = fetch_data("/work-life-balance")
|
| 158 |
|
| 159 |
if data is not None and not data.empty:
|
| 160 |
-
st.
|
| 161 |
-
correlation_value = data.iloc[0, 0] if isinstance(data, pd.DataFrame) else data["correlation_coefficient"]
|
| 162 |
-
st.metric(label="Correlation Coefficient", value=f"{correlation_value:.2f}")
|
| 163 |
|
|
|
|
| 164 |
|
| 165 |
-
# β
Career Development Tracking
|
| 166 |
-
if analysis_option == "Career Development Tracking":
|
| 167 |
-
st.title("π Career Development Tracking")
|
| 168 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
all_employees = fetch_data("/career-development")
|
| 170 |
-
|
| 171 |
if all_employees is not None and not all_employees.empty:
|
| 172 |
employee_ids = all_employees["Employee ID"].unique().tolist()
|
| 173 |
-
selected_employee = st.
|
| 174 |
else:
|
| 175 |
selected_employee = None
|
| 176 |
|
|
@@ -178,8 +554,241 @@ elif page == "π Analytics Dashboard":
|
|
| 178 |
data = fetch_data("/career-development", params)
|
| 179 |
|
| 180 |
if data is not None and not data.empty:
|
| 181 |
-
st.
|
| 182 |
-
|
| 183 |
-
st.
|
| 184 |
-
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
import requests
|
| 3 |
import pandas as pd
|
| 4 |
import plotly.express as px
|
| 5 |
+
import time
|
| 6 |
+
from chatbot import main as chatbot_main
|
| 7 |
+
import matplotlib.pyplot as plt
|
| 8 |
+
import plotly.figure_factory as ff
|
| 9 |
+
import base64
|
| 10 |
+
from sklearn.linear_model import LinearRegression, LogisticRegression
|
| 11 |
+
import numpy as np
|
| 12 |
+
from sklearn.preprocessing import LabelEncoder
|
| 13 |
+
import plotly.graph_objects as go
|
| 14 |
+
|
| 15 |
+
encoder = LabelEncoder()
|
| 16 |
+
|
| 17 |
+
# β
Set Page Config at the Top
|
| 18 |
+
st.set_page_config(page_title="HR Analytics Dashboard", layout="wide")
|
| 19 |
|
| 20 |
# Backend API URL
|
| 21 |
API_BASE_URL = "https://logeswari-cap-backend.hf.space"
|
| 22 |
|
| 23 |
+
USERNAME = "admin"
|
| 24 |
+
PASSWORD = "password123"
|
| 25 |
+
|
| 26 |
+
# β
Store Auth State in Session
|
| 27 |
+
if "authenticated" not in st.session_state:
|
| 28 |
+
st.session_state.authenticated = False
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
# ========== Authentication Function ==========
|
| 32 |
+
def authenticate():
|
| 33 |
+
st.title("π Login to HR Analytics Dashboard")
|
| 34 |
+
st.write("Please enter your credentials to continue.")
|
| 35 |
+
|
| 36 |
+
username = st.text_input("Username", value="", key="username")
|
| 37 |
+
password = st.text_input("Password", type="password", value="", key="password")
|
| 38 |
+
|
| 39 |
+
col1, col2 = st.columns([1, 1])
|
| 40 |
+
|
| 41 |
+
with col1:
|
| 42 |
+
if st.button("Login"):
|
| 43 |
+
if username == USERNAME and password == PASSWORD:
|
| 44 |
+
st.session_state.authenticated = True
|
| 45 |
+
st.success("β
Logged in successfully!")
|
| 46 |
+
time.sleep(1)
|
| 47 |
+
st.rerun()
|
| 48 |
+
else:
|
| 49 |
+
st.error("β Invalid username or password")
|
| 50 |
+
|
| 51 |
+
with col2:
|
| 52 |
+
if st.button("Cancel"):
|
| 53 |
+
st.session_state.authenticated = False
|
| 54 |
+
st.experimental_rerun()
|
| 55 |
+
def plot_correlation_heatmap(df):
|
| 56 |
+
st.subheader("π Correlation Heatmap")
|
| 57 |
+
corr = df.corr()
|
| 58 |
+
fig = ff.create_annotated_heatmap(
|
| 59 |
+
z=corr.values,
|
| 60 |
+
x=list(corr.columns),
|
| 61 |
+
y=list(corr.index),
|
| 62 |
+
colorscale='Viridis'
|
| 63 |
+
)
|
| 64 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 65 |
+
|
| 66 |
+
def plot_treemap(df, path, values, title):
|
| 67 |
+
st.subheader(title)
|
| 68 |
+
fig = px.treemap(df, path=path, values=values, title=title, color=values)
|
| 69 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 70 |
+
|
| 71 |
+
def plot_radar_chart(categories, values, title):
|
| 72 |
+
fig = go.Figure()
|
| 73 |
+
fig.add_trace(go.Scatterpolar(r=values, theta=categories, fill='toself', name='Employee'))
|
| 74 |
+
fig.update_layout(polar=dict(radialaxis=dict(visible=True)), title=title)
|
| 75 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 76 |
+
|
| 77 |
+
def get_base64_image(file_path):
|
| 78 |
+
with open(file_path, "rb") as file:
|
| 79 |
+
encoded = base64.b64encode(file.read()).decode("utf-8")
|
| 80 |
+
return f"data:image/gif;base64,{encoded}"
|
| 81 |
+
|
| 82 |
+
human_image_path = "D:\capstone\Data_new\Frontend\cap_frontend\istockphoto-1221348467-612x612.jpg"
|
| 83 |
+
human_base64 = get_base64_image(human_image_path)
|
| 84 |
+
|
| 85 |
+
# β
Add Human Image in Bottom Right (Clickable)
|
| 86 |
+
# In your human image code, change this:
|
| 87 |
+
st.markdown(
|
| 88 |
+
f"""
|
| 89 |
+
<div style="
|
| 90 |
+
position: fixed;
|
| 91 |
+
bottom: 20px;
|
| 92 |
+
right: 20px;
|
| 93 |
+
z-index: 9999;
|
| 94 |
+
text-align: center;
|
| 95 |
+
">
|
| 96 |
+
<a href="?page=HR_Chatbot">
|
| 97 |
+
<img src="{human_base64}" alt="Chatbot" style="
|
| 98 |
+
width: 80px;
|
| 99 |
+
height: 80px;
|
| 100 |
+
border-radius: 50%;
|
| 101 |
+
cursor: pointer;
|
| 102 |
+
border: 3px solid #4CAF50;
|
| 103 |
+
box-shadow: 0px 4px 8px rgba(0,0,0,0.2);
|
| 104 |
+
transition: 0.3s;
|
| 105 |
+
" />
|
| 106 |
+
</a>
|
| 107 |
+
<h4 style="color: #4CAF50; font-size: 14px; margin-top: 5px;">π¬ Chatbot</h4>
|
| 108 |
+
</div>
|
| 109 |
+
""",
|
| 110 |
+
unsafe_allow_html=True
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
# β
Logout Button
|
| 114 |
+
def logout():
|
| 115 |
+
st.session_state.authenticated = False
|
| 116 |
+
st.success("β
Logged out successfully!")
|
| 117 |
+
time.sleep(1)
|
| 118 |
+
st.rerun()
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
# β
Show Login Page if Not Authenticated
|
| 122 |
+
if not st.session_state.authenticated:
|
| 123 |
+
authenticate()
|
| 124 |
+
|
| 125 |
+
else:
|
| 126 |
+
# β
Logout Button at Top Right
|
| 127 |
+
st.markdown(
|
| 128 |
+
"""
|
| 129 |
+
<div style="position: fixed; top: 10px; right: 10px; z-index: 9999;">
|
| 130 |
+
<form action="" method="post">
|
| 131 |
+
<input type="submit" value="πͺ Logout" style="
|
| 132 |
+
background-color: red;
|
| 133 |
+
color: white;
|
| 134 |
+
border: none;
|
| 135 |
+
padding: 8px 16px;
|
| 136 |
+
border-radius: 4px;
|
| 137 |
+
cursor: pointer;
|
| 138 |
+
" onclick="fetch('/_logout', {method: 'POST'})">
|
| 139 |
+
</form>
|
| 140 |
+
</div>
|
| 141 |
+
""",
|
| 142 |
+
unsafe_allow_html=True
|
| 143 |
+
)
|
| 144 |
+
|
| 145 |
+
# ========== Fetch Data Function ==========
|
| 146 |
+
def fetch_data(endpoint, params=None):
|
| 147 |
+
url = f"{API_BASE_URL}{endpoint}"
|
| 148 |
+
placeholder = st.empty()
|
| 149 |
+
|
| 150 |
+
try:
|
| 151 |
+
# β
Show Loading GIF
|
| 152 |
+
with placeholder.container():
|
| 153 |
+
st.write("β³ Loading data...")
|
| 154 |
+
time.sleep(2) # Simulate loading delay
|
| 155 |
+
|
| 156 |
+
response = requests.get(url, params=params)
|
| 157 |
+
response.raise_for_status()
|
| 158 |
+
data = response.json()
|
| 159 |
+
|
| 160 |
+
placeholder.empty()
|
| 161 |
+
|
| 162 |
+
return pd.DataFrame(data) if isinstance(data, list) else pd.DataFrame([data])
|
| 163 |
+
except requests.exceptions.RequestException as e:
|
| 164 |
+
placeholder.empty()
|
| 165 |
+
st.error(f"Error fetching data: {e}")
|
| 166 |
+
return None
|
| 167 |
+
|
| 168 |
+
# ========== Prediction Request Function ==========
|
| 169 |
+
def send_prediction_request(endpoint, payload):
|
| 170 |
+
placeholder = st.empty()
|
| 171 |
+
|
| 172 |
+
try:
|
| 173 |
+
with placeholder.container():
|
| 174 |
+
st.write("β³ Processing...")
|
| 175 |
+
time.sleep(2) # Simulate loading delay
|
| 176 |
+
|
| 177 |
+
url = f"{API_BASE_URL}{endpoint}"
|
| 178 |
+
response = requests.post(url, json=payload)
|
| 179 |
+
placeholder.empty()
|
| 180 |
+
|
| 181 |
+
if response.status_code == 200:
|
| 182 |
+
return response.json()
|
| 183 |
+
else:
|
| 184 |
+
st.error(f"Error: {response.json().get('detail', 'Unknown error')}")
|
| 185 |
+
return None
|
| 186 |
+
except requests.exceptions.RequestException as e:
|
| 187 |
+
placeholder.empty()
|
| 188 |
+
st.error(f"Request error: {e}")
|
| 189 |
+
return None
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
# Convert the local GIF to base64
|
| 195 |
+
def get_base64_image(file_path):
|
| 196 |
+
with open(file_path, "rb") as file:
|
| 197 |
+
encoded = base64.b64encode(file.read()).decode("utf-8")
|
| 198 |
+
return f"data:image/gif;base64,{encoded}"
|
| 199 |
+
|
| 200 |
+
# β
Load Human Image as Base64
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
# Path to local brain GIF file
|
| 205 |
+
gif_base64_dashboard = get_base64_image("D:/capstone/Data_new/Frontend/cap_frontend/samplegif.gif")
|
| 206 |
+
gif_base64_prediction = get_base64_image("D:/capstone/Data_new/Frontend/cap_frontend/samplegif.gif")
|
| 207 |
+
def display_chart(data, chart_type, x_col, y_col, title):
|
| 208 |
+
"""Display different types of charts based on user selection."""
|
| 209 |
+
if data is None or data.empty:
|
| 210 |
+
st.warning(f"No data available for {title}")
|
| 211 |
+
return
|
| 212 |
+
|
| 213 |
+
st.title(title)
|
| 214 |
+
|
| 215 |
+
if chart_type == "bar":
|
| 216 |
+
fig = px.bar(data, x=x_col, y=y_col, color=y_col, title=title, height=500)
|
| 217 |
+
elif chart_type == "scatter":
|
| 218 |
+
fig = px.scatter(data, x=x_col, y=y_col, color=y_col, title=title, size=y_col, height=500)
|
| 219 |
+
elif chart_type == "line":
|
| 220 |
+
fig = px.line(data, x=x_col, y=y_col, markers=True, title=title, height=500)
|
| 221 |
+
elif chart_type == "pie":
|
| 222 |
+
fig = px.pie(data, names=x_col, values=y_col, title=title)
|
| 223 |
+
elif chart_type == "histogram":
|
| 224 |
+
fig = px.histogram(data, x=x_col, title=title, nbins=10, height=500)
|
| 225 |
+
elif chart_type == "bubble":
|
| 226 |
+
if y_col in data.columns:
|
| 227 |
+
fig = px.scatter(data, x=x_col, y=y_col, size=y_col, color=y_col, hover_name=x_col, size_max=60, title=title)
|
| 228 |
+
else:
|
| 229 |
+
st.warning(f"{y_col} not found in data.")
|
| 230 |
+
return
|
| 231 |
+
elif chart_type == "treemap":
|
| 232 |
+
if x_col in data.columns and y_col in data.columns:
|
| 233 |
+
fig = px.treemap(data, path=[x_col], values=y_col, title=title)
|
| 234 |
+
else:
|
| 235 |
+
st.warning(f"{x_col} or {y_col} not found in data.")
|
| 236 |
+
return
|
| 237 |
+
else:
|
| 238 |
+
st.warning("Invalid chart type")
|
| 239 |
+
return
|
| 240 |
+
|
| 241 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 242 |
+
|
| 243 |
+
# ========== Fetch Data Function ==========
|
| 244 |
def fetch_data(endpoint, params=None):
|
|
|
|
| 245 |
url = f"{API_BASE_URL}{endpoint}"
|
| 246 |
+
placeholder = st.empty()
|
| 247 |
+
|
| 248 |
try:
|
| 249 |
+
# β
Show dashboard loading GIF
|
| 250 |
+
with placeholder.container():
|
| 251 |
+
st.markdown(
|
| 252 |
+
f"""
|
| 253 |
+
<div style="position: fixed;
|
| 254 |
+
top: 0; left: 100px;
|
| 255 |
+
width: 100%; height: 100%;
|
| 256 |
+
display: flex;
|
| 257 |
+
justify-content: center;
|
| 258 |
+
align-items: center;
|
| 259 |
+
background-color: rgba(0, 0, 0, 0.5);
|
| 260 |
+
z-index: 9999;">
|
| 261 |
+
<img src="{gif_base64_dashboard}" alt="Loading..." width="120" />
|
| 262 |
+
</div>
|
| 263 |
+
""",
|
| 264 |
+
unsafe_allow_html=True
|
| 265 |
+
)
|
| 266 |
+
time.sleep(2) # Simulate loading delay
|
| 267 |
+
|
| 268 |
response = requests.get(url, params=params)
|
| 269 |
response.raise_for_status()
|
| 270 |
data = response.json()
|
| 271 |
|
| 272 |
+
# β
Remove GIF after fetching
|
| 273 |
+
placeholder.empty()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
|
| 275 |
+
return pd.DataFrame(data) if isinstance(data, list) else pd.DataFrame([data])
|
| 276 |
+
|
| 277 |
except requests.exceptions.RequestException as e:
|
| 278 |
+
placeholder.empty()
|
| 279 |
st.error(f"Error fetching data: {e}")
|
| 280 |
return None
|
| 281 |
|
| 282 |
+
# ========== Prediction Request Function ==========
|
| 283 |
+
def send_prediction_request(endpoint, payload):
|
| 284 |
+
placeholder = st.empty()
|
| 285 |
|
| 286 |
+
try:
|
| 287 |
+
with placeholder.container():
|
| 288 |
+
# β
Show prediction-specific loading GIF
|
| 289 |
+
st.markdown(
|
| 290 |
+
f"""
|
| 291 |
+
<div style="position: fixed;
|
| 292 |
+
top: 0; left: 100px;
|
| 293 |
+
width: 100%; height: 100%;
|
| 294 |
+
display: flex;
|
| 295 |
+
justify-content: center;
|
| 296 |
+
align-items: center;
|
| 297 |
+
background-color: rgba(0, 0, 0, 0.5);
|
| 298 |
+
z-index: 9999;">
|
| 299 |
+
<img src="{gif_base64_prediction}" alt="Processing..." width="120" />
|
| 300 |
+
</div>
|
| 301 |
+
""",
|
| 302 |
+
unsafe_allow_html=True
|
| 303 |
+
)
|
| 304 |
+
time.sleep(4) # Simulate processing delay
|
| 305 |
+
|
| 306 |
+
url = f"{API_BASE_URL}{endpoint}"
|
| 307 |
+
response = requests.post(url, json=payload)
|
| 308 |
+
|
| 309 |
+
# β
Remove GIF after processing
|
| 310 |
+
placeholder.empty()
|
| 311 |
|
| 312 |
+
if response.status_code == 200:
|
| 313 |
+
return response.json()
|
| 314 |
+
else:
|
| 315 |
+
st.error(f"Error: {response.json().get('detail', 'Unknown error')}")
|
| 316 |
+
return None
|
| 317 |
+
|
| 318 |
+
except requests.exceptions.RequestException as e:
|
| 319 |
+
placeholder.empty()
|
| 320 |
+
st.error(f"Request error: {e}")
|
| 321 |
+
return None
|
| 322 |
+
|
| 323 |
+
# ========== Set Up Streamlit Layout ==========
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
# ========== Sidebar ==========
|
| 327 |
+
import base64
|
| 328 |
+
|
| 329 |
+
def get_base64_image(file_path):
|
| 330 |
+
with open(file_path, "rb") as file:
|
| 331 |
+
encoded = base64.b64encode(file.read()).decode("utf-8")
|
| 332 |
+
return f"data:image/gif;base64,{encoded}"
|
| 333 |
+
|
| 334 |
+
# Load GIF as base64
|
| 335 |
+
gif_base64_sidebar = get_base64_image("D:/capstone/Data_new/Frontend/cap_frontend/gif image.gif")
|
| 336 |
+
|
| 337 |
+
# Embed GIF using HTML
|
| 338 |
+
st.sidebar.markdown(
|
| 339 |
+
f"""
|
| 340 |
+
<div style="text-align: center;">
|
| 341 |
+
<img src="{gif_base64_sidebar}" alt="Loading..." style="width: 100%; max-width: 500px;height:220px" />
|
| 342 |
+
</div>
|
| 343 |
+
""",
|
| 344 |
+
unsafe_allow_html=True
|
| 345 |
+
)
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
if st.query_params.get("page") == "HR_Chatbot":
|
| 349 |
+
page = "π€ HR Chatbot"
|
| 350 |
+
else:
|
| 351 |
+
# Your existing page selection code
|
| 352 |
+
page = st.sidebar.selectbox("Select Page", [
|
| 353 |
+
"π Home",
|
| 354 |
+
"π Analytics Dashboard",
|
| 355 |
+
"π§ AI Predictions",
|
| 356 |
+
"π€ HR Chatbot"
|
| 357 |
+
])
|
| 358 |
|
| 359 |
+
# ========== Home Page ==========
|
| 360 |
if page == "π Home":
|
| 361 |
st.title("π Welcome to the HR Analytics Dashboard")
|
|
|
|
| 362 |
|
| 363 |
+
st.markdown(
|
| 364 |
+
"""
|
| 365 |
+
### π About the Platform
|
| 366 |
+
This platform leverages employee data to provide actionable insights on satisfaction, performance, training effectiveness, and more.
|
| 367 |
+
Built using **FastAPI** and **Streamlit**, it enables you to explore trends, identify improvement areas, and forecast future performance.
|
| 368 |
+
|
| 369 |
+
### π Key Features
|
| 370 |
+
- β
**Employee Satisfaction Analysis** β Track satisfaction scores and identify key drivers.
|
| 371 |
+
- β
**Departmental Performance Metrics** β Compare and track performance across departments.
|
| 372 |
+
- β
**Training Program Analytics** β Measure training effectiveness and ROI.
|
| 373 |
+
- β
**Engagement-Performance Correlation** β Analyze how engagement impacts performance.
|
| 374 |
+
- β
**Cost-Benefit Analysis** β Measure ROI of training programs and performance improvements.
|
| 375 |
+
- β
**Training Effectiveness Metrics** β Assess training program success rates.
|
| 376 |
+
- β
**Diversity and Inclusion Dashboard** β Monitor workforce diversity and inclusion metrics.
|
| 377 |
+
- β
**Work-Life Balance Impact Study** β Explore how work-life balance influences performance.
|
| 378 |
+
- β
**Career Development Tracking** β Monitor employee progression and promotion trends.
|
| 379 |
+
|
| 380 |
+
### π€ AI-Powered Insights
|
| 381 |
+
- **Satisfaction Prediction** β Predict employee satisfaction using engagement and performance data.
|
| 382 |
+
- **Performance Forecasting** β Forecast employee performance based on historical data.
|
| 383 |
+
- **Employee Retention Risk** β Identify employees at risk of leaving the organization.
|
| 384 |
+
- **Training Success Prediction** β Estimate training completion rates and success.
|
| 385 |
+
|
| 386 |
+
### π How to Use the Dashboard
|
| 387 |
+
1. **Select the type of analysis** from the sidebar.
|
| 388 |
+
2. View results in both **graph and table format**.
|
| 389 |
+
3. Filter data by **department, date, or employee type**.
|
| 390 |
+
4. Export insights for further analysis.
|
| 391 |
+
|
| 392 |
+
### π Secure Data Handling
|
| 393 |
+
All data is securely processed and protected using industry-standard encryption and authentication methods.
|
| 394 |
+
"""
|
| 395 |
+
)
|
| 396 |
+
|
| 397 |
+
|
| 398 |
+
# ========== Analytics Dashboard ==========
|
| 399 |
elif page == "π Analytics Dashboard":
|
| 400 |
|
| 401 |
+
# β
Create Tabs Instead of Sidebar Dropdown
|
| 402 |
+
tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8, tab9 = st.tabs([
|
| 403 |
"Employee Satisfaction", "Department Performance", "Training Analytics",
|
| 404 |
"Engagement-Performance Correlation", "Cost-Benefit Analysis",
|
| 405 |
"Training Effectiveness", "Diversity & Inclusion", "Work-Life Balance Impact",
|
| 406 |
"Career Development Tracking"
|
| 407 |
])
|
| 408 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
# β
Employee Satisfaction Analysis
|
| 410 |
+
with tab1:
|
| 411 |
+
department = st.text_input("Enter Department (optional):")
|
| 412 |
params = {"department": department} if department else None
|
| 413 |
data = fetch_data("/satisfaction-analysis", params)
|
| 414 |
|
| 415 |
if data is not None and not data.empty:
|
| 416 |
st.subheader(f"π Employee Satisfaction in {department if department else 'All Departments'}")
|
|
|
|
|
|
|
|
|
|
| 417 |
|
| 418 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="satisfaction_view")
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
if view_option == "Graph View":
|
| 422 |
+
display_chart(data, "bar", "DepartmentType", "Satisfaction Score", "π Employee Satisfaction by Department")
|
| 423 |
+
|
| 424 |
+
else:
|
| 425 |
+
st.dataframe(data)
|
| 426 |
|
| 427 |
# β
Department Performance Metrics
|
| 428 |
+
with tab2:
|
| 429 |
data = fetch_data("/department-performance")
|
|
|
|
| 430 |
|
| 431 |
+
if data is not None and not data.empty:
|
| 432 |
+
st.subheader("π Departmental Performance Metrics")
|
| 433 |
+
|
| 434 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="performance_view")
|
| 435 |
+
|
| 436 |
+
|
| 437 |
+
if view_option == "Graph View":
|
| 438 |
+
display_chart(data, "scatter", "DepartmentType", "Performance Score", "π Departmental Performance Metrics")
|
| 439 |
+
else:
|
| 440 |
+
st.dataframe(data)
|
| 441 |
|
| 442 |
# β
Training Program Analytics
|
| 443 |
+
with tab3:
|
| 444 |
+
program_name = st.text_input("Enter Training Program Name (optional):")
|
| 445 |
params = {"program_name": program_name} if program_name else None
|
| 446 |
data = fetch_data("/training-analytics", params)
|
| 447 |
|
| 448 |
if data is not None and not data.empty:
|
| 449 |
+
st.subheader("π Training Program Analytics")
|
|
|
|
| 450 |
|
| 451 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="training_view")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 452 |
|
| 453 |
|
| 454 |
+
if view_option == "Graph View":
|
| 455 |
+
if "Training Program Name" in data.columns:
|
| 456 |
+
melted_data = data.melt(id_vars="Training Program Name", var_name="Outcome", value_name="Percentage")
|
| 457 |
+
display_chart(melted_data, "bubble", "Training Program Name", "Percentage", "π Training Outcomes by Program")
|
| 458 |
+
else:
|
| 459 |
+
st.warning("Training Program Name column missing in data.")
|
| 460 |
+
else:
|
| 461 |
+
st.dataframe(data)
|
| 462 |
+
|
| 463 |
# β
Engagement vs. Performance Correlation
|
| 464 |
+
with tab4:
|
| 465 |
data = fetch_data("/engagement-performance")
|
| 466 |
+
|
| 467 |
if data is not None and not data.empty:
|
| 468 |
+
st.subheader("π Engagement vs. Performance Correlation")
|
| 469 |
+
|
| 470 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="engagement_view")
|
| 471 |
|
| 472 |
|
| 473 |
+
correlation_value = data.iloc[0, 0]
|
| 474 |
+
if view_option == "Graph View":
|
| 475 |
+
st.metric(label="Correlation Coefficient", value=f"{correlation_value:.2f}")
|
| 476 |
+
else:
|
| 477 |
+
st.write(f"Correlation Coefficient: **{correlation_value:.2f}**")
|
| 478 |
+
|
| 479 |
# β
Cost-Benefit Analysis
|
| 480 |
+
with tab5:
|
| 481 |
data = fetch_data("/cost-benefit-analysis")
|
| 482 |
+
|
| 483 |
+
if data is not None and not data.empty:
|
| 484 |
+
st.subheader("π Cost-Benefit Analysis")
|
| 485 |
+
|
| 486 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="cost_benefit_view")
|
| 487 |
|
| 488 |
|
| 489 |
+
if view_option == "Graph View":
|
| 490 |
+
display_chart(data, "pie", "DepartmentType", "ROI", "π Cost-Benefit Analysis")
|
| 491 |
+
else:
|
| 492 |
+
st.dataframe(data)
|
| 493 |
+
|
| 494 |
# β
Training Effectiveness Metrics
|
| 495 |
+
with tab6:
|
| 496 |
data = fetch_data("/training-effectiveness")
|
|
|
|
| 497 |
|
| 498 |
+
if data is not None and not data.empty:
|
| 499 |
+
st.subheader("π Training Effectiveness")
|
| 500 |
+
|
| 501 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="effectiveness_view")
|
| 502 |
+
|
| 503 |
+
|
| 504 |
+
if view_option == "Graph View":
|
| 505 |
+
display_chart(data, "line", "Training Program Name", "Performance Score", "π Training Effectiveness")
|
| 506 |
+
else:
|
| 507 |
+
st.dataframe(data)
|
| 508 |
|
| 509 |
# β
Diversity and Inclusion
|
| 510 |
+
with tab7:
|
| 511 |
data = fetch_data("/diversity-inclusion")
|
| 512 |
|
| 513 |
if data is not None and not data.empty:
|
| 514 |
+
st.subheader("π Diversity and Inclusion Dashboard")
|
|
|
|
| 515 |
|
| 516 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="diversity_view")
|
|
|
|
| 517 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 518 |
|
| 519 |
+
if view_option == "Graph View":
|
| 520 |
+
melted_data = data.melt(id_vars="DepartmentType", var_name="Gender", value_name="Percentage")
|
| 521 |
+
fig = px.bar(melted_data, x="DepartmentType", y="Percentage", color="Gender", barmode="group",
|
| 522 |
+
title="π Diversity Breakdown by Department", height=500)
|
| 523 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 524 |
+
else:
|
| 525 |
+
st.dataframe(data)
|
| 526 |
|
| 527 |
# β
Work-Life Balance Impact
|
| 528 |
+
with tab8:
|
| 529 |
data = fetch_data("/work-life-balance")
|
| 530 |
|
| 531 |
if data is not None and not data.empty:
|
| 532 |
+
st.subheader("π Work-Life Balance vs. Performance Correlation")
|
|
|
|
|
|
|
| 533 |
|
| 534 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="work_life_view")
|
| 535 |
|
|
|
|
|
|
|
|
|
|
| 536 |
|
| 537 |
+
correlation_value = data.iloc[0, 0] if isinstance(data, pd.DataFrame) else data["correlation_coefficient"]
|
| 538 |
+
if view_option == "Graph View":
|
| 539 |
+
st.metric(label="Correlation Coefficient", value=f"{correlation_value:.2f}")
|
| 540 |
+
else:
|
| 541 |
+
st.write(f"Correlation Coefficient: **{correlation_value:.2f}**")
|
| 542 |
+
|
| 543 |
+
# β
Career Development Tracking
|
| 544 |
+
with tab9:
|
| 545 |
all_employees = fetch_data("/career-development")
|
| 546 |
+
|
| 547 |
if all_employees is not None and not all_employees.empty:
|
| 548 |
employee_ids = all_employees["Employee ID"].unique().tolist()
|
| 549 |
+
selected_employee = st.selectbox("Select Employee ID:", [""] + employee_ids)
|
| 550 |
else:
|
| 551 |
selected_employee = None
|
| 552 |
|
|
|
|
| 554 |
data = fetch_data("/career-development", params)
|
| 555 |
|
| 556 |
if data is not None and not data.empty:
|
| 557 |
+
st.subheader("π Career Development Tracking")
|
| 558 |
+
|
| 559 |
+
view_option = st.radio("Select View:", ["Graph View", "Table View"], index=0, key="career_development_view")
|
| 560 |
+
|
| 561 |
+
|
| 562 |
+
if view_option == "Graph View":
|
| 563 |
+
fig = px.histogram(data, x="Career Movements", title="π Career Development Histogram", nbins=10, height=500)
|
| 564 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 565 |
+
else:
|
| 566 |
+
st.dataframe(data)
|
| 567 |
+
|
| 568 |
+
|
| 569 |
+
# ========== AI-Based Prediction ==========
|
| 570 |
+
elif page == "π§ AI Predictions":
|
| 571 |
+
st.title("π§ AI-Based Employee Success Predictions")
|
| 572 |
+
prediction_type = st.sidebar.selectbox("Select Prediction Type", [
|
| 573 |
+
"Satisfaction Prediction",
|
| 574 |
+
"Performance Forecasting",
|
| 575 |
+
"Employee Retention Risk",
|
| 576 |
+
"Training Success Prediction"
|
| 577 |
+
])
|
| 578 |
+
|
| 579 |
+
# β
Satisfaction Prediction
|
| 580 |
+
if prediction_type == "Satisfaction Prediction":
|
| 581 |
+
st.subheader("π― Predict Employee Satisfaction")
|
| 582 |
+
engagement_score = st.number_input("Engagement Score", min_value=0, max_value=100, value=50)
|
| 583 |
+
work_life_balance_score = st.number_input("Work-Life Balance Score", min_value=0, max_value=100, value=50)
|
| 584 |
+
performance_score = st.number_input("Performance Score", min_value=0, max_value=100, value=50)
|
| 585 |
+
|
| 586 |
+
if st.button("Predict Satisfaction"):
|
| 587 |
+
payload = {
|
| 588 |
+
"engagement_score": engagement_score,
|
| 589 |
+
"work_life_balance_score": work_life_balance_score,
|
| 590 |
+
"performance_score": performance_score
|
| 591 |
+
}
|
| 592 |
+
result = send_prediction_request("/predict/satisfaction", payload)
|
| 593 |
+
if result:
|
| 594 |
+
satisfaction_score = result['satisfaction_score']
|
| 595 |
+
st.success(f"β
Predicted Satisfaction Score: {satisfaction_score:.2f}")
|
| 596 |
+
|
| 597 |
+
# Add visualization for satisfaction score
|
| 598 |
+
fig = plt.figure(figsize=(10, 4))
|
| 599 |
+
|
| 600 |
+
# Create gauge chart for satisfaction score
|
| 601 |
+
ax = fig.add_subplot(121)
|
| 602 |
+
gauge_colors = [(0.8, 0.0, 0.0, 0.8), (1.0, 0.9, 0.0, 0.8), (0.0, 0.8, 0.0, 0.8)]
|
| 603 |
+
gauge = plt.cm.RdYlGn(satisfaction_score/100)
|
| 604 |
+
wedges, texts = ax.pie([satisfaction_score, 100-satisfaction_score],
|
| 605 |
+
wedgeprops=dict(width=0.3, edgecolor='w'),
|
| 606 |
+
startangle=90, colors=[gauge, (0.9, 0.9, 0.9, 0.4)])
|
| 607 |
+
ax.text(0, 0, f"{satisfaction_score:.1f}%", ha='center', va='center', fontsize=24)
|
| 608 |
+
ax.set_title("Satisfaction Score")
|
| 609 |
+
|
| 610 |
+
# Create bar chart for factors
|
| 611 |
+
ax2 = fig.add_subplot(122)
|
| 612 |
+
factors = ['Engagement', 'Work-Life Balance', 'Performance']
|
| 613 |
+
values = [engagement_score, work_life_balance_score, performance_score]
|
| 614 |
+
colors = [plt.cm.RdYlGn(v/100) for v in values]
|
| 615 |
+
ax2.bar(factors, values, color=colors)
|
| 616 |
+
ax2.set_ylim(0, 100)
|
| 617 |
+
ax2.set_title("Contributing Factors")
|
| 618 |
+
ax2.set_ylabel("Score")
|
| 619 |
+
|
| 620 |
+
plt.tight_layout()
|
| 621 |
+
st.pyplot(fig)
|
| 622 |
+
|
| 623 |
+
# β
Performance Forecasting
|
| 624 |
+
elif prediction_type == "Performance Forecasting":
|
| 625 |
+
st.subheader("π Predict Employee Performance")
|
| 626 |
+
satisfaction_score = st.number_input("Satisfaction Score", min_value=0, max_value=100, value=50)
|
| 627 |
+
engagement_score = st.number_input("Engagement Score", min_value=0, max_value=100, value=50)
|
| 628 |
+
training_duration = st.number_input("Training Duration (Days)", min_value=1, value=30)
|
| 629 |
+
training_cost = st.number_input("Training Cost", min_value=0.0, value=1000.0)
|
| 630 |
+
|
| 631 |
+
if st.button("Predict Performance"):
|
| 632 |
+
payload = {
|
| 633 |
+
"satisfaction_score": satisfaction_score,
|
| 634 |
+
"engagement_score": engagement_score,
|
| 635 |
+
"training_duration": training_duration,
|
| 636 |
+
"training_cost": training_cost
|
| 637 |
+
}
|
| 638 |
+
result = send_prediction_request("/predict/performance", payload)
|
| 639 |
+
if result:
|
| 640 |
+
performance_score = result['performance_score']
|
| 641 |
+
st.success(f"β
Predicted Performance Score: {performance_score:.2f}")
|
| 642 |
+
|
| 643 |
+
# Add visualization for performance score
|
| 644 |
+
fig = plt.figure(figsize=(10, 4))
|
| 645 |
+
|
| 646 |
+
# Create gauge chart for performance score
|
| 647 |
+
ax = fig.add_subplot(121)
|
| 648 |
+
gauge = plt.cm.RdYlGn(performance_score/100)
|
| 649 |
+
wedges, texts = ax.pie([performance_score, 100-performance_score],
|
| 650 |
+
wedgeprops=dict(width=0.3, edgecolor='w'),
|
| 651 |
+
startangle=90, colors=[gauge, (0.9, 0.9, 0.9, 0.4)])
|
| 652 |
+
ax.text(0, 0, f"{performance_score:.1f}%", ha='center', va='center', fontsize=24)
|
| 653 |
+
ax.set_title("Performance Score")
|
| 654 |
+
|
| 655 |
+
# Create spider chart for factors
|
| 656 |
+
ax2 = fig.add_subplot(122, polar=True)
|
| 657 |
+
factors = ['Satisfaction', 'Engagement', 'Training\nDuration', 'Training\nCost']
|
| 658 |
+
# Normalize values to 0-1 scale
|
| 659 |
+
norm_training_duration = min(training_duration / 60, 1) # Assuming 60 days is max
|
| 660 |
+
norm_training_cost = min(training_cost / 5000, 1) # Assuming $5000 is max
|
| 661 |
+
values = [satisfaction_score/100, engagement_score/100, norm_training_duration, norm_training_cost]
|
| 662 |
+
|
| 663 |
+
angles = np.linspace(0, 2*np.pi, len(factors), endpoint=False).tolist()
|
| 664 |
+
values = values + [values[0]] # Close the loop
|
| 665 |
+
angles = angles + [angles[0]] # Close the loop
|
| 666 |
+
factors = factors + [factors[0]] # Close the loop
|
| 667 |
+
|
| 668 |
+
ax2.plot(angles, values, 'o-', linewidth=2, color='blue')
|
| 669 |
+
ax2.fill(angles, values, alpha=0.25, color='blue')
|
| 670 |
+
ax2.set_thetagrids(np.degrees(angles[:-1]), factors[:-1])
|
| 671 |
+
ax2.set_ylim(0, 1)
|
| 672 |
+
ax2.set_title("Contributing Factors")
|
| 673 |
+
|
| 674 |
+
plt.tight_layout()
|
| 675 |
+
st.pyplot(fig)
|
| 676 |
+
|
| 677 |
+
# β
Retention Risk Prediction
|
| 678 |
+
elif prediction_type == "Employee Retention Risk":
|
| 679 |
+
st.subheader("π¨ Predict Employee Retention Risk")
|
| 680 |
+
satisfaction_score = st.number_input("Satisfaction Score", min_value=0, max_value=100, value=50)
|
| 681 |
+
engagement_score = st.number_input("Engagement Score", min_value=0, max_value=100, value=50)
|
| 682 |
+
performance_score = st.number_input("Performance Score", min_value=0, max_value=100, value=50)
|
| 683 |
+
|
| 684 |
+
if st.button("Predict Retention Risk"):
|
| 685 |
+
payload = {
|
| 686 |
+
"satisfaction_score": satisfaction_score,
|
| 687 |
+
"engagement_score": engagement_score,
|
| 688 |
+
"performance_score": performance_score
|
| 689 |
+
}
|
| 690 |
+
result = send_prediction_request("/predict/retention", payload)
|
| 691 |
+
if result:
|
| 692 |
+
retention_risk = result['retention_risk']
|
| 693 |
+
st.success(f"β
Predicted Retention Risk: {retention_risk}")
|
| 694 |
+
|
| 695 |
+
# Convert text-based risk to numeric for visualization
|
| 696 |
+
risk_mapping = {"Low": 25, "Medium": 50, "High": 75, "Very High": 95}
|
| 697 |
+
risk_value = risk_mapping.get(retention_risk, 50)
|
| 698 |
+
|
| 699 |
+
# Add visualization for retention risk
|
| 700 |
+
fig = plt.figure(figsize=(10, 4))
|
| 701 |
+
|
| 702 |
+
# Create gauge chart for retention risk
|
| 703 |
+
ax = fig.add_subplot(121)
|
| 704 |
+
gauge = plt.cm.RdYlGn_r(risk_value/100) # Reversed colormap for risk
|
| 705 |
+
wedges, texts = ax.pie([risk_value, 100-risk_value],
|
| 706 |
+
wedgeprops=dict(width=0.3, edgecolor='w'),
|
| 707 |
+
startangle=90, colors=[gauge, (0.9, 0.9, 0.9, 0.4)])
|
| 708 |
+
ax.text(0, 0, f"{retention_risk}", ha='center', va='center', fontsize=20)
|
| 709 |
+
ax.set_title("Retention Risk")
|
| 710 |
+
|
| 711 |
+
# Create horizontal bar chart for factors
|
| 712 |
+
ax2 = fig.add_subplot(122)
|
| 713 |
+
factors = ['Satisfaction', 'Engagement', 'Performance']
|
| 714 |
+
values = [satisfaction_score, engagement_score, performance_score]
|
| 715 |
+
colors = [plt.cm.RdYlGn(v/100) for v in values]
|
| 716 |
+
ax2.barh(factors, values, color=colors)
|
| 717 |
+
ax2.set_xlim(0, 100)
|
| 718 |
+
ax2.set_title("Employee Metrics")
|
| 719 |
+
ax2.set_xlabel("Score")
|
| 720 |
+
|
| 721 |
+
plt.tight_layout()
|
| 722 |
+
st.pyplot(fig)
|
| 723 |
+
|
| 724 |
+
# β
Training Success Prediction
|
| 725 |
+
elif prediction_type == "Training Success Prediction":
|
| 726 |
+
st.subheader("π Predict Training Success")
|
| 727 |
+
training_type = st.number_input("Training Type (0 = Internal, 1 = External)", min_value=0, max_value=1, value=0, key="training_type_input")
|
| 728 |
+
training_duration = st.number_input("Training Duration (Days)", min_value=1, value=30, key="training_duration_success_input")
|
| 729 |
+
training_cost = st.number_input("Training Cost", min_value=0.0, value=1000.0, key="training_cost_success_input")
|
| 730 |
+
|
| 731 |
+
if st.button("Predict Training Success", key="predict_training_success"):
|
| 732 |
+
model = LogisticRegression()
|
| 733 |
+
X = np.array([[0, 30, 1000], [1, 45, 2000], [0, 60, 3000]])
|
| 734 |
+
y = np.array([1, 0, 1])
|
| 735 |
+
y_encoded = encoder.fit_transform(y)
|
| 736 |
+
|
| 737 |
+
model.fit(X, y_encoded)
|
| 738 |
+
|
| 739 |
+
input_data = np.array([[training_type, training_duration, training_cost]])
|
| 740 |
+
training_success = model.predict(input_data)[0]
|
| 741 |
+
success_status = encoder.inverse_transform([training_success])[0]
|
| 742 |
+
st.success(f"β
Predicted Training Success: {success_status}")
|
| 743 |
+
|
| 744 |
+
# Add visualization for training success prediction
|
| 745 |
+
fig = plt.figure(figsize=(10, 4))
|
| 746 |
+
|
| 747 |
+
# Create visual indicator for success/failure
|
| 748 |
+
ax = fig.add_subplot(121)
|
| 749 |
+
success_color = 'green' if success_status == 1 else 'red'
|
| 750 |
+
success_label = 'Success' if success_status == 1 else 'Failure'
|
| 751 |
+
ax.pie([1], colors=[success_color], wedgeprops=dict(width=0.3, edgecolor='w'))
|
| 752 |
+
ax.text(0, 0, success_label, ha='center', va='center', fontsize=20, color='black')
|
| 753 |
+
ax.set_title("Predicted Outcome")
|
| 754 |
+
|
| 755 |
+
# Create feature importance visualization
|
| 756 |
+
ax2 = fig.add_subplot(122)
|
| 757 |
+
|
| 758 |
+
# Convert categorical training type to label
|
| 759 |
+
training_type_label = "External" if training_type == 1 else "Internal"
|
| 760 |
+
|
| 761 |
+
# Show the input features with scaled representation
|
| 762 |
+
features = ['Training Type', 'Duration (Days)', 'Cost ($)']
|
| 763 |
+
values = [training_type, min(training_duration/60, 1)*100, min(training_cost/5000, 1)*100]
|
| 764 |
+
|
| 765 |
+
# Create horizontal bars with custom colors
|
| 766 |
+
colors = ['#3498db', '#f39c12', '#2ecc71']
|
| 767 |
+
bars = ax2.barh(features, values, color=colors)
|
| 768 |
+
|
| 769 |
+
# Add text annotations for the actual values
|
| 770 |
+
ax2.text(values[0] + 5, 0, training_type_label)
|
| 771 |
+
ax2.text(values[1] + 5, 1, f"{training_duration} days")
|
| 772 |
+
ax2.text(values[2] + 5, 2, f"${training_cost:.2f}")
|
| 773 |
+
|
| 774 |
+
ax2.set_title("Training Parameters")
|
| 775 |
+
ax2.set_xlim(0, 100)
|
| 776 |
+
|
| 777 |
+
plt.tight_layout()
|
| 778 |
+
st.pyplot(fig)
|
| 779 |
+
|
| 780 |
+
# Add a simple recommendation based on the prediction
|
| 781 |
+
st.subheader("Recommendation")
|
| 782 |
+
if success_status == 1:
|
| 783 |
+
st.info("β
This training program is likely to be successful. Consider implementing it.")
|
| 784 |
+
else:
|
| 785 |
+
st.warning("β οΈ This training may not be successful. Consider adjusting the parameters or exploring alternative training options.")
|
| 786 |
+
|
| 787 |
+
|
| 788 |
+
|
| 789 |
+
|
| 790 |
+
# Update this condition to match
|
| 791 |
+
elif page == "π€ HR Chatbot":
|
| 792 |
+
chatbot_main()
|
| 793 |
+
|
| 794 |
+
# ========== Footer ==========
|
chatbot.py
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from langchain_community.agent_toolkits.sql.toolkit import SQLDatabaseToolkit
|
| 3 |
+
from langchain_community.utilities import SQLDatabase
|
| 4 |
+
from langchain.chat_models import init_chat_model
|
| 5 |
+
from langchain_community.agent_toolkits import create_sql_agent
|
| 6 |
+
from langchain.callbacks.base import BaseCallbackHandler
|
| 7 |
+
|
| 8 |
+
# Database connection string
|
| 9 |
+
url = "postgresql://postgres.qxvpaoeakhddzabctekw:8&CiDRpTFbRRBrT@aws-0-ap-south-1.pooler.supabase.com:5432/postgres"
|
| 10 |
+
|
| 11 |
+
# β
Initialize session state variables if they don't exist
|
| 12 |
+
if "db" not in st.session_state:
|
| 13 |
+
st.session_state.db = SQLDatabase.from_uri(url)
|
| 14 |
+
|
| 15 |
+
if "chat_history" not in st.session_state:
|
| 16 |
+
st.session_state.chat_history = [] # Stores past queries and responses
|
| 17 |
+
|
| 18 |
+
if "agent_chain_output" not in st.session_state:
|
| 19 |
+
st.session_state.agent_chain_output = ""
|
| 20 |
+
|
| 21 |
+
# Custom callback handler for streaming output
|
| 22 |
+
class StreamHandler(BaseCallbackHandler):
|
| 23 |
+
def __init__(self, container):
|
| 24 |
+
self.container = container
|
| 25 |
+
self.text = ""
|
| 26 |
+
|
| 27 |
+
def on_llm_start(self, serialized, prompts, **kwargs):
|
| 28 |
+
self.text += "π§ Starting to think...\n\n"
|
| 29 |
+
self.container.markdown(self.text)
|
| 30 |
+
|
| 31 |
+
def on_llm_new_token(self, token, **kwargs):
|
| 32 |
+
self.text += token
|
| 33 |
+
self.container.markdown(self.text)
|
| 34 |
+
|
| 35 |
+
def on_llm_end(self, response, **kwargs):
|
| 36 |
+
self.text += "\n\nβ
Thinking complete.\n\n"
|
| 37 |
+
self.container.markdown(self.text)
|
| 38 |
+
|
| 39 |
+
def on_tool_start(self, serialized, input_str, **kwargs):
|
| 40 |
+
self.text += f"π§ Using tool: {serialized['name']}\n"
|
| 41 |
+
self.text += f"Tool input: {input_str}\n\n"
|
| 42 |
+
self.container.markdown(self.text)
|
| 43 |
+
|
| 44 |
+
def on_tool_end(self, output, **kwargs):
|
| 45 |
+
self.text += f"Tool output: {output}\n\n"
|
| 46 |
+
self.container.markdown(self.text)
|
| 47 |
+
|
| 48 |
+
def on_chain_start(self, serialized, inputs, **kwargs):
|
| 49 |
+
chain_type = serialized.get("name", "Chain")
|
| 50 |
+
self.text += f"βοΈ Starting {chain_type}...\n"
|
| 51 |
+
self.container.markdown(self.text)
|
| 52 |
+
|
| 53 |
+
def on_chain_end(self, outputs, **kwargs):
|
| 54 |
+
self.text += f"βοΈ Chain complete.\n\n"
|
| 55 |
+
self.container.markdown(self.text)
|
| 56 |
+
|
| 57 |
+
def on_agent_action(self, action, **kwargs):
|
| 58 |
+
self.text += f"π€ Agent action: {action.tool}\n"
|
| 59 |
+
self.text += f"Action input: {action.tool_input}\n\n"
|
| 60 |
+
self.container.markdown(self.text)
|
| 61 |
+
|
| 62 |
+
def on_agent_finish(self, finish, **kwargs):
|
| 63 |
+
self.text += f"π Agent finished: {finish.return_values.get('output')}\n\n"
|
| 64 |
+
self.container.markdown(self.text)
|
| 65 |
+
|
| 66 |
+
# Main function to run the app
|
| 67 |
+
def main():
|
| 68 |
+
st.title("π€ Database Query Assistant")
|
| 69 |
+
st.write("Ask questions about your database in natural language.")
|
| 70 |
+
|
| 71 |
+
# Sidebar for database information and settings
|
| 72 |
+
with st.sidebar:
|
| 73 |
+
st.header("Database Information")
|
| 74 |
+
st.write(f"Connected to: PostgreSQL database")
|
| 75 |
+
|
| 76 |
+
# Options
|
| 77 |
+
show_sql = st.checkbox("Show SQL Queries", value=True)
|
| 78 |
+
show_thinking = st.checkbox("Show Agent Thinking", value=True)
|
| 79 |
+
|
| 80 |
+
# Database schema button
|
| 81 |
+
if st.button("Show Database Schema"):
|
| 82 |
+
with st.spinner("Fetching database schema..."):
|
| 83 |
+
schema = st.session_state.db.get_table_info()
|
| 84 |
+
st.code(schema)
|
| 85 |
+
|
| 86 |
+
# Display Chat History
|
| 87 |
+
st.sidebar.subheader("π Chat History")
|
| 88 |
+
for entry in st.session_state.chat_history:
|
| 89 |
+
with st.sidebar.expander(f"Query: {entry['query']}"):
|
| 90 |
+
st.write(f"**Agent Response:** {entry['response']}")
|
| 91 |
+
if show_thinking and "thinking" in entry:
|
| 92 |
+
st.write(f"**Agent Thinking:**\n{entry['thinking']}")
|
| 93 |
+
|
| 94 |
+
if st.sidebar.button("π Clear Chat History"):
|
| 95 |
+
st.session_state.chat_history = []
|
| 96 |
+
st.experimental_rerun()
|
| 97 |
+
|
| 98 |
+
# Query input section
|
| 99 |
+
query_options = ["Free-form query", "Get employee details"]
|
| 100 |
+
query_type = st.radio("Query Type:", query_options)
|
| 101 |
+
|
| 102 |
+
if query_type == "Free-form query":
|
| 103 |
+
query = st.text_area("Enter your query:", height=100,
|
| 104 |
+
placeholder="Example: What are the top 3 highest paid employees?")
|
| 105 |
+
else:
|
| 106 |
+
employee_id = st.text_input("Enter Employee ID:", placeholder="Example: 1001")
|
| 107 |
+
query = f"Give details of employee ID {employee_id}" if employee_id else ""
|
| 108 |
+
|
| 109 |
+
# Process button
|
| 110 |
+
process_button = st.button("Run Query")
|
| 111 |
+
|
| 112 |
+
# Results section
|
| 113 |
+
st.header("Results")
|
| 114 |
+
|
| 115 |
+
# Create containers for output
|
| 116 |
+
if show_thinking:
|
| 117 |
+
thinking_container = st.expander("Agent Thinking Process", expanded=True)
|
| 118 |
+
thinking_output = thinking_container.empty()
|
| 119 |
+
|
| 120 |
+
result_container = st.container()
|
| 121 |
+
result_output = result_container.empty()
|
| 122 |
+
|
| 123 |
+
# Process the query when button is clicked
|
| 124 |
+
if process_button and query:
|
| 125 |
+
# Set up the streaming handlers
|
| 126 |
+
if show_thinking:
|
| 127 |
+
stream_handler = StreamHandler(thinking_output)
|
| 128 |
+
else:
|
| 129 |
+
stream_handler = None
|
| 130 |
+
|
| 131 |
+
# Initialize LLM
|
| 132 |
+
try:
|
| 133 |
+
api_key = "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"
|
| 134 |
+
|
| 135 |
+
# Create a new LLM instance
|
| 136 |
+
llm = init_chat_model(
|
| 137 |
+
"llama-3.3-70b-versatile",
|
| 138 |
+
model_provider="groq",
|
| 139 |
+
api_key=api_key,
|
| 140 |
+
streaming=True,
|
| 141 |
+
callbacks=[stream_handler] if stream_handler else None
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
# Create the agent with callbacks
|
| 145 |
+
toolkit = SQLDatabaseToolkit(db=st.session_state.db, llm=llm)
|
| 146 |
+
agent_executor = create_sql_agent(
|
| 147 |
+
llm,
|
| 148 |
+
toolkit=toolkit,
|
| 149 |
+
verbose=show_thinking,
|
| 150 |
+
callbacks=[stream_handler] if stream_handler else None
|
| 151 |
+
)
|
| 152 |
+
|
| 153 |
+
# Process the query and display the result
|
| 154 |
+
with st.spinner("Processing your query..."):
|
| 155 |
+
result = agent_executor.invoke(query)
|
| 156 |
+
|
| 157 |
+
# Store chat history
|
| 158 |
+
st.session_state.chat_history.append({
|
| 159 |
+
"query": query,
|
| 160 |
+
"response": result["output"],
|
| 161 |
+
"thinking": stream_handler.text if show_thinking else ""
|
| 162 |
+
})
|
| 163 |
+
|
| 164 |
+
# Display the result
|
| 165 |
+
result_container.success("Query processed successfully!")
|
| 166 |
+
result_output.markdown("### Answer")
|
| 167 |
+
result_output.write(result["output"])
|
| 168 |
+
|
| 169 |
+
# Show the SQL if requested
|
| 170 |
+
if show_sql and "intermediate_steps" in result:
|
| 171 |
+
sql_container = st.expander("SQL Queries Used", expanded=True)
|
| 172 |
+
for step in result["intermediate_steps"]:
|
| 173 |
+
if hasattr(step[0], 'tool') and step[0].tool == "sql_db_query":
|
| 174 |
+
sql_container.code(step[0].tool_input, language="sql")
|
| 175 |
+
|
| 176 |
+
except Exception as e:
|
| 177 |
+
st.error(f"An error occurred: {str(e)}")
|
| 178 |
+
|
| 179 |
+
if __name__ == "__main__":
|
| 180 |
+
main()
|
gif image.gif
ADDED
|
istockphoto-1221348467-612x612.jpg
ADDED
|
requirements.txt
CHANGED
|
@@ -2,3 +2,6 @@ streamlit
|
|
| 2 |
requests
|
| 3 |
pandas
|
| 4 |
plotly
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
requests
|
| 3 |
pandas
|
| 4 |
plotly
|
| 5 |
+
supabase-py
|
| 6 |
+
python-dotenv
|
| 7 |
+
psycopg2-binary
|
samplegif.gif
ADDED
|