datacipen commited on
Commit
f9c20f7
·
verified ·
1 Parent(s): ddca6df

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +189 -33
main.py CHANGED
@@ -1,12 +1,14 @@
1
  import json
2
  import os
3
  import time
 
 
4
  from pathlib import Path
5
  import chainlit as cl
6
- from azure.ai.inference import ChatCompletionsClient
7
- from azure.ai.inference.models import SystemMessage, UserMessage
8
- from azure.core.credentials import AzureKeyCredential
9
-
10
  os.environ["GITHUB_TOKEN"] = os.environ["GITHUB_TOKEN"]
11
 
12
  @cl.step(type="tool", show_input=True)
@@ -50,40 +52,92 @@ def Chargement_des_datas_web(profile):
50
  fileOpen.close()
51
  return txt
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  @cl.step(type="llm", show_input=True)
54
  def Connexion_Mistral():
55
- return ChatCompletionsClient(
56
- endpoint="https://models.inference.ai.azure.com",
57
- credential=AzureKeyCredential(os.environ["GITHUB_TOKEN"]),
58
- )
59
 
60
  @cl.step(type="tool", show_input=True)
61
  def Generation_reponse(client, data, question):
62
- return client.complete(
63
- stream=True,
64
  messages=[
65
  SystemMessage(content="Tu es un spécialiste de l'enseignement supérieur, des formations et de la pédagogie. Tu es en capacité d'analyser en profondeur les séances pédagogiques et de les mettre en adéquation avec les théories de la recherche en éducation. Répondez à la question seulement et exclusivement à partir du contexte et des définitions ci-contre, de la manière la plus pertinente, seulement en fonction des informations fournies. Contexte : " + str(data) + ". Définition : les formations MIPI (Management de l'Innovation et du Patrimoine Immobilier) concernent le secteur de l'immobilier : facility management, property management, asset management. Les formations MITIC (Management de l'Innovation des Technologies de l'Information et de la Communication) concernent le secteur du numérique : management de projet, innovation et conseil, support numérique aux métiers"),
66
  UserMessage(content=question + "Donne le résultat au format texte markdown, jusqu'à 3000 caractères convertis en UTF-8. Continue la réponse en citant, dans un paragraphe supplémentaire de 3 lignes, introduit un saut de ligne et par \"\n📚 Sources : \", les 3 verbatim, jusqu'à 100 caractères pour chaque verbatim, avec leur numéro de ligne respectif, qui ont permis de générer la réponse, à partir du contexte. Termine la réponse en créant, dans un dernier paragraphe d'une seule et unique ligne, introduite par un saut de ligne et par \"\n📣 Question en relation avec le sujet : \", 1 seule et unique question en relation avec la question posée, en commençant la ligne par \"Question relative au contexte :\"."),
67
  ],
68
- model="Phi-3.5-MoE-instruct",
69
- presence_penalty=0.1,
70
- frequency_penalty=0.8,
71
  max_tokens=1024,
72
- stop=["<|endoftext|>"],
73
- temperature=0,
74
- top_p=1,
75
- model_extras={
76
- "logprobs": True
77
- }
78
- )
 
 
 
 
 
 
 
 
 
79
  @cl.step(type="tool", show_input=True)
80
  async def Affichage_reponse(response):
81
  msg = cl.Message(author="COPILOT",content="")
82
 
83
  for update in response:
84
- if update.choices:
85
  time.sleep(0.125)
86
- await msg.stream_token(update.choices[0].delta.content.replace('Ã','é').replace('©','').replace('Ã','è').replace('¨','').replace('â','\'').replace('€','').replace('™','').replace('Å','oe').replace('“','').replace('®','î').replace('´','ô').replace('<','').replace('>','').replace('/',''))
87
 
88
  await msg.send()
89
  return msg
@@ -133,16 +187,33 @@ async def on_action(action):
133
  async def on_action(action):
134
  client = cl.user_session.get("client")
135
  data = Chargement_des_datas_web(cl.user_session.get("chat_profile"))
136
- data = data[0:6975]
 
 
 
137
  question = action.value
