import os import json import bcrypt import pandas as pd import numpy as np import plotly.express as px from typing import List from pathlib import Path from langchain_openai import ChatOpenAI from langchain.schema.runnable.config import RunnableConfig from langchain.schema import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain.agents import AgentExecutor from langchain.agents.agent_types import AgentType from langchain_experimental.agents.agent_toolkits import create_pandas_dataframe_agent, create_csv_agent import chainlit as cl from chainlit.input_widget import TextInput, Select, Switch, Slider from deep_translator import GoogleTranslator from IPython.display import display @cl.password_auth_callback def auth_callback(username: str, password: str): auth = json.loads(os.environ['CHAINLIT_AUTH_LOGIN']) ident = next(d['ident'] for d in auth if d['ident'] == username) pwd = next(d['pwd'] for d in auth if d['ident'] == username) resultLogAdmin = bcrypt.checkpw(username.encode('utf-8'), bcrypt.hashpw(ident.encode('utf-8'), bcrypt.gensalt())) resultPwdAdmin = bcrypt.checkpw(password.encode('utf-8'), bcrypt.hashpw(pwd.encode('utf-8'), bcrypt.gensalt())) resultRole = next(d['role'] for d in auth if d['ident'] == username) if resultLogAdmin and resultPwdAdmin and resultRole == "admindatapcc": return cl.User( identifier=ident + " : đŸ§‘â€đŸ’Œ Admin Datapcc", metadata={"role": "admin", "provider": "credentials"} ) elif resultLogAdmin and resultPwdAdmin and resultRole == "userdatapcc": return cl.User( identifier=ident + " : 🧑‍🎓 User Datapcc", metadata={"role": "user", "provider": "credentials"} ) def create_agent(filename: str): """ Create an agent that can access and use a large language model (LLM). Args: filename: The path to the CSV file that contains the data. Returns: An agent that can access and use the LLM. """ # Create an OpenAI object. os.environ['OPENAI_API_KEY'] = os.environ['OPENAI_API_KEY'] llm = ChatOpenAI(temperature=0, model="gpt-4o-2024-05-13") # Read the CSV file into a Pandas DataFrame. df = pd.read_csv(filename) # Create a Pandas DataFrame agent. return create_csv_agent(llm, filename, verbose=False, allow_dangerous_code=True, handle_parsing_errors=True, agent_type=AgentType.OPENAI_FUNCTIONS) def query_agent(agent, query): """ Query an agent and return the response as a string. Args: agent: The agent to query. query: The query to ask the agent. Returns: The response from the agent as a string. """ prompt = ( """ For the following query, if it requires drawing a table, reply as follows: {"table": {"columns": ["column1", "column2", ...], "data": [[value1, value2, ...], [value1, value2, ...], ...]}} If the query requires creating a bar chart, reply as follows: {"bar": {"columns": ["A", "B", "C", ...], "data": [25, 24, 10, ...]}} If the query requires creating a line chart, reply as follows: {"line": {"columns": ["A", "B", "C", ...], "data": [25, 24, 10, ...]}} There can only be two types of chart, "bar" and "line". If it is just asking a question that requires neither, reply as follows: {"answer": "answer"} Example: {"answer": "The title with the highest rating is 'Gilead'"} If you do not know the answer, reply as follows: {"answer": "I do not know."} Return all output as a string. All strings in "columns" list and data list, should be in double quotes, For example: {"columns": ["title", "ratings_count"], "data": [["Gilead", 361], ["Spider's Web", 5164]]} Lets think step by step. Below is the query. Query: """ + query ) # Run the prompt through the agent. response = agent.invoke(prompt) # Convert the response to a string. return response.__str__() def decode_response(response: str) -> dict: """This function converts the string response from the model to a dictionary object. Args: response (str): response from the model Returns: dict: dictionary with response data """ return json.loads("[" + response + "]") def write_response(response_dict: dict): """ Write a response from an agent to a Streamlit app. Args: response_dict: The response from the agent. Returns: None. """ # Check if the response is an answer. return response_dict["answer"] @cl.set_chat_profiles async def chat_profile(): return [ cl.ChatProfile(name="Traitement des donnĂ©es d'enquĂȘte : «ExpĂ© CFA : questionnaire auprĂšs des professionnels de la branche de l'agencement»",markdown_description="VidĂ©o exploratoire autour de l'Ă©vĂ©nement",icon="/public/logo-ofipe.png",), ] #@cl.set_starters #async def set_starters(): # return [ # cl.Starter( # label="RĂ©partition du nombre de CAA dans les entreprises", # message="Quel est le nombre de chargĂ©.e d'affaires en agencement dans chaque type d'entreprises?", # icon="/public/request-theme.svg", # ) # ] @cl.on_chat_start async def on_chat_start(): await cl.Message(f"> SURVEYIA").send() elements = [] df = pd.read_csv('./public/survey.csv') df_taille = df.groupby('taille_entreprise').size().reset_index(name='obs') fig_taille = px.pie(df_taille, names='taille_entreprise', values='obs', color='obs', title="La taille des entreprises ayant rĂ©pondu", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe).update_traces(textposition='inside', textinfo='percent+label').update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_taille", figure=fig_taille, display="inline", size="small")) #await cl.sleep(2) df_temps = df.groupby('temps_active_domaine_agencement').size().reset_index(name='obs') fig_temps = px.pie(df_temps, names='temps_active_domaine_agencement', values='obs', color='obs', title="L’engagement dans le domaine de l’agencement", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe).update_traces(textposition='inside', textinfo='percent+label').update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_temps", figure=fig_temps, display="inline", size="small")) #await cl.sleep(2) df_temps_entreprise = df.groupby(['temps_active_domaine_agencement', 'taille_entreprise']).size().reset_index(name='obs') fig_temps_entreprise = px.bar(df_temps_entreprise, x='temps_active_domaine_agencement', y='obs', color='taille_entreprise', title="L’engagement dans le domaine de l’agencement par taille d'entreprise", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_temps_entreprise", figure=fig_temps_entreprise, display="inline", size="small")) #await cl.sleep(2) df_nb_charge = df.groupby('nombre_chargĂ©s_affaires').size().reset_index(name='obs') fig_nb_charge = px.pie(df_nb_charge, names='nombre_chargĂ©s_affaires', values='obs', color='obs', title="Le nombre de chargĂ©.e d’affaires en agencement", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe).update_traces(textposition='inside', textinfo='percent+label').update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_nb_charge", figure=fig_nb_charge, display="inline", size="small")) #await cl.sleep(2) df_nb_charge_entreprise = df.groupby(['nombre_chargĂ©s_affaires', 'taille_entreprise']).size().reset_index(name='obs') fig_nb_charge_entreprise = px.bar(df_nb_charge_entreprise, x='nombre_chargĂ©s_affaires', y='obs', color='taille_entreprise', title="Le nombre de chargĂ©.e d’affaires en agencement par taille d'entreprise", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_nb_charge_entreprise", figure=fig_nb_charge_entreprise, display="inline", size="small")) #await cl.sleep(2) df_nb_charge_engagement = df.groupby(['nombre_chargĂ©s_affaires', 'temps_active_domaine_agencement']).size().reset_index(name='obs') fig_nb_charge_entreprise = px.bar(df_nb_charge_engagement, x='nombre_chargĂ©s_affaires', y='obs', color='temps_active_domaine_agencement', title="Le nombre de chargĂ©.e d’affaires en agencement par annĂ©e d'engagement", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_nb_charge_entreprise", figure=fig_nb_charge_entreprise, display="inline", size="small")) #await cl.sleep(2) df_statut = df.groupby('fonction_Statut_repondant').size().reset_index(name='obs') fig_statut = px.bar(df_statut, x='obs', y='fonction_Statut_repondant', orientation='h', color='obs', title="Le profil des rĂ©pondants", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_statut", figure=fig_statut, display="inline", size="small")) #await cl.sleep(2) df1 = df df1['principaux_interlocuteurs'] = df1['principaux_interlocuteurs'].str.split(';') df1 = df1.explode('principaux_interlocuteurs') df_interlocuteur = df1.groupby('principaux_interlocuteurs').size().reset_index(name='obs') fig_interlocuteur = px.bar(df_interlocuteur, x='obs', y='principaux_interlocuteurs', orientation='h', color='obs', title="Les principaux interlocuteurs du CAA", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_interlocuteur", figure=fig_interlocuteur, display="inline", size="small")) #await cl.sleep(2) df_interlocuteur_entreprise = df1.groupby(['principaux_interlocuteurs', 'taille_entreprise']).size().reset_index(name='obs') fig_interlocuteur_entreprise = px.bar(df_interlocuteur_entreprise, x='obs', y='principaux_interlocuteurs', orientation='h', color='taille_entreprise', title="Les principaux interlocuteurs du CAA par taille d'entreprise", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_interlocuteur_entreprise", figure=fig_interlocuteur_entreprise, display="inline", size="small")) #await cl.sleep(2) df_interlocuteur_nb_charge = df1.groupby(['principaux_interlocuteurs', 'nombre_chargĂ©s_affaires']).size().reset_index(name='obs') fig_interlocuteur_nb_charge = px.bar(df_interlocuteur_nb_charge, x='obs', y='principaux_interlocuteurs', orientation='h', color='nombre_chargĂ©s_affaires', title="Les principaux interlocuteurs du CAA par nombre chargĂ©.e d'affaires", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_interlocuteur_nb_charge", figure=fig_interlocuteur_nb_charge, display="inline", size="small")) #await cl.sleep(2) df2 = df df2['principales_compĂ©tences_attendues'] = df2['principales_compĂ©tences_attendues'].str.split(';') df2 = df2.explode('principales_compĂ©tences_attendues') df_competences = df2.groupby('principales_compĂ©tences_attendues').size().reset_index(name='obs') fig_competences = px.bar(df_competences, x='obs', y='principales_compĂ©tences_attendues', orientation='h', color='obs', title="Les principales compĂ©tences attendues", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_competences", figure=fig_competences, display="inline", size="small")) #await cl.sleep(2) df_competences_entreprise = df2.groupby(['principales_compĂ©tences_attendues', 'taille_entreprise']).size().reset_index(name='obs') fig_competences_entreprise = px.bar(df_competences_entreprise, x='obs', y='principales_compĂ©tences_attendues', orientation='h', color='taille_entreprise', title="Les principales compĂ©tences attendues par taille d'entreprise", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_competences_entreprise", figure=fig_competences_entreprise, display="inline", size="small")) #await cl.sleep(2) df_competences_nb_charge = df2.groupby(['principales_compĂ©tences_attendues', 'nombre_chargĂ©s_affaires']).size().reset_index(name='obs') fig_competences_nb_charge = px.bar(df_competences_nb_charge, x='obs', y='principales_compĂ©tences_attendues', orientation='h', color='nombre_chargĂ©s_affaires', title="Les principales compĂ©tences attendues par nombre chargĂ©.e d'affaires", labels={'obs':'nombre'}, color_discrete_sequence=px.colors.qualitative.Safe, text_auto=True).update_layout(font=dict(size=9,color="RebeccaPurple")) elements.append(cl.Plotly(name="chart_competences_nb_charge", figure=fig_competences_nb_charge, display="inline", size="small")) tableau_taille = [cl.Text(name="Tableaux", content=df_taille.to_html(), display="side")] tableau_temps = [cl.Text(name="Tableaux", content=df_temps.to_html(), display="side")] await cl.Message(content="Tableaux des donnĂ©es de La \"taille des entreprises ayant rĂ©pondu\"", elements=tableau_taille,).send() await cl.Message(content="Tableaux des donnĂ©es de \"L’engagement dans le domaine de l’agencement\"", elements=tableau_temps,).send() await cl.Message(content="Datavisualisation de l'enquĂȘte des recruteurs des chargĂ©.e.s d'affaires en agencement", elements=elements).send() @cl.on_message async def on_message(message: cl.Message): await cl.Message(f"> SURVEYIA").send() agent = create_agent("./public/surveyia.csv") cb = cl.AsyncLangchainCallbackHandler() try: res = await agent.acall("RĂ©ponds en langue française Ă  la question suivante : " + message.content, callbacks=[cb]) await cl.Message(author="COPILOT",content=GoogleTranslator(source='auto', target='fr').translate(res['output'])).send() except ValueError as e: res = str(e) resArray = res.split(":") ans = '' if str(res).find('parsing') != -1: for i in range(2,len(resArray)): ans += resArray[i] await cl.Message(author="COPILOT",content=ans.replace("`","")).send() else: await cl.Message(author="COPILOT",content="Reformulez votre requĂȘte, s'il vous plait 😃").send() # Query the agent. #response = query_agent(agent=agent, query=message.content) # Decode the response. #decoded_response = decode_response(response) # Write the response to the Streamlit app. #result = write_response(decoded_response) #await cl.Message(author="COPILOT",content=GoogleTranslator(source='auto', target='fr').translate(result)).send()