Samad Filali commited on
Commit
7715c35
·
0 Parent(s):

First commit

Browse files
.env ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ TAVILY_API_KEY=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
2
+ LANGCHAIN_API_KEY=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
3
+ GROQ_API_KEY=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
4
+ LANGSMITH_API_key=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
BD_Echantillon_2014.db ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7186e3cfbebec41d45d13af1f161e41c344a7e8db7894039b8b49725e0311b05
3
+ size 5656576
Input/Liste_des_tables.txt ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Milieur_de_Résidence
2
+ Code de modalité Nom de modalité
3
+ 1 Urbain
4
+ 2 Rural
5
+ 9 Information identifiante
6
+
7
+ Lien_avec_le_chef_de_ménage
8
+ Code de modalité Nom de modalité
9
+ 0 Chef de ménage
10
+ 1 Conjoint
11
+ 2 Fils / Fille
12
+ 3 Petit-fils / Petite-fille
13
+ 4 Père / Mère
14
+ 5 Frère / Sœur
15
+ 6 Gendre / Bru
16
+ 7 Autre parent
17
+ 8 Domestique
18
+ 9 Personne sans lien de parenté
19
+ 99 Non déterminé
20
+
21
+ Nationalité
22
+ Code de modalité Nom de modalité
23
+ 1 Marocaine
24
+ 2 Africaine (non marocaine)
25
+ 3 Européenne
26
+ 4 Autre nationalité étrangère n.c.a.
27
+ 9 Nationalité étrangère non déterminée
28
+
29
+ Sexe
30
+ Code de modalité Nom de modalité
31
+ 1 Masculin
32
+ 2 Féminin
33
+
34
+ Age_simple_pour_les_moins_de_25_ans
35
+ Code de modalité Nom de modalité
36
+ 0 Moins d'1 an
37
+ 1 1 an
38
+ 2 2 ans
39
+ 3 3 ans
40
+ 4 4 ans
41
+ 5 5 ans
42
+ 6 6 ans
43
+ 7 7 ans
44
+ 8 8 ans
45
+ 9 9 ans
46
+ 10 10 ans
47
+ 11 11 ans
48
+ 12 12 ans
49
+ 13 13 ans
50
+ 14 14 ans
51
+ 15 15 ans
52
+ 16 16 ans
53
+ 17 17 ans
54
+ 18 18 ans
55
+ 19 19 ans
56
+ 20 20 ans
57
+ 21 21 ans
58
+ 22 22 ans
59
+ 23 23 ans
60
+ 24 24 ans
61
+ 98 25 ans et plus
62
+ 99 Non déterminé
63
+
64
+ Age_quinquennal
65
+ Code de modalité Nom de modalité
66
+ 0 0-4 ans
67
+ 5 5-9 ans
68
+ 10 10-14 ans
69
+ 15 15-19 ans
70
+ 20 20-24 ans
71
+ 25 25-29 ans
72
+ 30 30-34 ans
73
+ 35 35-39 ans
74
+ 40 40-44 ans
75
+ 45 45-49 ans
76
+ 50 50-54 ans
77
+ 55 55-59 ans
78
+ 60 60-64 ans
79
+ 65 65-69 ans
80
+ 70 70-74 ans
81
+ 75 75 ans et plus
82
+ 99 Non déterminé
83
+
84
+ Etat_Matrimonial
85
+ Code de modalité Nom de modalité
86
+ 1 Célibataire
87
+ 2 Marié
88
+ 3 Divorcé
89
+ 4 Veuf
90
+ 9 Non déterminé
91
+
92
+ Enfants_vivants_Nombre
93
+ Code de modalité Nom de modalité
94
+ 0 Aucun enfant
95
+ 1 1 enfant
96
+ 2 2 enfants
97
+ 3 3 enfants
98
+ 4 4 enfants
99
+ 5 5 enfants
100
+ 6 6 enfants
101
+ 7 7 enfants
102
+ 8 8 enfants
103
+ 9 9 enfants
104
+ 10 10 enfants et plus
105
+ 96 Non déterminé
106
+ 97 Femme dont l'état matrimonial est non déterminé
107
+ 98 Femme célibataire
108
+ 99 Homme
109
+ Enfants_décédés_Nombre
110
+ Code de modalité Nom de modalité
111
+ 0 Aucun enfant
112
+ 1 1 enfant
113
+ 2 2 enfants
114
+ 3 3 enfants
115
+ 4 4 enfants
116
+ 5 5 enfants
117
+ 6 6 enfants
118
+ 7 7 enfants
119
+ 8 8 enfants
120
+ 9 9 enfants
121
+ 10 10 enfants et plus
122
+ 96 Non déterminé
123
+ 97 Femme dont l'état matrimonial est non déterminé
124
+ 98 Femme célibataire
125
+ 99 Homme
126
+
127
+ Naissances_vivantes_durant_les_12_mois_précédant_la_date_de_référence_du_recensement_Nombre
128
+ Code de modalité Nom de modalité
129
+ 0 Aucun enfant
130
+ 1 1 enfant
131
+ 2 2 enfants
132
+ 3 3 enfants
133
+ 95 Non déterminé
134
+ 96 Femme dont l'état matrimonial est non déterminé
135
+ 97 Femme non célibataire de 55 ans ou plus
136
+ 98 Femme célibataire
137
+ 99 Homme
138
+
139
+ Décés_parmi_les_naissances_vivates_des-12_mois_précédant_la_date_de_référence_du_recensement_Nombre
140
+ Code de modalité Nom de modalité
141
+ 0 Aucun enfant
142
+ 1 1 enfant
143
+ 2 2 enfants
144
+ 3 3 enfants
145
+ 4 4 enfants
146
+ 5 5 enfants
147
+ 95 Non déterminé
148
+ 96 Femme dont l'état matrimonial est non déterminé
149
+ 97 Femme non célibataire de 55 ans ou plus
150
+ 98 Femme célibataire
151
+ 99 Homme
152
+
153
+ Handicap_Vision
154
+ Code de modalité Nom de modalité
155
+ 0 Aucune difficulté
156
+ 1 Peu de difficulté
157
+ 2 Beaucoup de difficulté
158
+ 3 Incapacité
159
+
160
+ Handicap_Audition
161
+ Code de modalité Nom de modalité
162
+ 0 Aucune difficulté
163
+ 1 Peu de difficulté
164
+ 2 Beaucoup de difficulté
165
+ 3 Incapacité
166
+
167
+ Handicap_Mobilité
168
+ Code de modalité Nom de modalité
169
+ 0 Aucune difficulté
170
+ 1 Peu de difficulté
171
+ 2 Beaucoup de difficulté
172
+ 3 Incapacité
173
+
174
+ Handicap_Mémoire
175
+ Code de modalité Nom de modalité
176
+ 0 Aucune difficulté
177
+ 1 Peu de difficulté
178
+ 2 Beaucoup de difficulté
179
+ 3 Incapacité
180
+
181
+ Handicap_Entretien_Personnel
182
+ Code de modalité Nom de modalité
183
+ 0 Aucune difficulté
184
+ 1 Peu de difficulté
185
+ 2 Beaucoup de difficulté
186
+ 3 Incapacité
187
+
188
+ Handicap_Communication
189
+ Code de modalité Nom de modalité
190
+ 0 Aucune difficulté
191
+ 1 Peu de difficulté
192
+ 2 Beaucoup de difficulté
193
+ 3 Incapacité
194
+
195
+ Handicap_Situation
196
+ Code de modalité Nom de modalité
197
+ 1 Personne en situation de handicap
198
+ 2 Personne non en situation de handicap
199
+
200
+
201
+
202
+
203
+ Code de modalité Nom de modalité
204
+
205
+ Code de modalité Nom de modalité
206
+
207
+ Code de modalité Nom de modalité
208
+
209
+ Code de modalité Nom de modalité
210
+
211
+ Code de modalité Nom de modalité
212
+
213
+ Code de modalité Nom de modalité
214
+
215
+ Code de modalité Nom de modalité
216
+
217
+ Code de modalité Nom de modalité
218
+
219
+ Code de modalité Nom de modalité
220
+
221
+ Code de modalité Nom de modalité
Input/Liste_des_tables.xlsx ADDED
Binary file (33.1 kB). View file
 