138
 
139
- response = Generation_reponse(client, data, question)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  msg = await Affichage_reponse(response)
142
 
143
- answer = msg.content
144
 
145
- await Affichage_question_contexte(answer, question)
146
 
147
 
148
  @cl.set_chat_profiles
@@ -302,6 +373,60 @@ async def chat_profile():
302
  )
303
  ]
304
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  ]
306
 
307
  @cl.on_chat_start
@@ -311,17 +436,48 @@ async def on_chat_start():
311
 
312
  @cl.on_message
313
  async def main(message: cl.Message):
314
- data = Chargement_des_datas(cl.user_session.get("chat_profile"))
315
- cl.user_session.set("data", data)
316
- client = cl.user_session.get("client")
 
317
 
318
- response = Generation_reponse(client, data, message.content)
319
 
320
- msg = await Affichage_reponse(response)
321
 
322
- answer = msg.content
323
- await Affichage_question_contexte(answer, message.content)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
 
 
 
 
 
 
 
 
325
  @cl.on_stop
326
  def on_stop():
327
  print("L'utilisateur veut arrêter la completion en cours!")
 
1
  import json
2
  import os
3
  import time
4
+ import datetime
5
+ import pandas as pd
6
  from pathlib import Path
7
  import chainlit as cl
8
+ from mistralai.client import MistralClient
9
+ from mistralai import Mistral, UserMessage, SystemMessage
10
+ from offres_emploi import Api
11
+ from offres_emploi.utils import dt_to_str_iso
12
  os.environ["GITHUB_TOKEN"] = os.environ["GITHUB_TOKEN"]
13
 
14
  @cl.step(type="tool", show_input=True)
 
52
  fileOpen.close()
53
  return txt
54
 
55
+ def connexion_France_Travail():
56
+ client = Api(client_id=os.getenv('POLE_EMPLOI_CLIENT_ID'),
57
+ client_secret=os.getenv('POLE_EMPLOI_CLIENT_SECRET'))
58
+ return client
59
+
60
+ def API_France_Travail_ROME(romeListArray):
61
+ client = connexion_France_Travail()
62
+ todayDate = datetime.datetime.today()
63
+ month, year = (todayDate.month-1, todayDate.year) if todayDate.month != 1 else (12, todayDate.year-1)
64
+ start_dt = todayDate.replace(day=1, month=month, year=year)
65
+ end_dt = datetime.datetime.today()
66
+ results = []
67
+ romeList = []
68
+ if romeListArray.find('-') != -1:
69
+ romeList = romeListArray.split('-')
70
+ else:
71
+ romeList.append(romeListArray)
72
+ for k in romeList:
73
+ k = k.lstrip()
74
+ k = k.rstrip()
75
+ params = {"motsCles": k.replace('/', '').replace('-', '').replace(',', '').replace(' ', ','),'minCreationDate': dt_to_str_iso(start_dt),'maxCreationDate': dt_to_str_iso(end_dt),'range':'0-149'}
76
+ try:
77
+ search_on_big_data = client.search(params=params)
78
+ results += search_on_big_data["resultats"]
79
+ except:
80
+ print("Il n'y a pas d'offres d'emploi.")
81
+
82
+ results_df = pd.DataFrame(results)
83
+ return results_df
84
+
85
+ def API_France_Travail_Metier(metier):
86
+ client = connexion_France_Travail()
87
+ todayDate = datetime.datetime.today()
88
+ month, year = (todayDate.month-1, todayDate.year) if todayDate.month != 1 else (12, todayDate.year-1)
89
+ start_dt = todayDate.replace(day=1, month=month, year=year)
90
+ end_dt = datetime.datetime.today()
91
+ results = []
92
+ params = {"motsCles": metier,'minCreationDate': dt_to_str_iso(start_dt),'maxCreationDate': dt_to_str_iso(end_dt),'range':'0-149'}
93
+ try:
94
+ search_on_big_data = client.search(params=params)
95
+ results += search_on_big_data["resultats"]
96
+ except:
97
+ print("Il n'y a pas d'offres d'emploi.")
98
+
99
+ results_df = pd.DataFrame(results)
100
+ return results_df
101
+
102
  @cl.step(type="llm", show_input=True)
