Ludovicollin commited on
Commit
4ef80f3
·
1 Parent(s): b9ac1c9

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +399 -0
main.py ADDED
@@ -0,0 +1,399 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ from operator import itemgetter
4
+ from collections import Counter
5
+ from langchain.schema.runnable import Runnable, RunnablePassthrough, RunnableLambda
6
+ from langchain.schema.runnable.config import RunnableConfig
7
+ from langchain.embeddings import HuggingFaceEmbeddings
8
+ from langchain.chains import ConversationalRetrievalChain
9
+ from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
10
+ from langchain.chains import LLMChain
11
+ from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
12
+ from langchain.schema import StrOutputParser
13
+ from langchain.chains.conversational_retrieval.prompts import CONDENSE_QUESTION_PROMPT
14
+ from langchain.chains.question_answering import load_qa_chain
15
+ from langchain.chains.qa_with_sources import load_qa_with_sources_chain
16
+ from langchain.vectorstores import Pinecone
17
+ import pinecone
18
+ from langchain.memory import ChatMessageHistory, ConversationBufferMemory
19
+ import pandas as pd
20
+ import numpy as np
21
+ from anthropic import Anthropic, HUMAN_PROMPT, AI_PROMPT
22
+ from langchain.chat_models import ChatAnthropic
23
+ import chainlit as cl
24
+ from chainlit.input_widget import Select, TextInput
25
+ from chainlit import user_session
26
+ from offres_emploi import Api
27
+ from offres_emploi.utils import dt_to_str_iso
28
+ import datetime
29
+
30
+ @cl.author_rename
31
+ def rename(orig_author: str):
32
+ rename_dict = {"ConversationalRetrievalChain": "💬 Assistant conversationnel", "Retriever": "Agent conversationnel", "StuffDocumentsChain": "Chaîne de documents", "LLMChain": "Agent", "ChatAnthropic": "🤖 IA"}
33
+ return rename_dict.get(orig_author, orig_author)
34
+
35
+ @cl.action_callback("download")
36
+ async def on_action(action):
37
+ content = []
38
+ content.append(action.value)
39
+ arrayContent = np.array(content)
40
+ df = pd.DataFrame(arrayContent)
41
+ with open('.chainlit/' + action.description + '.txt', 'wb') as csv_file:
42
+ df.to_csv(path_or_buf=csv_file, index=False,header=False, encoding='utf-8')
43
+ elements = [
44
+ cl.File(
45
+ name= action.description + ".txt",
46
+ path="./.chainlit/" + action.description + ".txt",
47
+ display="inline",
48
+ ),
49
+ ]
50
+ await cl.Message(
51
+ author="🌐🌐🌐", content="[Lien] 🔗", elements=elements
52
+ ).send()
53
+ await action.remove()
54
+
55
+ @cl.action_callback("close_button")
56
+ async def on_action(action):
57
+ time.sleep(0.5)
58
+ track = user_session.get("tracker")
59
+ await track.remove()
60
+
61
+ @cl.action_callback("action_button")
62
+ async def on_action(action):
63
+ task_list = cl.TaskList()
64
+ # Create the TaskList
65
+ # Create a task and put it in the running state
66
+ task1 = cl.Task(title="Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data Processing data \n\n Processing data", status=cl.TaskStatus.READY)
67
+ await task_list.add_task(task1)
68
+ task2 = cl.Task(title=action.value, status=cl.TaskStatus.READY)
69
+ await task_list.add_task(task2)
70
+ # Perform some action on your end
71
+ await task_list.send()
72
+ tracking = user_session.set("tracker", task_list)
73
+
74
+ others = [
75
+ cl.Action(name="close_button", value="closed", label="Fermer", description="Fermer le volet d'information!")
76
+ ]
77
+ await cl.Message(author="🌐🌐🌐",content="Fermer le panneau d'information", actions=others).send()
78
+
79
+ @cl.cache
80
+ def to_cache(file):
81
+ #time.sleep(5) # Simulate a time-consuming process
82
+ return "https://cipen.univ-gustave-eiffel.fr/fileadmin/CIPEN/datas/assets/docs/" + file + ".csv"
83
+
84
+
85
+ @cl.set_chat_profiles
86
+ async def chat_profile():
87
+ return [
88
+ cl.ChatProfile(name="Note composante sectorielle - NCS",markdown_description="Note composante sectorielle",icon="./public/favicon.png",),
89
+ #cl.ChatProfile(name="Fiche synoptique - FCS",markdown_description="Fiche synoptique",icon="./public/favicon.png",),
90
+ #cl.ChatProfile(name="Fiche activité - FCA",markdown_description="Fiche activité",icon="./public/favicon.png",),
91
+ #cl.ChatProfile(name="Fiche compétence - FCC",markdown_description="Fiche compétence",icon="./public/favicon.png",),
92
+ #cl.ChatProfile(name="Module de formation - cours - MDF",markdown_description="Module de formation - cours",icon="./public/favicon.png",),
93
+ #cl.ChatProfile(name="Référentiel d'évaluation - REV",markdown_description="Référentiel d'évaluation",icon="./public/favicon.png",),
94
+ #cl.ChatProfile(name="Matrice de cohérences - MDC",markdown_description="Matrice de cohérences",icon="./public/favicon.png",),
95
+ ]
96
+ @cl.on_chat_start
97
+ async def start():
98
+ chat_profile = cl.user_session.get("chat_profile")
99
+ chatProfile = chat_profile.split(' - ')
100
+
101
+ if chatProfile[1] == 'NCS':
102
+ connexion = cl.TaskList()
103
+ connexion.status = "Running..."
104
+
105
+ # Create a task and put it in the running state
106
+ task1 = cl.Task(title="Chargement des données, en attente...", status=cl.TaskStatus.RUNNING)
107
+ await connexion.add_task(task1)
108
+ await connexion.send()
109
+
110
+
111
+ logo = [
112
+ cl.Image(name="Logo", size="small", display="inline", path="./public/logo_light.png")
113
+ ]
114
+
115
+ await cl.Message(author="🌐🌐🌐",content="", elements=logo).send()
116
+ settings = await cl.ChatSettings(
117
+ [
118
+ Select(
119
+ id="rome",
120
+ label="Codes Rome",
121
+ values=["", "M1604,K1204,K1204,M1302,M1605 - DU entrepreneuriat", "M1502,M1503 - LP GORH", "K1902 - LP MDAI"],
122
+ initial_index=0,
123
+ ),
124
+ Select(
125
+ id="type",
126
+ label="Type de fiche",
127
+ values=["", "Note de composante sectorielle - NCS", "Fiche synoptique - FCS", "Fiche activité - FCA", "Fiche compétence - FCC", "Module de formation - cours - MDF", "Référentiel d'évaluation - REV", "Matrice de cohérences - MDC"],
128
+ initial_index=0,
129
+ ),
130
+ ]
131
+ ).send()
132
+ value = settings["rome"]
133
+ task1.status = cl.TaskStatus.DONE
134
+ await cl.sleep(0.5)
135
+ await connexion.remove()
136
+
137
+ if len(value) < 1:
138
+ await cl.Message(author="🌐🌐🌐",content="⚠️ Aucun contexte fixé!\nAussi, vous ne pourrez pas élaborer de document de la chaîne documentaire APCC!").send()
139
+ warning = [
140
+ cl.Image(name="Warning", size="medium", display="inline", path="./public/warning.png")
141
+ ]
142
+ await cl.Message(author="🌐🌐🌐",content="1️⃣ Cliquez sur le bouton dont l'image suit, dans le prompt, pour commencer à élaborer un premier texte de la chaîne documentaire APCC!").send()
143
+ await cl.Message(author="🌐🌐🌐",content="", elements=warning).send()
144
+ await cl.Message(author="🌐🌐🌐",content="2️⃣ Puis sélectionnez un code ROME et un type de fiche dans les menus déroulants proposés. Et vous êtes prêt!").send()
145
+ elif chatProfile[1] == 'FCS':
146
+ poleemploi = cl.TaskList()
147
+ poleemploi.status = "Running..."
148
+
149
+ # Create a task and put it in the running state
150
+ task1 = cl.Task(title="Chargement des données du marché de l'emploi, en attente...", status=cl.TaskStatus.RUNNING)
151
+ await poleemploi.add_task(task1)
152
+ await poleemploi.send()
153
+ logo = [
154
+ cl.Image(name="Logo", size="small", display="inline", path="./public/logo_light.png")
155
+ ]
156
+
157
+ await cl.Message(author="🌐🌐🌐",content="", elements=logo).send()
158
+ #file = to_cache(chatProfile[0])
159
+ await cl.Message(author="🌐🌐🌐",content=f"💻😊 Vous pouvez rechercher des \"{chat_profile}\"!").send()
160
+ await cl.Message(
161
+ author="🌐🌐🌐",content=f"💡Voici des exemples de requête \n\t1️⃣ Basée sur un code ROME : M1403\n\t2️⃣ Basée sur une appellation métier : Coach sportif"
162
+ ).send()
163
+ task1.status = cl.TaskStatus.DONE
164
+ await cl.sleep(0.5)
165
+ await poleemploi.remove()
166
+ cl.user_session.set("memory", ConversationBufferMemory(return_messages=True))
167
+ memory = cl.user_session.get("memory")
168
+ cl.user_session.set("runnable", memory)
169
+ else:
170
+ emploi = cl.TaskList()
171
+ emploi.status = "Running..."
172
+
173
+ # Create a task and put it in the running state
174
+ task1 = cl.Task(title="Chargement des données du marché de l'emploi, en attente...", status=cl.TaskStatus.RUNNING)
175
+ await emploi.add_task(task1)
176
+ await emploi.send()
177
+ logo = [
178
+ cl.Image(name="Logo", size="small", display="inline", path="./public/logo_light.png")
179
+ ]
180
+
181
+ await cl.Message(author="🌐🌐🌐",content="", elements=logo).send()
182
+ file = to_cache(chatProfile[0])
183
+ await cl.Message(author="🌐🌐🌐",content=f"💻😊 Vous pouvez poser vos questions concernant le marché de l'emploi de \"{chat_profile}\"!").send()
184
+ await cl.Message(author="🌐🌐🌐",content=f"📈 Le marché de l'emploi se présente comme un gros tableau structuré comme suit :\n1. Emplois\n2. Type de contrat\n3. Expérience\n4. Compétences professionnelles\n5. Salaire\n6. Qualification\n7. Localisation").send()
185
+ await cl.Message(
186
+ author="🌐🌐🌐",content=f"💡Voici des exemples de question \n\t1️⃣ Peux-tu créer une liste de 5 emplois différents les plus listés ?\n\t2️⃣ Peux-tu créer une liste de 5 emplois différents les plus listés avec leur salaire moyen correspondant à chacun de ces emplois?\n\t3️⃣ Peux-tu créer une liste de 5 emplois différents les plus listés et leur répartition dans les localisations suivantes, le 75, ou le 77, ou le 78, ou le 91, ou le 92, ou le 93, ou le 94, ou le 95?\n\t4️⃣ Peux-tu créer une liste de 5 emplois différents les plus listés pour un niveau de qualification Bac+2 Bac+3?\n\t5️⃣ Peux-tu créer une liste de 5 emplois différents les plus listés et associer 2 compétences professionnelles à chaque emploi, de type activités professionnelles, sans lister les compétences transversales?\n\t6️⃣ Peux-tu créer une liste de 5 emplois différents les plus listés avec un contrat en CDI?\n\t7️⃣ Quelles sont les compétences professionnelles les mieux payées?"
187
+ ).send()
188
+ model = ChatAnthropic(model="claude-2.1",top_p=0.9,temperature=1,max_tokens_to_sample=4097,streaming=True)
189
+ df = pd.read_csv(file, sep=",")
190
+ df = df.replace(np.nan, '', regex=True)
191
+ df['combined'] = 'Emploi ' + df['Poste'] + '; type de contrat : ' + df['Contrat'] + '; Compétences professionnelles : ' + df['Savoir'] + '; Salaire : ' + df['Salaire'] + '; Niveau de qualification : ' + df['Niveau'] + '; Localisation : ' + df['Localisation']
192
+
193
+ context = []
194
+ for i, row in df.iterrows():
195
+ context.append(row['combined'])
196
+
197
+ context = "\n".join(context)
198
+ context = context[0:590000]
199
+ task1.status = cl.TaskStatus.DONE
200
+ await cl.sleep(5)
201
+ await emploi.remove()
202
+ cl.user_session.set("memory", ConversationBufferMemory(return_messages=True))
203
+ memory = cl.user_session.get("memory")
204
+ prompt = ChatPromptTemplate.from_messages(
205
+ [
206
+ (
207
+ "system",
208
+ f"Contexte : Vous êtes un spécialiste du marché de l'emploi en fonction du niveau de qualification, des compétences professionnelles, des compétences transversales, du salaire et de l'expérience. Vous êtes doué pour faire des analyses sur les métiers les plus demandés grâce à votre aptitude à synthétiser les informations en fonction des critères définis ci-avant. En fonction des informations suivantes et du contexte suivant seulement et strictement. En fonction des informations suivantes et du contexte suivant seulement et strictement. Contexte et document : {context}. Réponds en langue française strictement à la question suivante en respectant strictement les données du document. Si vous ne pouvez pas répondre à la question sur la base des informations, dites que vous ne trouvez pas de réponse ou que vous ne parvenez pas à trouver de réponse. Essayez donc de comprendre en profondeur le contexte et répondez uniquement en vous basant sur les informations fournies. Ne générez pas de réponses non pertinentes.",
209
+ ),
210
+ MessagesPlaceholder(variable_name="history"),
211
+ ("human", "{question}, d'après le document en vous réferrant strictement aux données du contexte fixé sans faire de recherche dans vos connaissances ou sur le web? Si les emplois sont différents aux données, recommencez votre liste. Réponse sous forme d'une liste. Si tu ne peux pas donner la liste, fais une projection par emplois."),
212
+ ]
213
+ )
214
+ #runnable = prompt | model | StrOutputParser()
215
+ runnable = (
216
+ RunnablePassthrough.assign(
217
+ history=RunnableLambda(memory.load_memory_variables) | itemgetter("history")
218
+ )
219
+ | prompt
220
+ | model
221
+ | StrOutputParser()
222
+ )
223
+ cl.user_session.set("runnable", runnable)
224
+
225
+ @cl.on_settings_update
226
+ async def setup_agent(settings):
227
+ print(settings)
228
+ if not settings['rome'] and not settings['type']:
229
+ await cl.Message(
230
+ author="🌐🌐🌐",content=f"⚠️ Pas de contexte : {settings['rome']}\n⚠️ Pas de type de fiche : {settings['type']}\n⛔ Vous ne pouvez pas élaborer de fiche!"
231
+ ).send()
232
+ elif settings['rome'] and not settings['type']:
233
+ await cl.Message(
234
+ author="🌐🌐🌐",content=f"👍 Changement de contexte : {settings['rome']}\n⚠️ Pas de type de fiche : {settings['type']}\n⛔ Vous ne pouvez pas élaborer de fiche!"
235
+ ).send()
236
+ elif not settings['rome'] and settings['type']:
237
+ await cl.Message(
238
+ author="🌐🌐🌐",content=f"⚠️ Pas de contexte : {settings['rome']}\n👍 Type de fiche : {settings['type']}\n⛔ Vous ne pouvez pas élaborer de fiche!"
239
+ ).send()
240
+ else:
241
+ await cl.Message(
242
+ author="🌐🌐🌐",content=f"👍 Changement de contexte : {settings['rome']}\n👍 Type de fiche : {settings['type']}"
243
+ ).send()
244
+
245
+
246
+
247
+
248
+
249
+ os.environ['ANTHROPIC_API_KEY'] = os.environ['ANTHROPIC_API_KEY']
250
+ model = ChatAnthropic(
251
+ streaming=True,
252
+ temperature=1,
253
+ max_tokens=4000
254
+ )
255
+ cl.user_session.set("memory", ConversationBufferMemory(return_messages=True))
256
+ memory = cl.user_session.get("memory")
257
+ prompt = ChatPromptTemplate.from_messages(
258
+ [
259
+ (
260
+ "system",
261
+ "Contexte : Vous êtes un spécialiste des formations, des compétences et des débouchés professionnels de l'enseignement supérieur en fonction du niveau d'études, des capacités, des compétences professionnelles, des compétences transversales ou soft skills. Vous êtes doué pour faire des analyses sur les formations grâce à votre aptitude à synthétiser les informations en fonction des critères définis ci-avant. En fonction des informations suivantes et du contexte suivant seulement et strictement. En fonction des informations suivantes et du contexte suivant seulement et strictement. Contexte et document : {context}. Réponds à la question suivante de la manière la plus pertinente, la plus exhaustive et la plus détaillée possible, avec au minimum 3000 tokens jusqu'à 4000 tokens, seulement et strictement dans le contexte et les informations fournies. Essayez donc de comprendre en profondeur le contexte et répondez uniquement en vous basant sur les informations fournies.",
262
+ ),
263
+ MessagesPlaceholder(variable_name="history"),
264
+ ("human", "{question}, dans le contexte fourni."),
265
+ ]
266
+ )
267
+ runnable = (
268
+ RunnablePassthrough.assign(
269
+ history=RunnableLambda(memory.load_memory_variables) | itemgetter("history")
270
+ )
271
+ | prompt
272
+ | model
273
+ | StrOutputParser()
274
+ )
275
+ cl.user_session.set("runnable", runnable)
276
+
277
+ @cl.on_message
278
+ async def main(message: cl.Message):
279
+ chat_profile = cl.user_session.get("chat_profile")
280
+ chatProfile = chat_profile.split(' - ')
281
+ if chatProfile[0] == "OF":
282
+ pineconeRetriever = cl.TaskList()
283
+ pineconeRetriever.status = "Etablissement de la chaîne documentaire..."
284
+
285
+ # Create a task and put it in the running state
286
+ task1 = cl.Task(title="Connexion à la base documentaire, en attente...", status=cl.TaskStatus.RUNNING)
287
+ await pineconeRetriever.add_task(task1)
288
+ await pineconeRetriever.send()
289
+
290
+ index_name = os.environ['PINECONE_INDEX_NAME']
291
+ pinecone.init(
292
+ api_key=os.environ['PINECONE_API_KEY'],
293
+ environment=os.environ['PINECONE_ENVIRONMENT']
294
+ )
295
+ embeddings = HuggingFaceEmbeddings()
296
+ task1.status = cl.TaskStatus.DONE
297
+ task2 = cl.Task(title="Recherche par cosine similarity, en attente...", status=cl.TaskStatus.RUNNING)
298
+ await pineconeRetriever.add_task(task2)
299
+ await pineconeRetriever.send()
300
+ docsearch = Pinecone.from_existing_index(index_name, embeddings)
301
+ retrieve = docsearch.similarity_search(message.content, k=40, filter={'categorie': {'$eq': 'OF'}})
302
+ task2.status = cl.TaskStatus.DONE
303
+ task3 = cl.Task(title="Création du contexte documentaire, en attente...", status=cl.TaskStatus.RUNNING)
304
+ await pineconeRetriever.add_task(task3)
305
+ await pineconeRetriever.send()
306
+ context = ''
307
+ metadatas = ''
308
+ text_elements = []
309
+ for i in range(0,len(retrieve)):
310
+ numSource = i + 1
311
+ source_name = f"Source n°{numSource}"
312
+ text_elements.append(
313
+ cl.Text(content="Codes ROME : " + retrieve[i].metadata["CODES_ROME"] + "\n" + retrieve[i].metadata["LIBELLES_ROME"] + "\n\n" + retrieve[i].page_content, name=source_name)
314
+ )
315
+ context += '\n' + retrieve[i].page_content
316
+ task3.status = cl.TaskStatus.DONE
317
+ await cl.sleep(20)
318
+ await pineconeRetriever.remove()
319
+ memory = cl.user_session.get("memory")
320
+ runnable = cl.user_session.get("runnable") # type: Runnable
321
+ msg = cl.Message(author="🌐🌐🌐",content="")
322
+ async for chunk in runnable.astream(
323
+ {"context":context,"question": message.content},
324
+ config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
325
+ ):
326
+ await msg.stream_token(chunk)
327
+ await msg.send()
328
+ source_names = [text_el.name for countMetadata, text_el in enumerate(text_elements) if countMetadata < 10]
329
+ if source_names:
330
+ metadatas += ', '.join(source_names)
331
+ else:
332
+ metadatas += "\n\nPas de source trouvée!"
333
+
334
+ if metadatas:
335
+ await cl.Message(author="🌐🌐🌐",content="Sources : " + metadatas, elements=text_elements).send()
336
+
337
+ actions = [
338
+ cl.Action(name="download", value="Question : " + message.content + "\n\nRéponse : " + msg.content, description="download_offre_formation")
339
+ ]
340
+ await cl.Message(author="🌐🌐🌐",content="Download", actions=actions).send()
341
+ memory.chat_memory.add_user_message(message.content)
342
+ memory.chat_memory.add_ai_message(msg.content)
343
+ elif chatProfile[0] == "Emplois":
344
+ client = Api(client_id=os.environ['POLE_EMPLOI_CLIENT_ID'],
345
+ client_secret=os.environ['POLE_EMPLOI_CLIENT_SECRET'])
346
+ runnable = cl.user_session.get("runnable")
347
+ memory = cl.user_session.get("memory")
348
+ msg = cl.Message(author="🌐🌐🌐",content="")
349
+ todayDate = datetime.datetime.today()
350
+ month, year = (todayDate.month-1, todayDate.year) if todayDate.month != 1 else (12, todayDate.year-1)
351
+ start_dt = todayDate.replace(day=1, month=month, year=year)
352
+
353
+ end_dt = datetime.datetime.today()
354
+
355
+ params = {"motsCles": message.content,'lieux':'75D','minCreationDate': dt_to_str_iso(start_dt),'maxCreationDate': dt_to_str_iso(end_dt),'range':'0-149'}
356
+ search_on_big_data = client.search(params=params)
357
+ results = search_on_big_data["resultats"]
358
+ emplois = []
359
+ text_elements = []
360
+ for i in range(0,len(results)):
361
+ emplois.append("✔️ Emploi : " + results[i]['intitule'] + "\nCode ROME : " + results[i]['romeCode'] + "\nLien vers Pôle Emploi : https://candidat.pole-emploi.fr/offres/recherche/detail/" + results[i]['id'] + "\n\nDescription : " + results[i]['description'] + "\n\n")
362
+ emplois_list = ''.join(emplois)
363
+ await msg.stream_token(emplois_list)
364
+ await msg.send()
365
+ listEmplois_name = f"Liste des emplois"
366
+ text_elements.append(
367
+ cl.Text(content="Question : " + message.content + "\n\nRéponse :\n" + msg.content, name=listEmplois_name)
368
+ )
369
+ actions = [
370
+ cl.Action(name="download", value="Question : " + message.content + "\n\nRéponse : " + msg.content, description="download_emplois")
371
+ ]
372
+ await cl.Message(author="🌐🌐🌐",content="Download", actions=actions).send()
373
+ await cl.Message(author="🌐🌐🌐",content="Source Pôle Emploi : " + listEmplois_name, elements=text_elements).send()
374
+
375
+ memory.chat_memory.add_user_message(message.content)
376
+ memory.chat_memory.add_ai_message(msg.content)
377
+
378
+ else:
379
+ memory = cl.user_session.get("memory")
380
+ runnable = cl.user_session.get("runnable") # type: Runnable
381
+ msg = cl.Message(author="🌐🌐🌐",content="")
382
+ text_elements = []
383
+ async for chunk in runnable.astream(
384
+ {"question": message.content},
385
+ config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
386
+ ):
387
+ await msg.stream_token(chunk)
388
+ await msg.send()
389
+ QA_Emplois_name = f"Question-réponse sur les emplois"
390
+ text_elements.append(
391
+ cl.Text(content="Question : " + message.content + "\n\nRéponse :\n" + msg.content, name=QA_Emplois_name)
392
+ )
393
+ actions = [
394
+ cl.Action(name="download", value="Question : " + message.content + "\n\nRéponse : " + msg.content, description="download_QA_emplois")
395
+ ]
396
+ await cl.Message(author="🌐🌐🌐",content="Download", actions=actions).send()
397
+ await cl.Message(author="🌐🌐🌐",content="Marché Emploi : " + QA_Emplois_name, elements=text_elements).send()
398
+ memory.chat_memory.add_user_message(message.content)
399
+ memory.chat_memory.add_ai_message(msg.content)