Modules/Agent_HCP.py ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_community.utilities import SQLDatabase
2
+ from dotenv import load_dotenv
3
+ from langchain_community.agent_toolkits import create_sql_agent
4
+ from langchain.agents import AgentType
5
+ from langchain.prompts import PromptTemplate
6
+ from langchain_groq import ChatGroq
7
+ import os
8
+ import ast
9
+ import Modules
10
+ import csv
11
+ import re
12
+ import json
13
+ from operator import itemgetter
14
+ from typing import List
15
+ from langchain_core.chat_history import BaseChatMessageHistory
16
+ from langchain_core.documents import Document
17
+ from langchain_core.messages import BaseMessage, AIMessage, HumanMessage
18
+ from langchain_core.memory import BaseMemory
19
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
20
+ # A remettre pour python 10
21
+ #from langchain_core.pydantic_v1 import BaseModel, Field
22
+ from pydantic import BaseModel , Field
23
+ from langchain_core.runnables import (
24
+ RunnableLambda,
25
+ ConfigurableFieldSpec,
26
+ RunnablePassthrough,
27
+ )
28
+
29
+ from langchain_core.runnables.history import RunnableWithMessageHistory
30
+ from typing import Optional
31
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
32
+
33
+
34
+
35
+ # Load the API_Keys
36
+ load_dotenv()
37
+ #langsmith_api_key = os.environ.get("LANGSMITH_API_key")
38
+ groq_api_key = os.environ.get("GROQ_API_KEY")
39
+
40
+ model = ChatGroq(temperature=0,
41
+ groq_api_key=groq_api_key,
42
+ #model_name="llama3-8b-8192"
43
+ model_name="llama3-70b-8192"
44
+ )
45
+ db = SQLDatabase.from_uri("sqlite:///"+Modules.DATA_BASE, sample_rows_in_table_info=5)
46
+
47
+ custom_prompt = PromptTemplate(
48
+ input_variables=['agent_scratchpad', 'input', 'history'], # Ajout de 'history' comme variable d'entrée
49
+ partial_variables={
50
+ 'tools': "sql_db_query - Input to this tool is a detailed and correct SQL query, output is a result from the database. If the query is not correct, an error message will be returned. If an error is returned, rewrite the query, check the query, and try again. If you encounter an issue with Unknown column 'xxxx' in 'field list', use sql_db_schema to query the correct table fields.\nsql_db_schema - Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables. Be sure that the tables actually exist by calling sql_db_list_tables first! Example Input: table1, table2, table3\nsql_db_list_tables - Input is an empty string, output is a comma-separated list of tables in the database.\nsql_db_query_checker - Use this tool to double-check if your query is correct before executing it. Always use this tool before executing a query with sql_db_query!",
51
+ 'tool_names': 'sql_db_query, sql_db_schema, sql_db_list_tables, sql_db_query_checker'
52
+ },
53
+ template="You are an expert in statistics designed to interact with a SQL database containing Moroccan census data.\n\
54
+ There is only one primary table in the database called `Table_recensement`, which contains population census data. To get the distinct modalities of any field in this table,\n\
55
+ you must query the table with the same name as the field. For example, if the field is `Age`, you must query the table `Age`.\nGiven an input question, create a syntactically correct SQLite query to run, then look at the results of the query and return the answer.\n\
56
+ Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most 50 results.\n\
57
+ If you can't find the query, return empty. You can order the results by a relevant column to return the most interesting examples in the database.\n\
58
+ Never query for all the columns from a specific table, only ask for the relevant columns given the question.\n\
59
+ You have access to tools for interacting with the database.\nOnly use the tools below. Only use the information returned by the tools below to construct your final answer.\n\
60
+ You MUST double-check your query before executing it. If you get an error while executing a query, rewrite the query and try again.\n\n\
61
+ DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP, etc.) to the database.\n\n\
62
+ If the question does not seem related to the database, just return I don't know as the answer.\n\n\
63
+ If relevant, you can refer to previous parts of the conversation to enrich your answer.\n\n\n{tools}\n\n\
64
+ Use the following format:\n\nQuestion: the input question you must answer\n\n\
65
+ Thought: you should always think about what to do\n\
66
+ Action: the action to take, should be one of [{tool_names}]\n\n\
67
+ Action Input: the input to the action\n\
68
+ Observation: the result of the action\n... (this Thought/Action/Action Input/Observation can repeat N times)\n\n\
69
+ Thought: I now know the final answer\n\n\
70
+ Final Answer: The final answer must be in the same language as the input. Detect the language of the input and respond in the same language.\n\n\
71
+ Begin!\n\n\
72
+ Relevant pieces of previous conversation (optional): {history}\n\
73
+ Question: {input}\n\
74
+ Thought: I should look at the tables in the database to see what I can query. Then I should query the schema of the most relevant fields and retrieve\n\
75
+ the distinct modalities for any given field using `SELECT DISTINCT XXXX FROM FieldName`.\n\
76
+ {agent_scratchpad}"
77
+ )
78
+
79
+
80
+
81
+ # Create Chatbot
82
+
83
+ class InMemoryHistory(BaseChatMessageHistory, BaseMemory):
84
+ """In memory implementation of chat message history."""
85
+
86
+ messages: List[BaseMessage] = Field(default_factory=list)
87
+
88
+ def add_messages(self, messages: List[BaseMessage]) -> None:
89
+ """Add a list of messages to the store"""
90
+ self.messages.extend(messages)
91
+
92
+ def clear(self) -> None:
93
+ """Clear the message history"""
94
+ self.messages = []
95
+
96
+ @property
97
+ def memory_variables(self) -> List[str]:
98
+ """Return a list of memory variables."""
99
+ # This defines what variables the memory will return
100
+ return ["history"]
101
+
102
+ def load_memory_variables(self, inputs: dict) -> dict:
103
+ """Return the history messages as a string."""
104
+ # Convert the message history into a format suitable for the agent to use
105
+ history_str = "\n".join([message.content for message in self.messages])
106
+ return {"history": history_str}
107
+
108
+ def save_context(self, inputs: dict, outputs: dict) -> None:
109
+ """Save the context of the conversation."""
110
+ # Save input and output messages
111
+ user_message = inputs.get("input", None)
112
+ ai_message = outputs.get("output", None)
113
+
114
+ if user_message:
115
+ self.add_messages([HumanMessage(content=user_message)])
116
+ if ai_message:
117
+ self.add_messages([AIMessage(content=ai_message)])
118
+
119
+
120
+ # Here we use a global variable to store the chat message history.
121
+ # This will make it easier to inspect it to see the underlying results.
122
+ store = {}
123
+
124
+
125
+ def get_session_history(
126
+ user_id: str, conversation_id: str
127
+ ) -> BaseChatMessageHistory:
128
+ global store
129
+ if (user_id, conversation_id) not in store:
130
+ store[(user_id, conversation_id)] = InMemoryHistory()
131
+ return store[(user_id, conversation_id)]
132
+
133
+ history = get_session_history(str(Modules.USER_ID),str(Modules.CONVERSATION_ID))
134
+ history.add_message(AIMessage(content="hello"))
135
+
136
+
137
+ # creation of agent
138
+ agent_executor = create_sql_agent(
139
+ model,
140
+ db=db,
141
+ get_session_history=get_session_history,
142
+ agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
143
+ verbose=True,
144
+ return_intermediate_steps=True,
145
+ handle_parsing_errors=True, # Enable handling of parsing errors
146
+ prompt=custom_prompt,
147
+ history_factory_config=[
148
+ ConfigurableFieldSpec(
149
+ id="user_id",
150
+ annotation=str,
151
+ name="User ID",
152
+ description="Unique identifier for the user.",
153
+ default=str(Modules.USER_ID),
154
+ is_shared=True,
155
+ ),
156
+ ConfigurableFieldSpec(
157
+ id="conversation_id",
158
+ annotation=str,
159
+ name="Conversation ID",
160
+ description="Unique identifier for the conversation.",
161
+ default=str(Modules.CONVERSATION_ID),
162
+ is_shared=True,
163
+ ),
164
+ ],
165
+
166
+ #max_iterations=3,
167
+ )
168
+
169
+ agent_executor.memory = history
170
+ agent_executor.return_intermediate_steps=True
171
+
172
+
173
+ def incrementer_conversation_id() :
174
+ Modules.CONVERSATION_ID = Modules.CONVERSATION_ID + 1
175
+
176
+ def get_response(query):
177
+ """Fonction pour obtenir la réponse du modèle."""
178
+ global history
179
+ global agent_executor
180
+ if not query:
181
+ return "", history
182
+
183
+ result = agent_executor.invoke(
184
+ {"input": query},
185
+ config={"configurable": {"user_id": str(Modules.USER_ID), "conversation_id": str(Modules.CONVERSATION_ID)}}
186
+ )
187
+
188
+ return result, history
189
+
190
+ def clear_memory():
191
+ """Fonction pour réinitialiser la mémoire."""
192
+ global history
193
+ global agent_executor
194
+
195
+ incrementer_conversation_id()
196
+ history = get_session_history(str(Modules.USER_ID),str(Modules.CONVERSATION_ID))
197
+ agent_executor.memory = history
198
+
199
+
200
+ def Parser_log_action(log) :
201
+ # Utilisation de regex pour extraire les parties nécessaires
202
+ question_match = re.search(r'Question: (.+)', log)
203
+ thought_match = re.search(r'Thought: (.+)', log)
204
+ action_match = re.search(r'Action: (.+)', log)
205
+ action_input_match = re.search(r'Action Input: (.*)', log)
206
+
207
+ # Création du dictionnaire avec les résultats
208
+ parsed_log = {
209
+ 'Question': question_match.group(1) if question_match else None,
210
+ 'Thought': thought_match.group(1) if thought_match else None,
211
+ 'Action': action_match.group(1) if action_match else None,
212
+ 'Action Input': action_input_match.group(1) if action_input_match else None
213
+ }
214
+
215
+ # Affichage du dictionnaire
216
+ return parsed_log
217
+
218
+ def save_sql_query_input_output_steps(result_agent,filename=Modules.FILE_HISTORY) :
219
+ """Fonction pour enregistrer l'historique des requêtes sql dans un fichier, l'input, output et les étapes"""
220
+ # Accéder au résultat de la requête SQL
221
+ steps = result_agent['intermediate_steps']
222
+ input = result_agent['input']
223
+ output = result_agent['output']
224
+ logs =[]
225
+ for action, result in steps:
226
+ log=Parser_log_action(action.log)
227
+ log['Result'] = result
228
+ logs.append(log)
229
+ if action.tool == 'sql_db_query':
230
+ # Supprimer les retours à la ligne dans action.tool_input
231
+ sql_query = action.tool_input.replace('\n', '').replace('\r', '')
232
+ # Convertir la chaîne de caractères en une structure Python sécurisée
233
+ try:
234
+ # Utilisez json.loads si le résultat est au format JSON, sinon continuez avec ast.literal_eval
235
+ try:
236
+ result_list = json.loads(result)
237
+ except json.JSONDecodeError:
238
+ result_list = ast.literal_eval(result)
239
+
240
+ # Vérifier si result_list est une liste de tuples
241
+ if isinstance(result_list, list) and len(result_list) > 0 and isinstance(result_list[0], tuple):
242
+ # Extraire la première valeur (si c'est une liste de tuples, on prend le premier tuple et le premier élément)
243
+ sql_result = result_list[0][0]
244
+ else:
245
+ sql_result = str(result_list) # Ou une autre gestion si ce n'est pas une liste de tuples
246
+
247
+ except (SyntaxError, ValueError) as e:
248
+ # Gestion des erreurs lors de la conversion
249
+ print(f"Erreur lors de la conversion de la chaîne 'result': {e}")
250
+ sql_result = "Erreur lors de l'analyse du résultat SQL"
251
+
252
+ with open(filename, 'a', newline='', encoding='utf-8') as file:
253
+ writer = csv.writer(file)
254
+ # Enregistrer l'input SQL et le résultat dans le fichier CSV
255
+ writer.writerow([input, sql_query,sql_result, output, result_agent])
256
+
257
+ return logs
Modules/__init__.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Path to your Excel file and image
2
+
3
+ Task_Flow_Path = "Input/Task_Flow.xlsx"
4
+ Arrow_Down_Path = "Input/Arrow_Down.png"
5
+ Sql_Requests_Path ='Input/Sql_Requests.xlsx'
6
+ DATA_BASE = 'BD_Echantillon_2014.db'
7
+ SESSION_ID = '1'
8
+ USER_ID = 1
9
+ CONVERSATION_ID = 1
10
+ PARSED_LOGS =[]
11
+ MAX_ACTIONS = 20
12
+ FILE_HISTORY = "Output/history.csv"
Modules/__pycache__/Agent_HCP.cpython-312.pyc ADDED
Binary file (12.8 kB). View file
 
