SMEIntervention / app.py
rairo's picture
Update app.py
d989293 verified
from pandasai.llm import GoogleGemini
import streamlit as st
import os
import pandas as pd
from pandasai import SmartDataframe
from pandasai.responses.response_parser import ResponseParser
from st_on_hover_tabs import on_hover_tabs
from ydata_profiling import ProfileReport
import google.generativeai as genai
import json
import plotly.express as px
class StreamLitResponse(ResponseParser):
def __init__(self,context) -> None:
super().__init__(context)
def format_dataframe(self,result):
st.dataframe(result['value'])
return
def format_plot(self,result):
st.image(result['value'])
return
def format_other(self, result):
st.write(result['value'])
return
gemini_api_key = os.environ['Gemini']
genai.configure(api_key=gemini_api_key)
generation_config = {
"temperature": 0.2,
"top_p": 0.95,
"max_output_tokens": 5000,
}
model = genai.GenerativeModel(
model_name="gemini-2.0-flash-thinking-exp",
generation_config=generation_config,
)
def calculate_kpis(df):
total_interventions = len(df) if hasattr(df, '__len__') else 0 # Check if df is a dataframe
try:
interventions_by_category = df['Intervention_Category'].value_counts().to_dict() if 'Intervention_Category' in df.columns else {}
except AttributeError:
interventions_by_category = {}
try:
interventions_by_type = df['Intervention'].value_counts().to_dict() if 'Intervention' in df.columns else {}
except AttributeError:
interventions_by_type = {}
try:
male_participants = len(df[df['Gender'] == 'Male']) if 'Gender' in df.columns else 0
except TypeError:
male_participants = 0
try:
female_participants = len(df[df['Gender'] == 'Female']) if 'Gender' in df.columns else 0
except TypeError:
female_participants = 0
try:
youth_participants = len(df[df['Youth'] == 'Yes']) if 'Youth' in df.columns else 0
except TypeError:
youth_participants = 0
try:
non_youth_participants = len(df[df['Youth'] == 'No']) if 'Youth' in df.columns else 0
except TypeError:
non_youth_participants = 0
kpis = {
"total_interventions": total_interventions,
"interventions_by_category": interventions_by_category,
"interventions_by_type": interventions_by_type,
"male_participants": male_participants,
"female_participants": female_participants,
"youth_participants": youth_participants,
"non_youth_participants": non_youth_participants,
}
return kpis
def get_pandas_profile(df):
profile = ProfileReport(df, title="Profiling Report")
json_profile = profile.to_json()
dict_p = json.loads(json_profile)
keys_to_keep = ['analysis', 'table', 'correlations', 'alerts', 'sample']
# Assuming your dictionary is named 'my_dict'
filtered_dict = {key: dict_p[key] for key in keys_to_keep}
return filtered_dict
def generateResponse(dataFrame,prompt):
llm = GoogleGemini(api_key=gemini_api_key)
pandas_agent = SmartDataframe(dataFrame,config={"llm":llm, "response_parser":StreamLitResponse})
answer = pandas_agent.chat(prompt)
return answer
st.write("# Intervention Analytics")
st.markdown('<style>' + open('./style.css').read() + '</style>', unsafe_allow_html=True)
st.write("Get analysis and engage in insightful conversations with your data through our powerful AI")
with st.sidebar:
st.subheader("Intervention Analytics")
st.sidebar.image("logoqb.jpeg", use_column_width=True)
tabs = on_hover_tabs(tabName=['Chat', 'Reports'], iconName=['chat', 'dashboard'], default_choice=0)
uploaded_file = "Intervention.csv"
# Load the full data *once*
df = pd.read_csv(uploaded_file)
if tabs == 'Chat':
st.write("Overall Data Visualizations") # Title above the visualizations
col1, col2 = st.columns([1, 1]) # Half and half split
with col1: # Visualizations on the left
st.set_option('deprecation.showPyplotGlobalUse', False) # Suppress warning
fig_youth = px.histogram(df, x="Youth", title="Youth Participation")
fig_youth.update_layout(height=400, width=None) # Responsive width
st.plotly_chart(fig_youth)
fig_company = px.histogram(df, y="Company Name", title="Company Distribution")
fig_company.update_layout(height=400, width=None) # Responsive width
st.plotly_chart(fig_company)
fig_category = px.histogram(df, y="Intervention_Category", title="Intervention Category Distribution")
fig_category.update_layout(height=400, width=None) # Responsive width
st.plotly_chart(fig_category)
fig_intervention = px.histogram(df, y="Intervention", title="Intervention Type Distribution")
fig_intervention.update_layout(height=400, width=None) # Responsive width
st.plotly_chart(fig_intervention)
fig_pie_category = px.pie(df, names='Intervention_Category', title='Intervention Category Pie Chart')
fig_pie_category.update_layout(height=400, width=None) # Responsive width
st.plotly_chart(fig_pie_category)
with col2: # Chat on the right
st.subheader("Chat with AI")
st.write("Get visualizations and analysis from our Gemini powered agent")
with st.expander("Preview"):
st.write(df.head())
user_input = st.text_input("Type your message here", placeholder="Ask me about your data")
if user_input:
answer = generateResponse(dataFrame=df, prompt=user_input)
st.write(answer)
elif tabs == 'Reports':
df = pd.read_csv(uploaded_file)
st.subheader("Reports")
st.write("Filter by Company Name, Gender, Youth, Intervention Category or Intervention to generate report")
# Filtering Interface
st.write("Filtering Options")
company_names = df['Company Name'].unique().tolist()
gender_options = df['Gender'].unique().tolist()
youth_options = df['Youth'].unique().tolist()
intervention_categories = df['Intervention_Category'].unique().tolist()
intervention_types = df['Intervention'].unique().tolist()
selected_companies = st.multiselect('Select Company(ies)', company_names, default=company_names)
selected_genders = st.multiselect('Select Gender(s)', gender_options, default=gender_options)
selected_youth = st.multiselect('Select Youth Status(es)', youth_options, default=youth_options)
selected_categories = st.multiselect('Select Intervention Category(ies)', intervention_categories, default=intervention_categories)
selected_interventions = st.multiselect('Select Intervention(s)', intervention_types, default=intervention_types)
if st.button('Apply Filters and Generate report'):
filtered_df = df.copy()
if selected_companies:
filtered_df = filtered_df[filtered_df['Company Name'].isin(selected_companies)]
if selected_genders:
filtered_df = filtered_df[filtered_df['Gender'].isin(selected_genders)]
if selected_youth:
filtered_df = filtered_df[filtered_df['Youth'].isin(selected_youth)]
if selected_categories:
filtered_df = filtered_df[filtered_df['Intervention_Category'].isin(selected_categories)]
if selected_interventions:
filtered_df = filtered_df[filtered_df['Intervention'].isin(selected_interventions)]
if not filtered_df.empty:
if len(filtered_df) > 1:
st.write("Filtered DataFrame")
with st.expander("Preview"):
st.write(filtered_df.head())
with st.spinner("Generating Report, Please Wait...."):
try:
prompt = f"""
You are an expert business analyst. Analyze the following data and generate a comprehensive and insightful business report,
including appropriate key performance indicators and recommendations.
Data: dataset:{str(filtered_df.to_json(orient='records'))}, kpis: {str(calculate_kpis(filtered_df))}
"""
response = model.generate_content(prompt)
report = response.text
st.markdown(report)
st.success("Report Generation Complete")
except Exception as e:
st.write(f"Error generating report: {e}")
else:
st.write("Not enough data after filtering for full visualizations and report generation.")
if not filtered_df.empty:
st.write("Filtered DataFrame:")
st.write(filtered_df)
else:
st.write("No data after filtering.")
else:
st.write("Click 'Apply Filters' to see the filtered data.")