103
  def Connexion_Mistral():
104
+ endpoint = "https://models.inference.ai.azure.com"
105
+ return Mistral(api_key=os.environ["GITHUB_TOKEN"], server_url=endpoint)
 
 
106
 
107
  @cl.step(type="tool", show_input=True)
108
  def Generation_reponse(client, data, question):
109
+ return client.chat.stream(
110
+ model="Mistral-Nemo",
111
  messages=[
112
  SystemMessage(content="Tu es un spécialiste de l'enseignement supérieur, des formations et de la pédagogie. Tu es en capacité d'analyser en profondeur les séances pédagogiques et de les mettre en adéquation avec les théories de la recherche en éducation. Répondez à la question seulement et exclusivement à partir du contexte et des définitions ci-contre, de la manière la plus pertinente, seulement en fonction des informations fournies. Contexte : " + str(data) + ". Définition : les formations MIPI (Management de l'Innovation et du Patrimoine Immobilier) concernent le secteur de l'immobilier : facility management, property management, asset management. Les formations MITIC (Management de l'Innovation des Technologies de l'Information et de la Communication) concernent le secteur du numérique : management de projet, innovation et conseil, support numérique aux métiers"),
113
  UserMessage(content=question + "Donne le résultat au format texte markdown, jusqu'à 3000 caractères convertis en UTF-8. Continue la réponse en citant, dans un paragraphe supplémentaire de 3 lignes, introduit un saut de ligne et par \"\n📚 Sources : \", les 3 verbatim, jusqu'à 100 caractères pour chaque verbatim, avec leur numéro de ligne respectif, qui ont permis de générer la réponse, à partir du contexte. Termine la réponse en créant, dans un dernier paragraphe d'une seule et unique ligne, introduite par un saut de ligne et par \"\n📣 Question en relation avec le sujet : \", 1 seule et unique question en relation avec la question posée, en commençant la ligne par \"Question relative au contexte :\"."),
114
  ],
115
+ temperature=0.1,
 
 
116
  max_tokens=1024,
117
+ )
118
+
119
+ def Generation_completion(client, data, question):
120
+ response = client.chat.complete(
121
+ model="Mistral-Nemo",
122
+ messages=[
123
+ SystemMessage(content="Tu es un spécialiste de l'enseignement supérieur, des formations et de la pédagogie. Tu es en capacité d'analyser en profondeur les séances pédagogiques et de les mettre en adéquation avec les théories de la recherche en éducation. Répondez à la question seulement et exclusivement à partir du contexte et des définitions ci-contre, de la manière la plus pertinente, seulement en fonction des informations fournies. Contexte : " + str(data) + ". Définition : les formations MIPI (Management de l'Innovation et du Patrimoine Immobilier) concernent le secteur de l'immobilier : facility management, property management, asset management. Les formations MITIC (Management de l'Innovation des Technologies de l'Information et de la Communication) concernent le secteur du numérique : management de projet, innovation et conseil, support numérique aux métiers"),
124
+ UserMessage(content=question + "Donne le résultat au format texte markdown, jusqu'à 3000 caractères convertis en UTF-8. Continue la réponse en citant, dans un paragraphe supplémentaire de 3 lignes, introduit un saut de ligne et par \"\n📚 Sources : \", les 3 verbatim, jusqu'à 100 caractères pour chaque verbatim, avec leur numéro de ligne respectif, qui ont permis de générer la réponse, à partir du contexte. Termine la réponse en créant, dans un dernier paragraphe d'une seule et unique ligne, introduite par un saut de ligne et par \"\n📣 Question en relation avec le sujet : \", 1 seule et unique question en relation avec la question posée, en commençant la ligne par \"Question relative au contexte :\"."),
125
+ ],
126
+ temperature=0.1,
127
+ max_tokens=1024,
128
+ top_p=0.1
129
+ )
130
+ msg = response.choices[0].message.content
131
+ return msg
132
+
133
  @cl.step(type="tool", show_input=True)
