logeswari commited on
Commit
4709845
Β·
1 Parent(s): 1de30c8

changes made

Browse files
.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
- # Debugging: Print API response
19
- print(f"Fetched from {url} | Params: {params} | Response: {data}")
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) # Convert list to DataFrame
 
26
  except requests.exceptions.RequestException as e:
 
27
  st.error(f"Error fetching data: {e}")
28
  return None
29
 
 
 
 
30
 
31
- # βœ… Set up Streamlit app layout
32
- st.set_page_config(page_title="HR Analytics Dashboard", layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- # βœ… Sidebar Navigation: Two main pages
35
- st.sidebar.title("πŸ“Š HR Analytics Dashboard")
36
- page = st.sidebar.selectbox("Select Page", ["🏠 Home", "πŸ“ˆ Analytics Dashboard"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- # βœ… HOME PAGE
39
  if page == "🏠 Home":
40
  st.title("🏠 Welcome to the HR Analytics Dashboard")
41
- st.write("Explore different HR metrics and insights.")
42
 
43
- # βœ… ANALYTICS DASHBOARD (with 9 endpoints)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  elif page == "πŸ“ˆ Analytics Dashboard":
45
 
46
- # Select an analysis option inside the Analytics page
47
- analysis_option = st.sidebar.selectbox("Choose an analysis:", [
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
- if analysis_option == "Employee Satisfaction":
82
- department = st.sidebar.text_input("Enter Department (optional):")
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
- if analysis_option == "Department Performance":
95
  data = fetch_data("/department-performance")
96
- display_chart(data, "scatter", "DepartmentType", "Performance Score", "πŸ“Š Departmental Performance Metrics")
97
 
 
 
 
 
 
 
 
 
 
 
98
 
99
  # βœ… Training Program Analytics
100
- if analysis_option == "Training Analytics":
101
- program_name = st.sidebar.text_input("Enter Training Program Name (optional):")
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.title("πŸ“Š Training Program Analytics")
107
- st.dataframe(data)
108
 
109
- if "Training Program Name" in data.columns:
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
- if analysis_option == "Engagement-Performance Correlation":
118
  data = fetch_data("/engagement-performance")
119
-
120
  if data is not None and not data.empty:
121
- st.title("πŸ“Š Engagement vs. Performance Correlation")
122
- correlation_value = data.iloc[0, 0] # Extract correlation coefficient
123
- st.metric(label="Correlation Coefficient", value=f"{correlation_value:.2f}") # Display metric
124
 
125
 
 
 
 
 
 
 
126
  # βœ… Cost-Benefit Analysis
127
- if analysis_option == "Cost-Benefit Analysis":
128
  data = fetch_data("/cost-benefit-analysis")
129
- display_chart(data, "pie", "DepartmentType", "ROI", "πŸ“Š Cost-Benefit Analysis")
 
 
 
 
130
 
131
 
 
 
 
 
 
132
  # βœ… Training Effectiveness Metrics
133
- if analysis_option == "Training Effectiveness":
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
- if analysis_option == "Diversity & Inclusion":
140
  data = fetch_data("/diversity-inclusion")
141
 
142
  if data is not None and not data.empty:
143
- st.title("πŸ“Š Diversity and Inclusion Dashboard")
144
- st.dataframe(data)
145
 
146
- # Convert to long format for plotting
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
- if analysis_option == "Work-Life Balance Impact":
157
  data = fetch_data("/work-life-balance")
158
 
159
  if data is not None and not data.empty:
160
- st.title("πŸ“Š Work-Life Balance vs. Performance Correlation")
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.sidebar.selectbox("Select Employee ID:", [""] + employee_ids)
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.dataframe(data)
182
- fig = px.histogram(data, x="Career Movements", title="πŸ“Š Career Development Histogram", nbins=10, height=500)
183
- st.plotly_chart(fig, use_container_width=True)
184
- else:
185
- st.warning("No data available for the selected Employee ID.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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