Modules/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (511 Bytes). View file
 
Output/history.csv ADDED
The diff for this file is too large to render. See raw diff
 
app.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from Modules import Agent_HCP
3
+ import Modules
4
+ import ast
5
+ import pandas as pd
6
+ import csv
7
+ import re
8
+
9
+
10
+ def chat_interface(query: str):
11
+ if not query:
12
+ return "", ""
13
+
14
+ result, memory = Agent_HCP.get_response(query)
15
+
16
+ # Formatage de l'historique pour affichage
17
+ formatted_history = ""
18
+ for message in memory.messages:
19
+ if message.type == "human":
20
+ formatted_history += (
21
+ f"<div style='text-align: right; margin: 10px 0; background-color: white; padding: 5px; border-radius: 5px; max-width: 60%; margin-left: auto;'>"
22
+ f"<strong>User:</strong> {message.content}</div>"
23
+ )
24
+ else:
25
+ formatted_history += (
26
+ f"<div style='text-align: left; margin: 10px 0; background-color: lightgray; padding: 5px; border-radius: 5px; max-width: 60%;'>"
27
+ f"<strong>ChatBot:</strong> {message.content}</div>"
28
+ )
29
+ Modules.PARSED_LOGS=Agent_HCP.save_sql_query_input_output_steps(result)
30
+
31
+ # Retourne l'historique formaté et la réponse
32
+ return formatted_history, ""
33
+
34
+ # Fonction pour réinitialiser l'historique
35
+ def clear_history():
36
+ Agent_HCP.clear_memory()
37
+ return "", ""
38
+
39
+
40
+ # Fonction pour colorer les lignes en alternance
41
+ def color_rows(val):
42
+ # Appliquer une couleur différente pour chaque ligne (alternée)
43
+ return ['background-color: #f0f0f0' if i % 2 == 0 else 'background-color: #ffffff' for i in range(len(val))]
44
+
45
+ # Fonction pour lire le CSV et afficher seulement deux colonnes du DataFrame
46
+ def display_dataframe():
47
+ # Lire le fichier CSV dans un DataFrame
48
+ df = pd.read_csv(Modules.FILE_HISTORY, header=None, names=['INPUT', 'SQL_QUERY', 'SQL_RESULT', 'OUTPUT', "STEPS"], quoting=csv.QUOTE_MINIMAL)
49
+ # Sélectionner seulement les colonnes 'INPUT', 'SQL_QUERY', 'SQL_RESULT', 'OUTPUT'
50
+ df_selected = df[['INPUT', 'SQL_QUERY', 'SQL_RESULT', 'OUTPUT']].sort_index(ascending=False)
51
+
52
+ # Appliquer le style au DataFrame
53
+ styled_df = df_selected.style.apply(color_rows, axis=0)
54
+ html_table = styled_df.to_html()
55
+
56
+ return html_table
57
+
58
+ def get_action_details(index):
59
+ log = Modules.PARSED_LOGS[index]
60
+ return (
61
+ f"<div style='color: #007BFF;'><strong>Action:</strong> {index+1}</div><br>"
62
+ f"<div style='color: #28A745;'><strong>Question:</strong> {log['Question']}</div><br>"
63
+ f"<div style='color: #FFC107;'><strong>Thought:</strong> {log['Thought']}</div><br>"
64
+ f"<div style='color: #17A2B8;'><strong>Action:</strong> {log['Action']}</div><br>"
65
+ f"<div style='color: #DC3545;'><strong>Action Input:</strong> {log['Action Input']}</div><br>"
66
+ f"<div style='color: #6C757D;'><strong>Result:</strong> {log['Result']}</div>"
67
+ )
68
+
69
+ # Fonction pour rafraîchir les données et créer les nouveaux boutons
70
+ def fn_action_buttons():
71
+ markdown_text = gr.Markdown(f"# Visualisation des actions de l'agent\n\nIl y a {len(Modules.PARSED_LOGS)} actions.")
72
+
73
+ # Vérifier s'il y a des logs à afficher
74
+ if len(Modules.PARSED_LOGS) > 0:
75
+ # Créer les boutons pour chaque action disponible
76
+ action_buttons = [gr.Button(f"Action {i + 1}", visible=True) for i in range(len(Modules.PARSED_LOGS))]
77
+ else:
78
+ # Si aucune action n'est disponible, on affiche un bouton placeholder caché
79
+ action_buttons = [gr.Button(visible=False)]
80
+
81
+ # Compléter avec des placeholders si nécessaire
82
+ while len(action_buttons) < Modules.MAX_ACTIONS:
83
+ action_buttons.append(gr.Button(visible=False)) # Ajouter des boutons cachés
84
+
85
+ return [markdown_text, *action_buttons]
86
+
87
+ # Interface Gradio
88
+ with gr.Blocks() as demo:
89
+ with gr.Tabs():
90
+ with gr.TabItem("Chat"):
91
+ with gr.Row():
92
+ with gr.Column(scale=1, min_width=200):
93
+ gr.Markdown("""
94
+ ### Description de l'outil :
95
+ - Posez vos questions sur les données de recensement de 2014 au Maroc.
96
+ - Cette base de données contient seulement 3.341.426 personnes.
97
+ - Pour avoir un résultat approximatif, il faut multiplier le résutat obtenu par 9,99999453089430
98
+ """)
99
+ with gr.Column(scale=4):
100
+ gr.Markdown("# Parlez avec les données de HCP")
101
+ chat_history = gr.HTML("")
102
+ user_input = gr.Textbox(placeholder="Enter text here…", label="Your input")
103
+ clear_btn = gr.Button("Clear History")
104
+ user_input.submit(chat_interface, inputs=user_input, outputs=[chat_history, user_input])
105
+ clear_btn.click(clear_history, outputs=[chat_history, user_input])
106
+ with gr.Row() :
107
+ # Ajout d'exemples
108
+ gr.Examples(
109
+ examples=["Combien y-a-t-il de personnes recensées ?", "Quel est le le nombre de femmes ?",\
110
+ "Combien de ménages sont dirigés par des femmes dans la province d'Al Hoceïma ?"],
111
+ inputs=user_input
112
+ )
113
+
114
+ with gr.TabItem("Evaluation"):
115
+ gr.Markdown("# SQL EVALUATION")
116
+ # Ajouter un tableau pour afficher le DataFrame dans cet onglet
117
+ refresh_button = gr.Button("Rafraîchir la table")
118
+ # Afficher le DataFrame
119
+ html_output = gr.HTML(display_dataframe())
120
+ # Rafraîchir les données à chaque clic sur le bouton
121
+ refresh_button.click(fn=display_dataframe, inputs=[], outputs=html_output)
122
+
123
+ # Fonction qui rafraîchit les données et retourne le texte Markdown mis à jour
124
+
125
+ with gr.TabItem("Suivi"):
126
+ # Affichage du nombre d'actions et bouton de rafraîchissement
127
+ info_text = gr.Markdown(f"# Visualisation des actions de l'agent\n\nIl y a {len(Modules.PARSED_LOGS)} actions.")
128
+ with gr.Row():
129
+ refresh_button = gr.Button("Rafraîchir les actions")
130
+
131
+ # Créer les boutons d'action initiaux
132
+ with gr.Row():
133
+ # Créer les boutons pour chaque action disponible
134
+ output_buttons = [gr.Button(f"Action {i + 1}", visible=False) for i in range(Modules.MAX_ACTIONS)]
135
+
136
+ # Zone pour afficher les détails de l'action sélectionnée
137
+ details_output = gr.Markdown("")
138
+
139
+ # Lier les boutons d'action à la fonction pour afficher les détails
140
+ for i, button in enumerate(output_buttons):
141
+ button.click(get_action_details, inputs=[gr.Number(i, visible=False)], outputs=details_output)
142
+
143
+ # Action du bouton de rafraîchissement
144
+ refresh_button.click(
145
+ fn_action_buttons, # Fonction appelée lors du clic
146
+ outputs=[info_text] + output_buttons # Mise à jour des éléments Markdown et boutons
147
+ )
148
+
149
+ demo.launch(share=False)
150
+ #demo.launch(share=True, auth=("username", "password"))
requirements.txt ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ aiohappyeyeballs==2.4.0
3
+ aiohttp==3.10.5
4
+ aiosignal==1.3.1
5
+ annotated-types==0.7.0
6
+ anyio==4.4.0
7
+ asttokens==2.4.1
8
+ attrs==24.2.0
9
+ certifi==2024.8.30
10
+ charset-normalizer==3.3.2
11
+ click==8.1.7
12
+ colorama==0.4.6
13
+ comm==0.2.2
14
+ contourpy==1.3.0
15
+ cycler==0.12.1
16
+ dataclasses-json==0.6.7
17
+ debugpy==1.8.5
18
+ decorator==5.1.1
19
+ distro==1.9.0
20
+ executing==2.1.0
21
+ fastapi==0.115.0
22
+ ffmpy==0.4.0
23
+ filelock==3.16.1
24
+ fonttools==4.53.1
25
+ frozenlist==1.4.1
26
+ fsspec==2024.9.0
27
+ gradio==4.44.0
28
+ gradio_client==1.3.0
29
+ greenlet==3.1.0
30
+ groq==0.11.0
31
+ h11==0.14.0
32
+ httpcore==1.0.5
33
+ httpx==0.27.2
34
+ huggingface-hub==0.25.0
35
+ idna==3.10
36
+ importlib_resources==6.4.5
37
+ ipykernel==6.29.5
38
+ ipython==8.27.0
39
+ jedi==0.19.1
40
+ Jinja2==3.1.4
41
+ jsonpatch==1.33
42
+ jsonpointer==3.0.0
43
+ jupyter_client==8.6.3
44
+ jupyter_core==5.7.2
45
+ kiwisolver==1.4.7
46
+ langchain==0.3.0
47
+ langchain-community==0.3.0
48
+ langchain-core==0.3.1
49
+ langchain-groq==0.2.0
50
+ langchain-text-splitters==0.3.0
51
+ langsmith==0.1.121
52
+ markdown-it-py==3.0.0
53
+ MarkupSafe==2.1.5
54
+ marshmallow==3.22.0
55
+ matplotlib==3.9.2
56
+ matplotlib-inline==0.1.7
57
+ mdurl==0.1.2
58
+ multidict==6.1.0
59
+ mypy-extensions==1.0.0
60
+ nest-asyncio==1.6.0
61
+ numpy==1.26.4
62
+ orjson==3.10.7
63
+ packaging==24.1
64
+ pandas==2.2.2
65
+ parso==0.8.4
66
+ pillow==10.4.0
67
+ platformdirs==4.3.6
68
+ prompt_toolkit==3.0.47
69
+ psutil==6.0.0
70
+ pure_eval==0.2.3
71
+ pydantic==2.9.2
72
+ pydantic-settings==2.5.2
73
+ pydantic_core==2.23.4
74
+ pydub==0.25.1
75
+ Pygments==2.18.0
76
+ pyparsing==3.1.4
77
+ python-dateutil==2.9.0.post0
78
+ python-dotenv==1.0.1
79
+ python-multipart==0.0.9
80
+ pytz==2024.2
81
+ pywin32==306
82
+ PyYAML==6.0.2
83
+ pyzmq==26.2.0
84
+ requests==2.32.3
85
+ rich==13.8.1
86
+ ruff==0.6.5
87
+ semantic-version==2.10.0
88
+ shellingham==1.5.4
89
+ six==1.16.0
90
+ sniffio==1.3.1
91
+ SQLAlchemy==2.0.35
92
+ stack-data==0.6.3
93
+ starlette==0.38.5
94
+ tenacity==8.5.0
95
+ tomlkit==0.12.0
96
+ tornado==6.4.1
97
+ tqdm==4.66.5
98
+ traitlets==5.14.3
99
+ typer==0.12.5
100
+ typing-inspect==0.9.0
101
+ typing_extensions==4.12.2
102
+ tzdata==2024.1
103
+ urllib3==2.2.3
104
+ uvicorn==0.30.6
105
+ wcwidth==0.2.13
106
+ websockets==12.0
107
+ yarl==1.11.1