134
  async def Affichage_reponse(response):
135
  msg = cl.Message(author="COPILOT",content="")
136
 
137
  for update in response:
138
+ if update.data.choices:
139
  time.sleep(0.125)
140
+ await msg.stream_token(update.data.choices[0].delta.content.replace('Ã','é').replace('©','').replace('Ã','è').replace('¨','').replace('â','\'').replace('€','').replace('™','').replace('Å','oe').replace('“','').replace('®','î').replace('´','ô').replace('<','').replace('>','').replace('/',''))
141
 
142
  await msg.send()
143
  return msg
 
187
  async def on_action(action):
188
  client = cl.user_session.get("client")
189
  data = Chargement_des_datas_web(cl.user_session.get("chat_profile"))
190
+
191
+ diviseur = str(len(data) // 23500)
192
+ reste = str(len(data) % 23500)
193
+
194
  question = action.value
195
 
196
+ answer = ''
197
+ if diviseur != 0:
198
+ for i in range(0, 3):
199
+ operator = i + 1
200
+ deb = i * 23500
201
+ end = operator * 23500
202
+ webData = data[deb:end]
203
+ answer += Generation_completion(client, webData, question)
204
+ else:
205
+ answer += Generation_reponse(client, data, question)
206
+
207
+ if diviseur != 0 and reste !=0 and len(reste) <= 23500:
208
+ answer += Generation_completion(client, reste, question)
209
+
210
+ response = Generation_reponse(client, answer, question)
211
 
212
  msg = await Affichage_reponse(response)
213
 
214
+ result = msg.content
215
 
216
+ await Affichage_question_contexte(result, question)
217
 
218
 
219
  @cl.set_chat_profiles
 
373
  )
374
  ]
375
  ),
376
+ cl.ChatProfile(
377
+ name="Offres d'emploi par code ROME",
378
+ markdown_description="Posez vos questions sur les offres d'emploi en direct avec France Travail grâce aux codes ROME rattachés aux formations.",
379
+ icon="/public/public_request-theme.svg",
380
+ starters = [
381
+ cl.Starter(
382
+ label="Offres d'emploi de la licence MIPI",
383
+ message="M1403-M1604-M1204-M1605-M1203",
384
+ icon="/public/public_learn.svg",
385
+ ),
386
+ cl.Starter(
387
+ label="Offres d'emploi de la licence MITIC",
388
+ message="M1403-M1604-M1204-M1605-M1203",
389
+ icon="/public/public_learn.svg",
390
+ ),
391
+ cl.Starter(
392
+ label="Offres d'emploi du master MIPI",
393
+ message="M1702-M1402-M1403-H1206-M1703",
394
+ icon="/public/public_learn.svg",
395
+ ),
396
+ cl.Starter(
397
+ label="Offres d'emploi du master MITIC",
398
+ message="M1702-M1402-M1403-H1206-M1703",
399
+ icon="/public/public_learn.svg",
400
+ )
401
+ ]
402
+ ),
403
+ cl.ChatProfile(
404
+ name="Offres d'emploi par métier type",
405
+ markdown_description="Posez vos questions sur les offres d'emploi en direct avec France Travail par métier type.",
406
+ icon="/public/public_request-theme.svg",
407
+ starters = [
408
+ cl.Starter(
409
+ label="Responsable de site industriel ou tertiaire",
410
+ message="Responsable de site industriel ou tertiaire",
411
+ icon="/public/public_learn.svg",
412
+ ),
413
+ cl.Starter(
414
+ label="Conseiller en investissement immobilier",
415
+ message="Conseiller en investissement immobilier",
416
+ icon="/public/public_learn.svg",
417
+ ),
418
+ cl.Starter(
419
+ label="Chef de projet digital",
420
+ message="Chef de projet digital",
421
+ icon="/public/public_learn.svg",
422
+ ),
423
+ cl.Starter(
424
+ label="Manager de l'innovation numérique",
425
+ message="Manager de l'innovation numérique",
426
+ icon="/public/public_learn.svg",
427
+ )
428
+ ]
429
+ ),
430
  ]
431
 
432
  @cl.on_chat_start
 
436
 
437
  @cl.on_message
438
  async def main(message: cl.Message):
439
+ if cl.user_session.get("chat_profile") != "Offres d'emploi par code ROME" and cl.user_session.get("chat_profile") != "Offres d'emploi par métier type":
440
+ data = Chargement_des_datas(cl.user_session.get("chat_profile"))
441
+ cl.user_session.set("data", data)
442
+ client = cl.user_session.get("client")
443
 
444
+ response = Generation_reponse(client, data, message.content)
445
 
446
+ msg = await Affichage_reponse(response)
447
 
448
+ answer = msg.content
449
+ await Affichage_question_contexte(answer, message.content)
450
+ else:
451
+ codeRomeStr = message.content
452
+ if codeRomeStr.find('-') != -1 or isinstance(codeRomeStr[-4], int) or isinstance(codeRomeStr[1:5], int):
453
+ await cl.Message(author="COPILOT", content="📊 Connexion à l'API France Travail").send()
454
+ df_FT = API_France_Travail_ROME(codeRomeStr)
455
+ elif isinstance(codeRomeStr[-4], int):
456
+ await cl.Message(author="COPILOT", content="📊 Connexion à l'API France Travail").send()
457
+ df_FT = API_France_Travail_ROME(codeRomeStr)
458
+ else:
459
+ df_FT = API_France_Travail_Metier(codeRomeStr)
460
+
461
+ await cl.Message(author="COPILOT", content="📈 Tableau des emplois les plus représentatifs").send()
462
+ df_intitule = df_FT.groupby('intitule').size().reset_index(name='obs')
463
+ df_intitule = df_intitule.sort_values(by=['obs'], ascending=True)
464
+ df_intitule = df_intitule.iloc[-25:]
465
+ displayTable = df_intitule.sort_values(by=['obs'], ascending=True).to_markdown
466
+ await cl.Message(author="COPILOT", content=displayTable).send()
467
+
468
+ df_FT_Select = df_FT[['intitule','typeContratLibelle','experienceLibelle','competences','description','qualitesProfessionnelles','salaire','lieuTravail','formations']].copy()
469
+ list_FT = df_FT_Select.values.tolist()
470
+ context = ''
471
+ for i in range(0,len(list_FT)):
472
+ context += "\n✔️ Emploi : " + str(list_FT[i][0]) + ";\n◉ Contrat : " + str(list_FT[i][1]) + ";\n◉ Compétences professionnelles : " + str(list_FT[i][3]).replace("{","").replace("}","").replace("[","").replace("]","").replace("code","").replace("libelle","") + ";\n" + "◉ Salaire : " + str(list_FT[i][6]).replace("{","").replace("}","").replace("[","").replace("]","") + ";\n◉ Qualification : " + str(list_FT[i][5]).replace("'libelle'","\n• 'libelle").replace("{","").replace("}","").replace("[","").replace("]","").replace("code","") + ";\n◉ Localisation : " + str(list_FT[i][7]).replace("{","").replace("}","").replace("[","").replace("]","") + ";\n◉ Expérience : " + str(list_FT[i][2]) + ";\n◉ Niveau de qualification : " + str(list_FT[i][8]).replace("{","").replace("}","").replace("[","").replace("]","") + ";\n◉ Description de l'emploi : " + str(list_FT[i][4]) + "\n"
473
 
474
+ listEmplois_name = f"Liste des emplois"
475
+ text_elements = []
476
+ text_elements.append(
477
+ cl.Text(content="Question : " + codeRomeStr + "\n\nRéponse :\n" + context.replace('[','').replace(']','').replace('{','').replace('}','').replace("'code'","\n• 'code'"), name=listEmplois_name, display="side")
478
+ )
479
+ await cl.Message(author="COPILOT", content="👨‍💼 Source France Travail : " + listEmplois_name, elements=text_elements).send()
480
+
481
  @cl.on_stop
482
  def on_stop():
483
  print("L'utilisateur veut arrêter la completion en cours!")