datapioneer / app.py
datacipen's picture
Update app.py
48a3377 verified
import os
import json
import datetime
import requests
import textwrap
import dash
import dash_player as dp
from offres_emploi import Api
from offres_emploi.utils import dt_to_str_iso
from dash import Dash, dcc, callback, ctx, Output, Input, dash_table, State, no_update, _dash_renderer, clientside_callback
from dash import html
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import dash_mantine_components as dmc
from dash_iconify import DashIconify
import pandas as pd
from dotenv import load_dotenv
_dash_renderer._set_react_version("18.2.0")
import plotly.io as pio
from langchain_community.llms import HuggingFaceEndpoint
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
#from langchain.schema.output_parser import StrOutputParser
from pinecone import Pinecone
from openai import OpenAI
from flask import Flask
from flask_caching import Cache
from pydantic import BaseModel
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_pinecone import PineconeVectorStore
server = Flask(__name__)
def vectorDatabase_connexion():
index_name = "all-jdlp"
embeddings = HuggingFaceEmbeddings()
vectorstore = PineconeVectorStore(
index_name=index_name, embedding=embeddings, pinecone_api_key=os.getenv('PINECONE_API_KEY')
)
return vectorstore
def vectorDatabase_connexion_skills():
index_name = "all-skills"
embeddings = HuggingFaceEmbeddings()
vectorstore = PineconeVectorStore(
index_name=index_name, embedding=embeddings, pinecone_api_key=os.getenv('PINECONE_API_KEY_SKILLS')
)
return vectorstore
def Retriever(data):
vectorstore = vectorDatabase_connexion()
retriever = vectorstore.as_retriever(search_type="similarity_score_threshold", search_kwargs={"score_threshold": .7, "k": 43,"filter": {"categorie": {"$eq": "greendeal"}}})
similarity = vectorstore.similarity_search_with_relevance_scores(data, score_threshold= .7, k= 43,filter={"categorie": {"$eq": "greendeal"}})
return [retriever, similarity]
def similarityStudyOccupation(data):
vectorstore = vectorDatabase_connexion_skills()
try:
retriever = vectorstore.similarity_search_with_relevance_scores(data, score_threshold= .7, k= 20,filter={"categorie": {"$eq": "escoCompetencesAppellation"}})
dict = []
for item in retriever:
occupation = item[0].metadata['métier']
dict.append({'metier':occupation, 'score':item[1]})
except:
dict.append({'Réponse':'Pas de réponse trouvée!'})
df = pd.DataFrame(dict)
return df
def similarityOccupationStudy(data):
vectorstore = vectorDatabase_connexion()
try:
retriever = vectorstore.similarity_search_with_relevance_scores(data, score_threshold= .7, k= 20,filter={"categorie": {"$eq": "OF"}})
dict = []
niveau = "NQF 7"
for item in retriever:
if item[0].metadata['ABREGE_LIBELLES'] == 'Titre ingénieur' or item[0].metadata['ABREGE_LIBELLES'] == 'Master':
niveau = "NQF 7"
elif item[0].metadata['ABREGE_LIBELLES'] == 'Licence' or item[0].metadata['ABREGE_LIBELLES'] == 'Licence professionnelle' or item[0].metadata['ABREGE_LIBELLES'] == 'Bachelor universitaire de technologie':
niveau = "NQF 6"
formation = item[0].metadata['ABREGE_LIBELLES'] + " " + item[0].metadata['INTITULE']
dict.append({'formation':formation, 'niveau': niveau, 'score':item[1]})
except:
niveau = "NQF 7"
dict.append({'Réponse':'Pas de réponse trouvée!'})
df = pd.DataFrame(dict)
df_niveau6 = df[df['niveau'] == "NQF 6"]
df_niveau7 = df[df['niveau'] == "NQF 7"]
return [df_niveau7, df_niveau6]
def getFicheCertification(data):
certification = data['points'][0]['y'].split(' ')
label = ''
if certification[1] == "professionnelle" or certification[1] == "ingénieur":
type = certification[0] + " " + certification[1]
for i in range(2,len(certification)):
label = label + " " + certification[i]
elif certification[1] == "universitaire":
type = certification[0] + " " + certification[1] + " " + certification[2] + " " + certification[3]
for i in range(4,len(certification)):
label = label + " " + certification[i]
else:
type = certification[0]
for i in range(1,len(certification)):
label = label + " " + certification[i]
pc = Pinecone(api_key=os.environ.get("PINECONE_API_KEY"))
index = pc.Index("all-jdlp")
try:
retrieverCertification = index.query(
top_k=1,
vector= [0] * 768, # embedding dimension
namespace='',
filter={"categorie": {"$eq": "OF"},"ABREGE_LIBELLES": {"$eq": type.strip()},"INTITULE": {"$eq": label.strip()}},
include_metadata=True
)
formation = "***" + retrieverCertification['matches'][0]['metadata']['ABREGE_LIBELLES'] + " " + retrieverCertification['matches'][0]['metadata']['INTITULE'] + "***\n\n***Activités visées :***\n" + retrieverCertification['matches'][0]['metadata']['ACTIVITES_VISEES'] + "\n\n***Capacités attestées :***\n" + retrieverCertification['matches'][0]['metadata']['CAPACITES_ATTESTEES'].replace('\x95','\n\n-') + "\n\n***ROME :***\n" + retrieverCertification['matches'][0]['metadata']['CODES_ROME'] + " : " + retrieverCertification['matches'][0]['metadata']['LIBELLES_ROME'] + "\n\n***Types d'emploi accessible :***\n" + retrieverCertification['matches'][0]['metadata']['TYPE_EMPLOI_ACCESSIBLES']
except:
formation = 'Pas de réponse RNCP trouvée!'
return formation
def splitList(list, type):
array = []
end = []
quotient = len(list) // 4
reste = len(list) % 4
if quotient >= 1:
for i in range(0, quotient):
array.append(list[i*4:(i+1)*4])
if reste == 1:
end = list[quotient*4:len(list)]
if type == 'int':
end.append('')
end.append('')
end.append('')
else:
end.append('')
end.append('')
end.append('')
array.append(end)
elif reste == 2:
end = list[quotient*4:len(list)]
if type == 'int':
end.append('')
end.append('')
else:
end.append('')
end.append('')
array.append(end)
elif reste == 3:
end = list[quotient*4:len(list)]
if type == 'int':
end.append('')
else:
end.append('')
array.append(end)
else:
end = list[0:reste]
if reste == 1:
if type == 'int':
end.append('')
end.append('')
end.append('')
else:
end.append('')
end.append('')
end.append('')
elif reste == 2:
if type == 'int':
end.append('')
end.append('')
else:
end.append('')
end.append('')
elif reste == 3:
if type == 'int':
end.append('')
else:
end.append('')
array.append(end)
return array
def cartoMapCertification(data):
df = FilterByStudydf(data)
### Green Skills ###
df_skills = df[['preferredLabel']].copy()
df_skills = df_skills.groupby(['preferredLabel']).size().reset_index(name='obs')
df_skills = df_skills.sort_values(by=['obs'])
list_skills = df_skills['preferredLabel'].values.tolist()
list_skills = list(map(lambda x: "<br>".join(textwrap.wrap(x.capitalize(),width=20)), list_skills))
len_skills = len(list_skills) // 4
list_skills = splitList(list_skills, 'str')
value_skills = df_skills['obs'].values.tolist()
value_skills = splitList(value_skills, 'int')
### Related Skills ###
df_broaderSkills = df[['broaderConceptPT']].copy()
df_broaderSkills['broaderConceptPT'] = df_broaderSkills['broaderConceptPT'].str.split('|')
df_broaderSkills = df_broaderSkills.explode('broaderConceptPT')
df_broaderSkills = df_broaderSkills[df_broaderSkills['broaderConceptPT'] != '']
df_broaderSkills = df_broaderSkills.groupby(['broaderConceptPT']).size().reset_index(name='obs')
df_broaderSkills = df_broaderSkills.sort_values(by=['obs'])
list_broaderSkills = df_broaderSkills['broaderConceptPT'].values.tolist()
list_broaderSkills = list(map(lambda x: "<br>".join(textwrap.wrap(x.capitalize(),width=20)), list_broaderSkills))
len_broaderSkills = len(list_broaderSkills) // 4
list_broaderSkills = splitList(list_broaderSkills, 'str')
value_broaderSkills = df_broaderSkills['obs'].values.tolist()
value_broaderSkills = splitList(value_broaderSkills, 'int')
### Occupation ###
df_occupation = df[['occupationLabel']].copy()
df_occupation = df_occupation.groupby(['occupationLabel']).size().reset_index(name='obs')
df_occupation = df_occupation.sort_values(by=['obs'])
list_occupation = df_occupation['occupationLabel'].values.tolist()
list_occupation = list(map(lambda x: "<br>".join(textwrap.wrap(x.capitalize(),width=20)), list_occupation))
len_occupation = len(list_occupation) // 4
list_occupation = splitList(list_occupation, 'str')
value_occupation = df_occupation['obs'].values.tolist()
value_occupation = splitList(value_occupation, 'int')
fig = make_subplots(
rows=1, cols=3,
horizontal_spacing=0.01,subplot_titles=("Green Skills", "Related Green Skills" , "Occupations"),
)
fig.add_trace(
go.Heatmap(
z=value_skills,
text=list_skills,
hovertemplate="Green Skill : %{customdata}<extra></extra>",
customdata=list_skills,
texttemplate="<b style='line-height:6pt'>%{text}</b><br>%{z}",
textfont={"size": 10},
xgap=2,ygap=2,
colorscale='Greens',hoverongaps = True,
showscale=False,
),
row=1, col=1
)
fig.add_trace(
go.Heatmap(
z=value_broaderSkills,
text=list_broaderSkills,
hovertemplate="Related Skill : %{customdata}<extra></extra>",
customdata=list_broaderSkills,
texttemplate="<b style='line-height:6pt'>%{text}</b><br>%{z}",
textfont={"size": 10},
xgap=2,ygap=2,colorscale='Blues',
showscale=False,
),
row=1, col=2
)
fig.add_trace(
go.Heatmap(
z=value_occupation,
text=list_occupation,
hovertemplate="Occupation : %{customdata}<extra></extra>",
customdata=list_occupation,
texttemplate="<b style='line-height:6pt'>%{text}</b><br>%{z}",
textfont={"size": 10},
xgap=2,ygap=2,colorscale='Purples',
showscale=False,
),
row=1, col=3
)
if len_skills <= 4:
height=450
else:
n = len_broaderSkills + 1
height=n*110
fig.update_layout(
template = "plotly_dark",
paper_bgcolor = 'rgba(36, 36, 36, 1)',
plot_bgcolor = 'rgba(36, 36, 36, 1)',
height=height,
width=1600,
title_text="Cartographie formation : " + data,
showlegend=False,hovermode="x",hoverlabel=dict(
bgcolor="black",
font_size=12,
),
margin=dict(l=10, r=1, t=100, b=1, pad=1),
)
# Mise à jour des axes
fig.update_xaxes(showticklabels=False)
fig.update_yaxes(showticklabels=False)
return fig
def cartoMapOccupation(data):
df = FilterByOccupationdf(data)
### Green Skills ###
df_skills = df[['preferredLabel']].copy()
df_skills = df_skills.groupby(['preferredLabel']).size().reset_index(name='obs')
df_skills = df_skills.sort_values(by=['obs'])
list_skills = df_skills['preferredLabel'].values.tolist()
list_skills = list(map(lambda x: "<br>".join(textwrap.wrap(x.capitalize(),width=20)), list_skills))
len_skills = len(list_skills) // 4
list_skills = splitList(list_skills, 'str')
value_skills = df_skills['obs'].values.tolist()
value_skills = splitList(value_skills, 'int')
### Related Skills ###
df_broaderSkills = df[['broaderConceptPT']].copy()
df_broaderSkills['broaderConceptPT'] = df_broaderSkills['broaderConceptPT'].str.split('|')
df_broaderSkills = df_broaderSkills.explode('broaderConceptPT')
df_broaderSkills = df_broaderSkills[df_broaderSkills['broaderConceptPT'] != '']
df_broaderSkills = df_broaderSkills.groupby(['broaderConceptPT']).size().reset_index(name='obs')
df_broaderSkills = df_broaderSkills.sort_values(by=['obs'])
list_broaderSkills = df_broaderSkills['broaderConceptPT'].values.tolist()
list_broaderSkills = list(map(lambda x: "<br>".join(textwrap.wrap(x.capitalize(),width=20)), list_broaderSkills))
len_broaderSkills = len(list_broaderSkills) // 4
list_broaderSkills = splitList(list_broaderSkills, 'str')
value_broaderSkills = df_broaderSkills['obs'].values.tolist()
value_broaderSkills = splitList(value_broaderSkills, 'int')
### Certification ###
df_certification = df[['frenchStudyLabel']].copy()
df_certification['frenchStudyLabel'] = df_certification['frenchStudyLabel'].str.split('|')
df_certification = df_certification.explode('frenchStudyLabel')
df_certification = df_certification[df_certification['frenchStudyLabel'] != '']
df_certification = df_certification.groupby(['frenchStudyLabel']).size().reset_index(name='obs')
df_certification = df_certification.sort_values(by=['obs'])
list_certification = df_certification['frenchStudyLabel'].values.tolist()
list_certification = list(map(lambda x: "<br>".join(textwrap.wrap(x.capitalize(),width=20)), list_certification))
len_certification = len(list_certification) // 4
list_certification = splitList(list_certification, 'str')
value_certification = df_certification['obs'].values.tolist()
value_certification = splitList(value_certification, 'int')
fig = make_subplots(
rows=1, cols=3,
horizontal_spacing=0.01,subplot_titles=("Green Skills", "Related Green Skills" , "Certifications"),
)
fig.add_trace(
go.Heatmap(
z=value_skills,
text=list_skills,
hovertemplate="Green Skill : %{customdata}<extra></extra>",
customdata=list_skills,
texttemplate="<b style='line-height:6pt'>%{text}</b><br>%{z}",
textfont={"size": 10},
xgap=2,ygap=2,
colorscale='Greens',hoverongaps = True,
showscale=False,
),
row=1, col=1
)
fig.add_trace(
go.Heatmap(
z=value_broaderSkills,
text=list_broaderSkills,
hovertemplate="Related Skill : %{customdata}<extra></extra>",
customdata=list_broaderSkills,
texttemplate="<b style='line-height:6pt'>%{text}</b><br>%{z}",
textfont={"size": 10},
xgap=2,ygap=2,colorscale='Blues',
showscale=False,
),
row=1, col=2
)
fig.add_trace(
go.Heatmap(
z=value_certification,
text=list_certification,
hovertemplate="Certification : %{customdata}<extra></extra>",
customdata=list_certification,
texttemplate="<b style='line-height:6pt'>%{text}</b><br>%{z}",
textfont={"size": 10},
xgap=2,ygap=2,colorscale='Purples',
showscale=False,
),
row=1, col=3
)
if len_skills <= 1 and len_broaderSkills < len_certification:
n = len_certification + 1
height=n*150
elif len_skills <= 1 and len_broaderSkills >= len_certification:
height=450
else:
n = len_broaderSkills + 1
height=n*110
fig.update_layout(
template = "plotly_dark",
paper_bgcolor = 'rgba(36, 36, 36, 1)',
plot_bgcolor = 'rgba(36, 36, 36, 1)',
height=height,
width=1600,
title_text="Cartographie Métier : " + data,
showlegend=False,hovermode="x",hoverlabel=dict(
bgcolor="black",
font_size=12,
),
margin=dict(l=10, r=1, t=100, b=1, pad=1),
)
# Mise à jour des axes
fig.update_xaxes(showticklabels=False)
fig.update_yaxes(showticklabels=False)
return fig
def listEmploisFT(data):
client = Api(client_id=os.getenv('POLE_EMPLOI_CLIENT_ID'),
client_secret=os.getenv('POLE_EMPLOI_CLIENT_SECRET'))
todayDate = datetime.datetime.today()
month, year = (todayDate.month-1, todayDate.year) if todayDate.month != 1 else (12, todayDate.year-1)
start_dt = todayDate.replace(day=1, month=month, year=year)
end_dt = datetime.datetime.today()
results = []
data = data.split('(')
if data[0].find('/') != -1:
metier = data[0].split('/')
search = metier[0]
else:
search = data[0]
try:
params = {"motsCles": search,'minCreationDate': dt_to_str_iso(start_dt),'maxCreationDate': dt_to_str_iso(end_dt),'range':'0-149'}
search_on_big_data = client.search(params=params)
results += search_on_big_data["resultats"]
df_FT = pd.DataFrame(results)
df = df_FT[['id','intitule','typeContratLibelle','experienceLibelle','lieuTravail','secteurActiviteLibelle','competences']].copy()
df["lieuTravail"] = df["lieuTravail"].apply(lambda x: x['libelle']).apply(lambda x: x[0:3]).apply(lambda x: x.strip())
listEmplois = df.values.tolist()
emplois = f"**[Dashboard des emplois](https://datacipen-dashskills.hf.space/?metier={search.replace(' ','%20')}) : {search}**\n\n\n"
for i in range(0,len(listEmplois)):
competence = ''
if isinstance(listEmplois[i][6], list):
for comp in listEmplois[i][6]:
competence = competence + '- ' + comp['libelle'] + '\n\n'
else:
competence = competence + 'Néant'
emplois += "\n***✔️ Emploi : " + str(listEmplois[i][1]).capitalize() + "***\n\nLien vers France Travail : https://candidat.francetravail.fr/offres/recherche/detail/" + str(listEmplois[i][0]) + "\n\nType de contrat : " + str(listEmplois[i][2]) + "\n\nExpérience : " + str(listEmplois[i][3]) + "\n\nLieu : " + str(listEmplois[i][4]) + "\n\nSecteur d'activité : " + str(listEmplois[i][5]) + "\n\nCompétences professionnelles : \n\n" + str(competence) + "\n\n\n"
return emplois
except:
return "Il n'y a pas d'offres d'emploi concernant ce métier!"
def getFicheMetier(data, item):
#repo_id = "mistralai/Mistral-7B-Instruct-v0.2"
#llm = HuggingFaceEndpoint(
# repo_id=repo_id, max_new_tokens=4096, temperature=0.7, task="text2text-generation", streaming=True
#)
#os.environ['API_KEY'] = os.environ['API_KEY']
client = OpenAI(base_url=os.environ['BASEURL_RENNES_API_KEY'], api_key=os.environ['ENDPOINT_RENNES_API_KEY'])
context_user = data['points'][0]['customdata']
completion = client.chat.completions.create(
model="gpt-oss-120b",
messages = [
{"role": "system", "content": f"Vous êtes un ingénieur pédagogique de l'enseignement supérieur et vous êtes doué pour faire des analyses des formations de l'enseignement supérieur et de faire le rapprochement entre les compétences professionnelles vertes relatives à la transition écologique attendues par le marché de l'emploi, et les métiers verts émergents et ou relatifs à la transition écologique, extraits de l'ESCO. En fonction des informations suivantes et du contexte suivant seulement et strictement, répondez en langue française strictement à la question ci-dessous, en 5000 mots au moins. Lorsque cela est possible, cite les sources du contexte. 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."},
{"role": "user", "content": f"Définition : l'acronyme ESCO signifie European Skills Competences and Occupation. Il s'agit d'une classification multilingue qui identifie et catégorise les compétences, les qualifications et les occupations pertinentes pour le marché du travail et l'éducation de l'Union Européenne. Les compétences, les savoirs, les savoir-faire et les savoir-être s'écrivent à l'aide de verbe d'action à l'infinitif comme le stipule la taxonomie de Bloom pour marquer une progression dans l'exercice de la compétence.\nContexte : {context_user}.\nQuestion : Crée une fiche métier de {data['points'][0]['y']}, dans un contexte de développement durable, spécifique à : {item} et comprenant des paragraphes sur les missions principales, le niveau de qualification, les compétences professionnelles, les savoirs, les savoir-faire, les savoir-être ainsi que les métiers apparentés.\nDonne le résultat au format texte, en langue française absolument."}
],
temperature=0.5
)
#prompt = ChatPromptTemplate.from_messages(
# [
# (
# "system",
# f"Vous êtes un ingénieur pédagogique de l'enseignement supérieur et vous êtes doué pour faire des analyses des formations de l'enseignement supérieur et de faire le rapprochement entre les compétences professionnelles vertes relatives à la transition écologique attendues par le marché de l'emploi, et les métiers verts émergents et ou relatifs à la transition écologique, extraits de l'ESCO. En fonction des informations suivantes et du contexte suivant seulement et strictement, répondez en langue française strictement à la question ci-dessous, en 5000 mots au moins. Lorsque cela est possible, cite les sources du contexte. 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.",
# ),
# ("human", "Définition : l'acronyme ESCO signifie European Skills Competences and Occupation. Il s'agit d'une classification multilingue qui identifie et catégorise les compétences, les qualifications et les occupations pertinentes pour le marché du travail et l'éducation de l'Union Européenne. Les compétences, les savoirs, les savoir-faire et les savoir-être s'écrivent à l'aide de verbe d'action à l'infinitif comme le stipule la taxonomie de Bloom pour marquer une progression dans l'exercice de la compétence.\nContexte : {context}.\nQuestion : {question}.\nDonne le résultat au format texte, en langue française absolument."),
# ]
#)
#question_user = "Crée une fiche métier de " + data['points'][0]['y'] + ", dans un contexte de développement durable, spécifique à : " + item + "et comprenant des paragraphes sur les missions principales, le niveau de qualification, les compétences professionnelles, les savoirs, les savoir-faire, les savoir-être ainsi que les métiers apparentés."
#runnable = prompt | llm
#answer = runnable.invoke({"question":question_user,"context":context_user})
return completion.choices[0].message.content
#return answer
#for s in runnable.stream({"question":question_user,"context":context_user}):
# return s
def DfToStr(theme):
df_allSkills = Opendf()
df_allSkills = df_allSkills[df_allSkills['catGreenDeal'] == theme]
df_greenskills = df_allSkills[['preferredLabel','broaderConceptPT','descriptionSkill','catGreenDeal','occupationLabel','altLabels','descriptionOccupation','frenchStudyLabel']].copy()
df_greenskills['preferredLabel'] = df_greenskills['preferredLabel'].apply(lambda x: 'Compétence : ' + x)
df_greenskills['occupationLabel'] = df_greenskills['occupationLabel'].apply(lambda x: 'Métier : ' + x)
df_greenskills['frenchStudyLabel'] = df_greenskills['frenchStudyLabel'].apply(lambda x: 'Formation : ' + x)
return df_greenskills.to_string(index = False)
def createListOccupations(theme):
df_allOccupations_AD = Filterdf(theme)
df_occupations = df_allOccupations_AD[['occupationLabel']].copy()
df_occupations = df_occupations.drop_duplicates(subset=['occupationLabel'])
list_occupations = df_occupations['occupationLabel'].values.tolist()
return [list_occupations, len(list_occupations)]
def createListSkills(theme):
df_allSkills_AD = Filterdf(theme)
df_skills = df_allSkills_AD[['preferredLabel','broaderConceptPT']].copy()
df_skills = df_skills.drop_duplicates(subset=['preferredLabel'])
list_skills = df_skills['preferredLabel'].values.tolist()
return [list_skills, len(list_skills)]
def createListStudies(theme):
df_allOccupations_AD = Filterdf(theme)
df_allOccupations_AD['frenchStudyLabel'] = df_allOccupations_AD['frenchStudyLabel'].str.split('|')
df_allOccupations_AD = df_allOccupations_AD.explode('frenchStudyLabel')
df_allOccupations_AD = df_allOccupations_AD[df_allOccupations_AD['frenchStudyLabel'] != '']
df_allOccupations_AD = df_allOccupations_AD[['preferredLabel','frenchStudyLabel']].copy()
df_studies = df_allOccupations_AD.drop_duplicates(subset=['frenchStudyLabel'])
list_studies = df_studies['frenchStudyLabel'].values.tolist()
return [list_studies, len(list_studies), df_allOccupations_AD]
def createInfoSkills(theme):
df_allSkills_AD = Filterdf(theme)
df_skillsInfo = df_allSkills_AD[['preferredLabel','broaderConceptPT','descriptionSkill','altLabels','descriptionOccupation']].copy()
df_skillsInfo = df_skillsInfo.drop_duplicates(subset=['preferredLabel'])
df_skillsInfo.set_index("preferredLabel", inplace=True)
return df_skillsInfo
def createInfoOccupations(theme):
df_allOccupations_AD = Filterdf(theme)
df_occupationsInfo = df_allOccupations_AD[['occupationLabel','broaderConceptPT','descriptionSkill','altLabels','descriptionOccupation']].copy()
df_occupationsInfo = df_occupationsInfo.drop_duplicates(subset=['occupationLabel'])
df_occupationsInfo.set_index("occupationLabel", inplace=True)
return df_occupationsInfo
def createCategoriesSkills(theme):
list_skills = createListSkills(theme)[0]
if theme == "Neutralité climatique":
categories = pd.Series({
list_skills[i]: cat for i, cat in enumerate([
1, 2, 1, 3, 2, 4]) # ÉNERGIE, CLIMAT ET ENVIRONNEMENT, GESTION ET COORDINATION, CONSEIL ET EXPERTISE
})
elif theme == "Économie circulaire":
categories = pd.Series({
list_skills[i]: cat for i, cat in enumerate([
1, 1, 2, 3, 2, 2, 2, 3, 1, 2, 1, 4, 2, 3, 3, 1, 1, 3, 2]) # 1: GESTION DE L'ENERGIE, 2: DEVELOPPEMENT DURABLE ET ENVIRONNEMENT, 3: TECHNOLOGIES ET SYSTEMES, 4: POLITIQUES ET MANAGEMENT
})
elif theme == "Agriculture plus durable":
categories = pd.Series({
list_skills[i]: cat for i, cat in enumerate([
2, 2, 3, 1, 3, 2, 2, 3, 2, 2, 4, 1, 4, 3, 1, 1, 1, 4, 1]) # 1: TECHNIQUES AGRICOLES FONDAMENTALES, 2: GESTION ET DÉVELOPPEMENT DURABLE, 3: RÉGLEMENTATION ET POLITIQUE, 4: AGRITOURISME ET SERVICES
})
elif theme == "Industrie propre":
categories = pd.Series({
list_skills[i]: cat for i, cat in enumerate([
1, 2, 4, 4, 3, 4, 2, 1, 4, 1, 2, 3, 2, 2, 4, 2, 3,1,2,1,3, 4,4,
4,
4,
4,
4,
2,
1,
3,
1,
2,
4,
3,
3,
3,
2,
2,
1,
2,
1,
1,
3,
3,
1,
3,
3,
2,
4,
1,
2,
3,
1,
4,
]) # 1: TECHNIQUE & OPÉRATIONNEL, 2: ENVIRONNEMENT & DURABILITÉ, 3: MANAGEMENT & CONSEIL, 4: RÉGLEMENTATION & ÉTHIQUE
})
elif theme == "Environnement plus sain":
categories = pd.Series({
list_skills[i]: cat for i, cat in enumerate([
1, 1, 4, 3, 2, 1, 4, 4, 3, 1, 1, 2, 1, 4, 3, 1, 4, 2, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 3, 1, 1, 4, 1, 1, 4, 1, 2, 1, 2, 1, 1, 1, 3, 1, 1, 3, 4, 2, 3, 1, 1, 2, 1, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 3, 4, 1, 1, 1, 1, 1, 4, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) # 1: PROTECTION ET GESTION DE L'ENVIRONNEMENT, 2: ÉNERGIE ET RESSOURCES DURABLES, 3: BIEN-ETRE ANIMAL ET BIODIVERSITE, 4: REGLEMENTATION ET CONFORMITE ENVIRONNEMENTALE
})
elif theme == "Justice climatique et équité":
categories = pd.Series({
list_skills[i]: cat for i, cat in enumerate([
1,3,1,3,4,2,3,1,1,1,2,4,2])
})#AUDIT ET CONSEILS EN DEVELOPPEMENT DURABLE, GESTION DES DECHETS ET POLLUTION, LEGISLATION ET REGLEMENTATION, SENSIBILISATION ET PROTECTION DE L'ENVIRONNEMENT
return categories
def strTheme(theme):
if theme == "Neutralité climatique":
return "Climate Neutrality"
elif theme == "Économie circulaire":
return "Circular Economy"
elif theme == "Agriculture plus durable":
return "Sustainable Farming"
elif theme == "Industrie propre":
return "Clean Industry"
elif theme == "Environnement plus sain":
return "Healthier Environment"
elif theme == "Justice climatique et équité":
return "Climate Justice and Fairness"
def listCategories(theme):
if theme == "Neutralité climatique":
return ["ÉNERGIE", "CLIMAT ET ENVIRONNEMENT", "GESTION ET COORDINATION", "CONSEIL ET EXPERTISE"]
elif theme == "Économie circulaire":
return ["GESTION DE L'ENERGIE", "DEVELOPPEMENT DURABLE ET ENVIRONNEMENT", "TECHNOLOGIES ET SYSTEMES", "POLITIQUES ET MANAGEMENT"]
elif theme == "Agriculture plus durable":
return ["TECHNIQUES AGRICOLES FONDAMENTALES", "GESTION ET DÉVELOPPEMENT DURABLE", "RÉGLEMENTATION ET POLITIQUE", "AGRITOURISME ET SERVICES"]
elif theme == "Industrie propre":
return ["TECHNIQUE & OPÉRATIONNEL", "ENVIRONNEMENT & DURABILITÉ", "MANAGEMENT & CONSEIL", "RÉGLEMENTATION & ÉTHIQUE"]
elif theme == "Environnement plus sain":
return ["PROTECTION ET GESTION DE L'ENVIRONNEMENT", "ÉNERGIE ET RESSOURCES DURABLES", "BIEN-ETRE ANIMAL ET BIODIVERSITE", "REGLEMENTATION ET CONFORMITE ENVIRONNEMENTALE"]
elif theme == "Justice climatique et équité":
return ["AUDIT ET CONSEILS EN DEVELOPPEMENT DURABLE", "GESTION DES DECHETS ET POLLUTION", "LEGISLATION ET REGLEMENTATION", "SENSIBILISATION ET PROTECTION DE L'ENVIRONNEMENT"]
# Create a customized version of the plotly_dark theme with a modified background color
custom_plotly_dark_theme = {
"layout": {
"paper_bgcolor": "#1E1E1E", # Update the paper background color
"plot_bgcolor": "#1E1E1E", # Update the plot background color
"font": {
"color": "#FFFFFF" # Update the font color
},
"xaxis": {
"gridcolor": "#333333", # Update the x-axis grid color
"zerolinecolor": "#666666" # Update the x-axis zero line color
},
"yaxis": {
"gridcolor": "#333333", # Update the y-axis grid color
"zerolinecolor": "#666666" # Update the y-axis zero line color
}
}
}
# Apply the customized theme to your Plotly figures
pio.templates["custom_plotly_dark"] = custom_plotly_dark_theme
pio.templates.default = "custom_plotly_dark"
load_dotenv()
def removeTags(all):
for data in all(['style', 'script']):
data.decompose()
return ''.join(all.stripped_strings)
theme_toggle = dmc.Tooltip(
dmc.ActionIcon(
[
dmc.Paper(DashIconify(icon="radix-icons:sun", width=25), darkHidden=True),
dmc.Paper(DashIconify(icon="radix-icons:moon", width=25), lightHidden=True),
],
variant="transparent",
color="yellow",
id="color-scheme-toggle",
size="lg",
ms="auto",
),
label="Changez de thème",
position="left",
withArrow=True,
arrowSize=6,
)
styleRefresh = {
"color": "lightgrey",
"textDecoration" : "none"
}
styleTitle = {
"textAlign": "center"
}
styleUSERIA = {
"textAlign": "right",
"marginBottom" : "5px"
}
styleSUBMITIA = {
"marginLeft":"auto",
"marginRight":"auto",
"marginTop": "5px",
"marginBottom" : "5px"
}
styleSYSIA = {
"marginTop":"10px",
"marginBottom":"120px",
}
styleTopvar = {
"display": "none"
}
styleToggle = {
"marginTop":"25px",
"textAlign": "right",
}
styleIcon = {
"marginTop":"10px",
}
styleSubmitBox = {
"position":"fixed",
"width": "100%",
"top": "calc(100vh - 100px)",
"right": "0"
}
def custom_error_handler(err):
# This function defines what we want to happen when an exception occurs
# For now, we just print the exception to the terminal with additional text
print(f"The app raised the following exception: {err}")
def format_docs(docs):
return "\n\n".join([d.page_content for d in docs])
def textbox(text, box="AI", name="Philippe"):
text = text.replace(f"{name}:", "").replace("You:", "")
#text = textile.textile(text)
style = {
"max-width": "60%",
"width": "max-content",
"padding": "5px 10px",
"border-radius": 25,
"margin-bottom": 20,
}
if box == "user":
style["margin-left"] = "auto"
style["margin-right"] = 0
return html.Div(dmc.Badge(text, size="lg", tt="none", variant="gradient", gradient={"from": "indigo", "to": "cyan"},),style=styleUSERIA)
elif box == "AI":
style["margin-left"] = 0
style["margin-right"] = "auto"
thumbnail = html.Img(
src=app.get_asset_url("sparkles.gif"),
style={
"border-radius": 50,
"height": 36,
"margin-right": 5,
"float": "left",
},
)
text = f"""{text}"""
text = text.replace(" ","")
textbox = dmc.Card(children=[dcc.Markdown(text, style={"font-size":"0.8em"})],withBorder=False,w="100%", style=styleSYSIA)
#textbox = dmc.Card(children=[dmc.Text(text,size="sm",c="dimmed")],withBorder=False,w="100%", style=styleSYSIA)
return html.Div([thumbnail, textbox])
else:
raise ValueError("Incorrect option for `box`.")
# Define Layout
conversation = html.Div(
html.Div(id="display-conversation"),
style={
"overflow-y": "auto",
"display": "flex",
"height": "calc(100vh - 100px)",
"flex-direction": "column-reverse",
},
)
controls = dbc.InputGroup(
children=[
dmc.TextInput(id="user-input", placeholder="Ecrire votre requête...", w="400", style=styleSUBMITIA),
dbc.InputGroupAddon(dmc.Button(leftSection=DashIconify("Envoyer", icon="tabler:send", width=20), variant="gradient", gradient={"from": "indigo", "to": "cyan"},id="submit"), addon_type="append", style=styleTitle),
#dbc.Input(id="user-input", placeholder="Ecrire votre requête...", type="text"),
#dbc.InputGroupAddon(dbc.Button("Submit", id="submit"), addon_type="append"),
],style=styleSubmitBox
)
class CustomDash(Dash):
def interpolate_index(self, **kwargs):
return '''
<!DOCTYPE html>
<html>
<head>
<title>Dashboard NLP des verbatim</title>
<link href="https://fonts.cdnfonts.com/css/inter" rel="stylesheet">
</head>
<body>
<div id="custom-topbar"></div>
{app_entry}
{config}
{scripts}
{renderer}
<div id="custom-footer"></div>
</body>
</html>
'''.format(
app_entry=kwargs['app_entry'],
config=kwargs['config'],
scripts=kwargs['scripts'],
renderer=kwargs['renderer'])
#app = Dash(__name__, external_scripts=external_scripts, external_stylesheets=dmc.styles.ALL, on_error=custom_error_handler)
app = CustomDash(__name__, server=server, use_pages=True, pages_folder='', external_stylesheets=dmc.styles.ALL, on_error=custom_error_handler)
cache = Cache(app.server, config={
'CACHE_TYPE': 'SimpleCache'
})
@cache.cached(timeout=3600)
def Opendf():
df_allSkills = pd.read_csv("./assets/GreenOccupationsEmbeddingsCatGreenDeal07_SALTOCALTDESCROMESTUDY.csv")
return df_allSkills
def Filterdf(theme):
df_allSkills = Opendf()
return df_allSkills[df_allSkills['catGreenDeal'] == theme]
def FilterByOccupationdf(occupation):
df_allSkills = Opendf()
return df_allSkills[df_allSkills['occupationLabel'] == occupation]
def FilterByStudydf(study):
df_allSkills = Opendf()
df_allSkills['frenchStudyLabel'] = df_allSkills['frenchStudyLabel'].str.split('|')
df_allSkills = df_allSkills.explode('frenchStudyLabel')
df_allSkills = df_allSkills[df_allSkills['frenchStudyLabel'] != '']
return df_allSkills[df_allSkills['frenchStudyLabel'] == study]
def layout(**kwargs):
try:
themeDefault = kwargs['theme'].replace(' ','').replace('%20','')
except:
themeDefault = "Industrie propre"
return dmc.MantineProvider(
[
html.Div(
children=[
dcc.Store(id="storCertification", storage_type='session'),
dcc.Store(id="storEmplois", storage_type='session'),
dcc.Store(id="storTheme", storage_type='session'),
dcc.Store(id="storThemeDefault", data=themeDefault, storage_type='session'),
dmc.Modal(id="modal-description-mapOccupation",
children=[
dcc.Loading(
id="loadingmapOccupation",
children=[
dcc.Graph(id="figmapOccupation"),
],
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default"
)
], fullScreen=True, padding=0
),
dmc.Modal(id="modal-description-mapCertification",
children=[
dcc.Loading(
id="loadingmapCertification",
children=[
dcc.Graph(id="figmapCertification"),
],
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default"
)
], fullScreen=True, padding=0
),
dmc.Modal(id="modal-description-emploisFT",
children=[
dcc.Loading(
id="loadingemploisFT",
children=[
dcc.Markdown(id="modal-liste-emploisFT", style={"font-size":"0.8em"}),
],
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default"
)
], size="lg"
),
dmc.Modal(id="modal-description-study",
children=[
dcc.Loading(
id="loadingDescriptionCertification",
children=[
dmc.Button("Cartographie de la formation", id="mapCertification", size="compact-xs", mx="auto", my="3", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
dcc.Graph(id="figRepartition-certification"),
dcc.Graph(id="figRepartitionSkills-certification"),
dcc.Graph(id="figRepartitionBroaderSkills-certification"),
dcc.Graph(id="figRepartitionOccupationsSkillsCat"),
dcc.Markdown(id="modal-description-certification", style={"font-size":"0.8em"}),
dcc.Graph(id="figMetier"),
],
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default"
)
], size="66%"
),
dmc.Modal(id="modal-description",
children=[
dcc.Loading(
id="loadingDescriptionOccupation",
children=[
dmc.Group(
gap=3,justify="center",
children=[
dmc.Button("Offres d'emploi France Travail", id="emploisFT", size="compact-xs", mx="auto", my="3", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
dmc.Button("Cartographie du métier", id="mapOccupation", size="compact-xs", mx="auto", my="3", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
],
),
dcc.Graph(id="figRepartition"),
dcc.Graph(id="figRepartitionSkills"),
dcc.Graph(id="figRepartitionBroaderSkills"),
dcc.Graph(id="figRepartitionSkillsCat"),
dcc.Markdown(id="modal-description-title", style={"font-size":"0.8em"}),
dcc.Graph(id="figStudyNQF7"),
dcc.Graph(id="figStudyNQF6")
],
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default"
)
], size="66%"
),
dmc.Modal(
title="Green Deal Themes",
id="modal-centered",
size="lg",centered=True,
opened=True,
children=[
dmc.Grid(
children=[
dmc.GridCol(
html.Div(
dmc.Card(
children=[
dmc.CardSection(
dmc.Image(
src="./assets/climate-neutrality.png",
mt=3,mx="auto",w=50,alt="climate neutrality",
)
),dmc.Group(
[
dmc.Text("Climate Neutrality", mx="auto", fw=500, c="bright"),
dmc.Button("Skills-Occupations", id="CNSKOC", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
dmc.Button("Skills-studies", id="CNSKST", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
],
justify="space-between",
mt="md",
mb="xs",
),
],
withBorder=True,
shadow="sm",
radius="md",
),
),
span=6),
dmc.GridCol(
html.Div(
dmc.Card(
children=[
dmc.CardSection(
dmc.Image(
src="./assets/circular-economy.png",
mt=3,mx="auto",w=50,alt="Circular Economy",
)
),dmc.Group(
[
dmc.Text("Circular Economy", mx="auto", fw=500, c="bright"),
dmc.Button("Skills-Occupations", id="CESKOC", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
dmc.Button("Skills-studies", id="CESKST", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
],
justify="space-between",
mt="md",
mb="xs",
),
],
withBorder=True,
shadow="sm",
radius="md",
),
),
span=6),
dmc.GridCol(
html.Div(
dmc.Card(
children=[
dmc.CardSection(
dmc.Image(
src="./assets/clean-industry.png",
mt=3,mx="auto",w=50,alt="Clean Industry",
)
),dmc.Group(
[
dmc.Text("Clean Industry", mx="auto", fw=500, c="bright"),
dmc.Group(
[
dmc.Button("Skills-Occupations", id="CISKOC", size="compact-xs", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
dmc.Button("Skills-studies", id="CISKST", size="compact-xs", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
],mx="auto"),
],
justify="space-between",
mt="md",
mb="xs",
),
],
withBorder=True,
shadow="sm",
radius="md",
),
),
span=6),
dmc.GridCol(
html.Div(
dmc.Card(
children=[
dmc.CardSection(
dmc.Image(
src="./assets/healthier-environment.png",
mt=3,mx="auto",w=50,alt="Healthier Environment",
)
),dmc.Group(
[
dmc.Text("Healthier Environment", mx="auto", fw=500, c="bright"),
dmc.Button("Skills-Occupations", id="HESKOC", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
dmc.Button("Skills-studies", id="HESKST", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
],
justify="space-between",
mt="md",
mb="xs",
),
],
withBorder=True,
shadow="sm",
radius="md",
),
),
span=6),
dmc.GridCol(
html.Div(
dmc.Card(
children=[
dmc.CardSection(
dmc.Image(
src="./assets/sustainable-farming.png",
mt=3,mx="auto",w=50,alt="Sustainable Farming",
)
),dmc.Group(
[
dmc.Text("Sustainable Farming", mx="auto", fw=500, c="bright"),
dmc.Button("Skills-Occupations", id="SFSKOC", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
dmc.Button("Skills-studies", id="SFSKST", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
],
justify="space-between",
mt="md",
mb="xs",
),
],
withBorder=True,
shadow="sm",
radius="md",
),
),
span=6),
dmc.GridCol(
html.Div(
dmc.Card(
children=[
dmc.CardSection(
dmc.Image(
src="./assets/climate-justice-and-fairness.png",
mt=3,mx="auto",w=50,alt="Climate Justice and Fairness",
)
),dmc.Group(
[
dmc.Text("Climate Justice and Fairness", mx="auto", fw=500, c="bright"),
dmc.Button("Skills-Occupations", id="CJSKOC", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
dmc.Button("Skills-studies", id="CJSKST", size="compact-xs", mx="auto", variant="gradient", gradient={"from": "indigo", "to": "cyan"}, loaderProps={"type": "dots"}),
],
justify="space-between",
mt="md",
mb="xs",
),
],
withBorder=True,
shadow="sm",
radius="md",
),
),
span=6)
])
],
),
dmc.Container(
children=[
dmc.Grid(
children=[
dmc.GridCol(html.Div(
children=[
dmc.Badge(DashIconify(icon="radix-icons:target",style={"width":"25px","height":"25px", "padding-top":"8px"}), size="xl", circle=True,my=5,mr=5, style={"float":"left"},variant="gradient", gradient={"from": "indigo", "to": "cyan"},),
dcc.Loading(dmc.Title(f"DATA PIONEER : ESCO Green Skills, Occupations and Certifications", order=3, py=2,c="bright",id="mainTitle"),type="default")
]
), span=12),
dmc.GridCol(html.Div(
children=[
dmc.Group(
[
html.Div(dmc.Tooltip(dmc.Button(leftSection=DashIconify(icon="tabler:seedling", width=30),variant="gradient",gradient={"from": "indigo", "to": "cyan"}, id="drawer-filter"), label="Select filter occupation options",position="right",withArrow=True,arrowSize=6,), style=styleToggle),
html.Div(dmc.Tooltip(dmc.Button(leftSection=DashIconify(icon="tabler:tree", width=30),variant="gradient",gradient={"from": "indigo", "to": "cyan"}, id="drawer-filter-certification"), label="Select filter certification options",position="right",withArrow=True,arrowSize=6,), style=styleToggle),
html.Div(dmc.Tooltip(dmc.Button(leftSection=DashIconify(icon="tabler:leaf", width=30),variant="gradient",gradient={"from": "indigo", "to": "cyan"}, id="modal-opened"), label="Select Green Deal theme",position="right",withArrow=True,arrowSize=6,), style=styleToggle),
]
),
dmc.Drawer(
title="Filter with occupation options",
children=[
dbc.Container(
fluid=False,
children=[
dmc.Grid(
children=[
dmc.GridCol(html.Div(
dmc.MultiSelect(
placeholder="Select an occupation",
id="selectOccupation",
value=["All"],
searchable=True,
dropdownOpened=True,
checkIconPosition="right",
withScrollArea=True,
maxDropdownHeight=650,
maxValues=1,
w=400,
mb=10,
),
), span=12
),
]
)
]
)
],id="drawer-filter",
padding="md",position="left",opened=False
),
dmc.Drawer(
title="Filter with certification options",
children=[
dbc.Container(
fluid=False,
children=[
dmc.Grid(
children=[
dmc.GridCol(html.Div(
dmc.MultiSelect(
placeholder="Select a certification",
id="selectCertification",
value=["All"],
searchable=True,
dropdownOpened=True,
checkIconPosition="right",
withScrollArea=True,
maxDropdownHeight=650,
maxValues=1,
w=400,
mb=10,
)
), span=12
),
]
)
]
)
],id="drawer-filter-certification",
padding="md",position="left",opened=False
),
dmc.Drawer(
title="Mistral answers your questions on green skills and occupations ESCO data.",
children=[dbc.Container(
fluid=False,
children=[
dcc.Store(id="store-conversation", data=""),
html.Div(
dmc.Badge("Bonjour, Mistral est à votre écoute!", size="xl", variant="gradient", gradient={"from": "indigo", "to": "cyan"},),
style=styleUSERIA),
dcc.Loading(html.Div(id="loading-component", style={"margin-top":"10%","z-index":"100"}),type="default"),
conversation,
controls,
#dbc.Spinner(html.Div(id="loading-component")),
],
)
],
id="drawer-simple",
padding="md",
size="50%",
position="right",opened=False
),]
), span=3),
dmc.GridCol(html.Div(
#dmc.MultiSelect(
# placeholder="Select an occupation",
# id="selectOccupation",
# value=[""],
# data=[{"value": occupation, "label": occupation} for occupation in createListOccupations()],
# w=400,
# mb=10,
#),
), span=3),
dmc.GridCol(html.Div(
#dmc.MultiSelect(
# placeholder="Select a category",
# id="selectCategory",
# value=[""],
# data=[
# {"value": "", "label": ""},
# ],
# w=400,
# mb=10,
#),
), span=4),
#dmc.GridCol(html.Div(theme_toggle, style=styleToggle), span=2),
dmc.GridCol(html.Div(theme_toggle, className="darkOrLight", hidden=True), span=1),
dmc.GridCol(html.Div(dmc.Tooltip(dmc.Button(leftSection=DashIconify(icon="tabler:sparkles", width=30),variant="gradient",gradient={"from": "indigo", "to": "cyan"}, id="drawer-demo-button"), label="Generative AI on data",position="right",withArrow=True,arrowSize=6,), style=styleToggle), span=1),
#dmc.GridCol(html.A(DashIconify(icon="tabler:restore", width=20), href='/', style=styleRefresh), p=0,style=styleUSERIA, span=12),
dmc.GridCol(dmc.Tabs(
[
dmc.TabsList(mx="auto",grow=True,
children=[
dmc.TabsTab("Green Skills <--> Occupations", leftSection=DashIconify(icon="tabler:ikosaedr"), value="1"),
dmc.TabsTab("Green Skills <--> Studies", leftSection=DashIconify(icon="tabler:ikosaedr"), value="2"),
]
),
dmc.TabsPanel(
dmc.Grid(
children=[
dmc.Affix(
#dmc.Card(children=[dmc.Text('This kind of occupation is not in the list for this item. Select "All" in filter options',variant="gradient",gradient={"from": "oroange", "to": "red", "deg": 45},style={"fontSize": 20})],withBorder=True,radius="md",w=350,style={"visibility":"hidden"},id="notification")
children=[
html.Div(dmc.Button('This kind of occupation is not in the list for this item. Select "All" in filter options', variant="gradient", gradient={"from": "orange", "to": "red"},size="sm",mb=10)),
html.Div(dmc.Button('Select "All" in filter options', variant="gradient", gradient={"from": "orange", "to": "red"},size="sm")),
],
position={"left": "40%", "top": 20},
style={"visibility":"hidden"},id="notification"),
dmc.GridCol(html.Div(
dcc.Loading(
id="loadingOccupations",
children=(dcc.Graph(id="figOccupations", clickData={"points": [{"y": "", "customdata": ""}]})),
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default",
)
), span=12),
dmc.GridCol(html.Div(
dcc.Loading(
id="loadingBestOfOccupations",
children=(dcc.Graph(id="figBestOfOccupations")),
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default",
)
), span=6),
dmc.GridCol(html.Div(
dcc.Loading(
id="loadingBestOfSkills",
children=(dcc.Graph(id="figBestOfSkills")),
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default",
)
), span=6),
]
)
, value="1"),
dmc.TabsPanel(
dmc.Grid(
children=[
dmc.Affix(
#dmc.Card(children=[dmc.Text('This kind of occupation is not in the list for this item. Select "All" in filter options',variant="gradient",gradient={"from": "oroange", "to": "red", "deg": 45},style={"fontSize": 20})],withBorder=True,radius="md",w=350,style={"visibility":"hidden"},id="notification")
children=[
html.Div(dmc.Button('This kind of certification is not in the list for this item. Select "All" in filter options', variant="gradient", gradient={"from": "orange", "to": "red"},size="sm",mb=10)),
html.Div(dmc.Button('Select "All" in filter options', variant="gradient", gradient={"from": "orange", "to": "red"},size="sm")),
],
position={"left": "40%", "top": 20},
style={"visibility":"hidden"},id="notificationStudy"),
dmc.GridCol(html.Div(
dcc.Loading(
id="loadingStudies",
children=(dcc.Graph(id="figStudies", clickData={"points": [{"y": "", "customdata": ""}]})),
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default",
)
), span=12),
dmc.GridCol(html.Div(
dcc.Loading(
id="loadingBestOfStudies",
children=(dcc.Graph(id="figBestOfStudies")),
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default",
)
), span=6),
dmc.GridCol(html.Div(
dcc.Loading(
id="loadingBestOfAllSkills",
children=(dcc.Graph(id="figBestOfAllSkills")),
overlay_style={"visibility":"visible", "filter": "blur(2px)"}, type="default",
)
), span=6),
]), value="2"),
],
id="tabs-styled-with-props", value="1",
), span=12),
dmc.GridCol(
html.Div(
children=[dmc.Title(f"DATA PIONEER : ESCO Green Skills, Occupations table", order=5, pt=2, pb=5, c="bright"),
dcc.Loading(
id="loadingTableau",
children=(dbc.Container(id="tableauGreenSkills")),
type="default",
)],
), span=12
),
],
gutter="xs",
)
],size="xxl",fluid=True,pt="10"
),
]
)
],
id="mantine-provider",
forceColorScheme="dark",
theme={
"primaryColor": "indigo",
"fontFamily": "'Inter', sans-serif",
"components": {
"Button": {"defaultProps": {"fw": 400}},
"Alert": {"styles": {"title": {"fontWeight": 500}}},
"AvatarGroup": {"styles": {"truncated": {"fontWeight": 500}}},
"Badge": {"styles": {"root": {"fontWeight": 500}}},
"Progress": {"styles": {"label": {"fontWeight": 500}}},
"RingProgress": {"styles": {"label": {"fontWeight": 500}}},
"CodeHighlightTabs": {"styles": {"file": {"padding": 12}}},
"Table": {
"defaultProps": {
"highlightOnHover": True,
"withTableBorder": True,
"verticalSpacing": "sm",
"horizontalSpacing": "md",
}
},
},
# add your colors
"colors": {
"deepBlue": ["#E9EDFC", "#C1CCF6", "#99ABF0"], # 10 color elements
},
"shadows": {
# other shadows (xs, sm, lg) will be merged from default theme
"md": "1px 1px 3px rgba(0,0,0,.25)",
"xl": "5px 5px 3px rgba(0,0,0,.25)",
},
"headings": {
"fontFamily": "Roboto, sans-serif",
"sizes": {
"h1": {"fontSize": 30},
},
},
},
)
dash.register_page("home", layout=layout, path="/")
app.layout = html.Div(dash.page_container)
@callback(
Output("mantine-provider", "forceColorScheme"),
Input("color-scheme-toggle", "n_clicks"),
State("mantine-provider", "forceColorScheme"),
prevent_initial_call=True,
)
def switch_theme(_, theme):
return "dark" if theme == "light" else "light"
@callback(
Output("drawer-filter", "opened"),
Input("drawer-filter", "n_clicks"),
prevent_initial_call=True,
)
def drawer_filter(n_clicks):
return True
@callback(
Output("drawer-filter-certification", "opened"),
Input("drawer-filter-certification", "n_clicks"),
prevent_initial_call=True,
)
def drawer_filter_certification(n_clicks):
return True
@callback(
Output("drawer-simple", "opened"),
Input("drawer-demo-button", "n_clicks"),
prevent_initial_call=True,
)
def drawer_demo(n_clicks):
return True
@callback(
Output("modal-centered", "opened"),
Input("modal-opened", "n_clicks"),
Input("CNSKOC", "n_clicks"),
Input("CNSKST", "n_clicks"),
Input("CESKOC", "n_clicks"),
Input("CESKST", "n_clicks"),
Input("CISKOC", "n_clicks"),
Input("CISKST", "n_clicks"),
Input("HESKOC", "n_clicks"),
Input("HESKST", "n_clicks"),
Input("SFSKOC", "n_clicks"),
Input("SFSKST", "n_clicks"),
Input("CJSKOC", "n_clicks"),
Input("CJSKST", "n_clicks"),
State("modal-centered", "opened"),
prevent_initial_call=True,
)
def modal_demo(nc1,nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9,nc10,nc11,nc12,nc13, opened):
return not opened
clientside_callback(
"""
function updateLoadingState(n_clicks) {
return true
}
""",
Output("CNSKOC", "n_clicks", allow_duplicate=True),
Output("CNSKST", "n_clicks", allow_duplicate=True),
Output("CESKOC", "n_clicks", allow_duplicate=True),
Output("CESKST", "n_clicks", allow_duplicate=True),
Output("CISKOC", "n_clicks", allow_duplicate=True),
Output("CISKST", "n_clicks", allow_duplicate=True),
Output("HESKOC", "n_clicks", allow_duplicate=True),
Output("HESKST", "n_clicks", allow_duplicate=True),
Output("SFSKOC", "n_clicks", allow_duplicate=True),
Output("SFSKST", "n_clicks", allow_duplicate=True),
Output("CJSKOC", "n_clicks", allow_duplicate=True),
Output("CJSKST", "n_clicks", allow_duplicate=True),
Input("CNSKOC", "n_clicks"),
Input("CNSKST", "n_clicks"),
Input("CESKOC", "n_clicks"),
Input("CESKST", "n_clicks"),
Input("CISKOC", "n_clicks"),
Input("CISKST", "n_clicks"),
Input("HESKOC", "n_clicks"),
Input("HESKST", "n_clicks"),
Input("SFSKOC", "n_clicks"),
Input("SFSKST", "n_clicks"),
Input("CJSKOC", "n_clicks"),
Input("CJSKST", "n_clicks"),
prevent_initial_call=True,
)
@app.callback(
Output('tabs-styled-with-props','value'),
Output("CNSKOC", "n_clicks"),
Output("CNSKST", "n_clicks"),
Output("CESKOC", "n_clicks"),
Output("CESKST", "n_clicks"),
Output("CISKOC", "n_clicks"),
Output("CISKST", "n_clicks"),
Output("HESKOC", "n_clicks"),
Output("HESKST", "n_clicks"),
Output("SFSKOC", "n_clicks"),
Output("SFSKST", "n_clicks"),
Output("CJSKOC", "n_clicks"),
Output("CJSKST", "n_clicks"),
Input("CNSKOC", "n_clicks"),
Input("CNSKST", "n_clicks"),
Input("CESKOC", "n_clicks"),
Input("CESKST", "n_clicks"),
Input("CISKOC", "n_clicks"),
Input("CISKST", "n_clicks"),
Input("HESKOC", "n_clicks"),
Input("HESKST", "n_clicks"),
Input("SFSKOC", "n_clicks"),
Input("SFSKST", "n_clicks"),
Input("CJSKOC", "n_clicks"),
Input("CJSKST", "n_clicks"),
prevent_initial_call=True,
)
def click2(nc1,nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9,nc10,nc11,nc12):
if nc2 == 1:
return "2", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc1 == 1:
return "1", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc3 == 1:
return "1", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc4 == 1:
return "2", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc5 == 1:
return "1", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc6 == 1:
return "2", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc7 == 1:
return "1", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc8 == 1:
return "2", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc9 == 1:
return "1", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc10 == 1:
return "2", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc11 == 1:
return "1", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
if nc12 == 1:
return "2", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@callback(
Output("storTheme", "data"),
Input("CNSKOC", "n_clicks"),
Input("CNSKST", "n_clicks"),
Input("CESKOC", "n_clicks"),
Input("CESKST", "n_clicks"),
Input("CISKOC", "n_clicks"),
Input("CISKST", "n_clicks"),
Input("HESKOC", "n_clicks"),
Input("HESKST", "n_clicks"),
Input("SFSKOC", "n_clicks"),
Input("SFSKST", "n_clicks"),
Input("CJSKOC", "n_clicks"),
Input("CJSKST", "n_clicks"),
prevent_initial_call=True,
)
def load_from_db(nc1,nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9,nc10,nc11,nc12):
if ctx.triggered_id == None:
return "Économie circulaire"
elif ctx.triggered_id == "CNSKOC" or ctx.triggered_id == "CNSKST":
return "Neutralité climatique"
elif ctx.triggered_id == "CESKOC" or ctx.triggered_id == "CESKST":
return "Économie circulaire"
elif ctx.triggered_id == "CISKOC" or ctx.triggered_id == "CISKST":
return "Industrie propre"
elif ctx.triggered_id == "HESKOC" or ctx.triggered_id == "HESKST":
return "Environnement plus sain"
elif ctx.triggered_id == "SFSKOC" or ctx.triggered_id == "SFSKST":
return "Agriculture plus durable"
elif ctx.triggered_id == "CJSKOC" or ctx.triggered_id == "CJSKST":
return "Justice climatique et équité"
### callback for dashboard ###
@callback(
Output(component_id='figRepartitionBroaderSkills-certification', component_property='figure'),
Output(component_id='figRepartitionSkills-certification', component_property='figure'),
Output(component_id='figRepartition-certification', component_property='figure'),
Output(component_id='figRepartitionOccupationsSkillsCat', component_property='figure'),
Input('figStudies', 'clickData'),
Input("mantine-provider", "forceColorScheme"),
)
def create_repartition_certification(certification, theme):
if theme == "dark":
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
else:
template = "ggplot2"
paper_bgcolor = 'rgba(255, 255, 255, 1)'
plot_bgcolor = 'rgba(255, 255, 255, 1)'
df_study = FilterByStudydf(certification['points'][0]['y'])
df_certification = df_study.copy()
df_sunburst = df_certification.copy()
formation = certification['points'][0]['y'].split("(")
for index, row in df_sunburst.iterrows():
df_sunburst.at[index,'formation']=formation[0].replace(" ","<br />")
df_sunburst = df_sunburst.groupby(['preferredLabel','catGreenDeal','formation']).size().reset_index(name='values')
fig_sunburst = px.sunburst(df_sunburst, width=1000, height=1000, path=['formation','catGreenDeal','preferredLabel'], values='values',
color='catGreenDeal', color_discrete_sequence=px.colors.sequential.Blues_r, template=template)
fig_sunburst.update_layout(title=dict(text="Cartographie de la formation :<br />" + certification['points'][0]['y'] + "<br />sur les thèmes du Green Deal", font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,margin=dict(
t=100
),).update_traces(textinfo='label+percent entry', hoverinfo='label+percent entry', texttemplate='%{label}<br />%{percentRoot:.1%}')
df_certification = df_certification.groupby(['frenchStudyLabel','catGreenDeal']).size().reset_index(name='obs')
df_certification = df_certification.sort_values(by=['catGreenDeal'])
df_studyList = df_certification[['obs']].copy()
df_studyList = df_studyList.set_index('obs')
studyList = df_studyList.index.tolist()
df_catGreenDealList = df_certification[['catGreenDeal']].copy()
df_catGreenDealList = df_catGreenDealList.set_index('catGreenDeal')
catGreenDealList = df_catGreenDealList.index.tolist()
df_figure = pd.DataFrame(dict(r=studyList, theta=catGreenDealList))
fig = px.line_polar(df_figure, r='r', theta='theta', width=600, line_close=True,color_discrete_sequence=px.colors.sequential.YlGnBu,
template=template)
fig.update_layout(title=dict(text="Répartition de la formation :<br />" + certification['points'][0]['y'] + "<br />sur les thèmes du Green Deal", font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),
showlegend = False,
polar = dict(
radialaxis_tickfont_size = 8,
angularaxis = dict(
tickfont_size=10,
)
)
)
fig.update_traces(fill='toself')
df_skills = df_study.copy()
df_skills = df_skills.groupby(['catGreenDeal', 'preferredLabel']).size().reset_index(name='obs')
df_skills = df_skills.sort_values(by=['catGreenDeal'])
fig_skills = px.bar(df_skills, y='obs', x='catGreenDeal', color='preferredLabel', width=600, height=800, labels={'catGreenDeal':'Thème Green Deal','preferredLabel':'Green Skills','obs':'nombre'}, color_discrete_sequence=px.colors.sequential.YlGnBu_r, text_auto=True, template=template)
fig_skills.update_layout(
title=dict(text="Les Green skills de la formation :<br />" + certification['points'][0]['y'] + "<br />réparties sur les thèmes du Green Deal", font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),showlegend = False,font=dict(size=10))
df_broaderskills = df_study.copy()
df_broaderskills['broaderConceptPT'] = df_broaderskills['broaderConceptPT'].str.split('|')
df_broaderskills = df_broaderskills.explode('broaderConceptPT')
df_broaderskills = df_broaderskills[df_broaderskills['broaderConceptPT'] != '']
df_broaderskills = df_broaderskills.groupby(['catGreenDeal', 'broaderConceptPT']).size().reset_index(name='obs')
df_broaderskills = df_broaderskills.sort_values(by=['catGreenDeal'])
fig_broaderskills = px.bar(df_broaderskills, y='obs', x='catGreenDeal', color='broaderConceptPT', width=600, height=800, labels={'catGreenDeal':'Thème Green Deal','broaderConceptPT':'Related Green Skills','obs':'nombre'}, color_discrete_sequence=px.colors.sequential.YlGnBu_r, text_auto=True, template=template)
fig_broaderskills.update_layout(
title=dict(text="Les Green skills complémentaires de la formation :<br />" + certification['points'][0]['y'] + "<br />réparties sur les thèmes du Green Deal", font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),showlegend = False,font=dict(size=10))
return fig_broaderskills, fig_skills, fig, fig_sunburst
@callback(
Output(component_id='figRepartitionBroaderSkills', component_property='figure'),
Output(component_id='figRepartitionSkills', component_property='figure'),
Output(component_id='figRepartition', component_property='figure'),
Output(component_id='figRepartitionSkillsCat', component_property='figure'),
Input('figOccupations', 'clickData'),
Input("mantine-provider", "forceColorScheme"),
)
def create_repartition(occupation, theme):
if theme == "dark":
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
else:
template = "ggplot2"
paper_bgcolor = 'rgba(255, 255, 255, 1)'
plot_bgcolor = 'rgba(255, 255, 255, 1)'
df_metier = FilterByOccupationdf(occupation['points'][0]['y'])
df_occupation = df_metier.copy()
df_occupation = df_occupation.groupby(['occupationLabel','catGreenDeal']).size().reset_index(name='obs')
df_occupation = df_occupation.sort_values(by=['catGreenDeal'])
df_metierList = df_occupation[['obs']].copy()
df_metierList = df_metierList.set_index('obs')
metierList = df_metierList.index.tolist()
df_catGreenDealList = df_occupation[['catGreenDeal']].copy()
df_catGreenDealList = df_catGreenDealList.set_index('catGreenDeal')
catGreenDealList = df_catGreenDealList.index.tolist()
df_figure = pd.DataFrame(dict(r=metierList, theta=catGreenDealList))
fig = px.line_polar(df_figure, r='r', theta='theta', width=600, line_close=True,color_discrete_sequence=px.colors.sequential.YlGnBu,
template=template)
fig.update_layout(title=dict(text="Répartition du métier :<br />" + occupation['points'][0]['y'] + "<br />sur les thèmes du Green Deal", font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),
showlegend = False,
polar = dict(
radialaxis_tickfont_size = 8,
angularaxis = dict(
tickfont_size=10,
)
)
)
fig.update_traces(fill='toself')
df_skills = df_metier.copy()
df_skills = df_skills.groupby(['catGreenDeal', 'preferredLabel']).size().reset_index(name='obs')
df_skills = df_skills.sort_values(by=['catGreenDeal'])
fig_skills = px.bar(df_skills, y='obs', x='catGreenDeal', color='preferredLabel', width=600, labels={'catGreenDeal':'Thème Green Deal','preferredLabel':'Green Skills','obs':'nombre'}, color_discrete_sequence=px.colors.sequential.YlGnBu_r, text_auto=True, template=template)
fig_skills.update_layout(
title=dict(text="Les Green skills du métier :<br />" + occupation['points'][0]['y'] + "<br />réparties sur les thèmes du Green Deal", font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),showlegend = False,font=dict(size=10))
df_broaderskills = df_metier.copy()
df_broaderskills['broaderConceptPT'] = df_broaderskills['broaderConceptPT'].str.split('|')
df_broaderskills = df_broaderskills.explode('broaderConceptPT')
df_broaderskills = df_broaderskills[df_broaderskills['broaderConceptPT'] != '']
df_sunburst = df_broaderskills.copy()
metier = occupation['points'][0]['y'].split("(")
for index, row in df_sunburst.iterrows():
df_sunburst.at[index,'metier']=metier[0].replace(" ","<br />")
df_sunburst = df_sunburst.groupby(['broaderConceptPT','preferredLabel','catGreenDeal','metier']).size().reset_index(name='values')
fig_sunburst = px.sunburst(df_sunburst, width=1000, height=1000, path=['metier','catGreenDeal','preferredLabel','broaderConceptPT'], values='values',
color='catGreenDeal', color_discrete_sequence=px.colors.sequential.Blues_r, template=template).update_traces(textinfo='label+percent entry', hoverinfo='label+percent entry', texttemplate='%{label}<br />%{percentRoot:.1%}')
fig_sunburst.update_layout(title=dict(text="Cartographie du métier en fonction des Green Skills :<br />" + occupation['points'][0]['y'] + "<br />sur les thèmes du Green Deal", font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),)
df_broaderskills = df_broaderskills.groupby(['catGreenDeal', 'broaderConceptPT']).size().reset_index(name='obs')
df_broaderskills = df_broaderskills.sort_values(by=['catGreenDeal'])
fig_broaderskills = px.bar(df_broaderskills, y='obs', x='catGreenDeal', color='broaderConceptPT', width=600, labels={'catGreenDeal':'Thème Green Deal','broaderConceptPT':'Related Green Skills','obs':'nombre'}, color_discrete_sequence=px.colors.sequential.YlGnBu_r, text_auto=True, template=template)
fig_broaderskills.update_layout(
title=dict(text="Les Green skills complémentaires du métier :<br />" + occupation['points'][0]['y'] + "<br />réparties sur les thèmes du Green Deal", font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),showlegend = False,font=dict(size=10))
return fig_broaderskills, fig_skills, fig, fig_sunburst
@callback(
Output('selectOccupation', 'data'),
Output('selectCertification', 'data'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
)
def create_multiselect(item, itemDefault):
if item is None:
item = itemDefault
tabOccupations = [{'label': 'All', 'value': 'All'}]
multiSelectOccupations = createListOccupations(item)[0]
multiSelectOccupations.sort()
for occ in multiSelectOccupations:
tabOccupations.append({'label': occ.capitalize(), 'value': occ})
tabCertifications = [{'label': 'All', 'value': 'All'}]
multiSelectCertifications = createListStudies(item)[0]
multiSelectCertifications.sort()
for cer in multiSelectCertifications:
tabCertifications.append({'label': cer.capitalize(), 'value': cer})
return tabOccupations, tabCertifications
@callback(
Output(component_id='figOccupations', component_property='figure'),
Output('notification', 'style'),
Input(component_id='selectOccupation', component_property='value'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
Input("mantine-provider", "forceColorScheme"),
running=[(Output("CNSKOC", "loading"), True, False),(Output("CNSKST", "loading"), True, False),(Output("CESKOC", "loading"), True, False),(Output("CESKST", "loading"), True, False),(Output("CISKOC", "loading"), True, False),(Output("CISKST", "loading"), True, False),(Output("HESKOC", "loading"), True, False),(Output("HESKST", "loading"), True, False),(Output("SFSKOC", "loading"), True, False),(Output("SFSKST", "loading"), True, False),(Output("CJSKOC", "loading"), True, False),(Output("CJSKST", "loading"), True, False)]
)
def create_occupation(selectOccupation, item, itemDefault,theme):
if item is None:
item = itemDefault
notification = {"visibility":"hidden"}
if theme == "dark":
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
else:
template = "ggplot2"
paper_bgcolor = 'rgba(255, 255, 255, 1)'
plot_bgcolor = 'rgba(255, 255, 255, 1)'
if item == "Industrie propre":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.97, 'chartWidth': 1800},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.03, 'title' : "Catégories :"},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.025, 'title' : "■ TECHNIQUE & OPÉRATIONNEL"},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.02, 'title' : "■ ENVIRONNEMENT & DURABILITÉ"},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.015, 'title' : "■ MANAGEMENT & CONSEIL"},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.01, 'title' : "■ RÉGLEMENTATION & ÉTHIQUE"},
]
elif item == "Agriculture plus durable":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 1500},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.10, 'title' : "Catégories :"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.08, 'title' : "■ TECHNIQUES AGRICOLES FONDAMENTALES"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.06, 'title' : "■ GESTION ET DÉVELOPPEMENT DURABLE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.04, 'title' : "■ RÉGLEMENTATION ET POLITIQUE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.02, 'title' : "■ AGRITOURISME ET SERVICES"},
]
elif item == "Économie circulaire":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 1500},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.10, 'title' : "Catégories :"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.08, 'title' : "■ GESTION DE L'ENERGIE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.06, 'title' : "■ DEVELOPPEMENT DURABLE ET ENVIRONNEMENT"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.04, 'title' : "■ TECHNOLOGIES ET SYSTEMES"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.02, 'title' : "■ POLITIQUES ET MANAGEMENT"},
]
elif item == "Neutralité climatique":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.95, 'chartWidth': 1500},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.20, 'title' : "Catégories :"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.18, 'title' : "■ ÉNERGIE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.16, 'title' : "■ CLIMAT ET ENVIRONNEMENT"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.14, 'title' : "■ GESTION ET COORDINATION"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.12, 'title' : "■ CONSEIL ET EXPERTISE"},
]
elif item == "Environnement plus sain":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.972, 'chartWidth': 2000},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.014, 'title' : "Catégories :"},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.011, 'title' : "■ PROTECTION ET GESTION DE L'ENVIRONNEMENT"},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.008, 'title' : "■ ÉNERGIE ET RESSOURCES DURABLES"},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.005, 'title' : "■ BIEN-ETRE ANIMAL ET BIODIVERSITE"},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.002, 'title' : "■ REGLEMENTATION ET CONFORMITE ENVIRONNEMENTALE"},
]
elif item == "Justice climatique et équité":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 1500},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.10, 'title' : "Catégories :"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.08, 'title' : "■ AUDIT ET CONSEILS EN DEVELOPPEMENT DURABLE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.06, 'title' : "■ GESTION DES DECHETS ET POLLUTION"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.04, 'title' : "■ LEGISLATION ET REGLEMENTATION"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.02, 'title' : "■ SENSIBILISATION ET PROTECTION DE L'ENVIRONNEMENT"},
]
df_allSkills_AD = Filterdf(item)
df_occupationsSkills = df_allSkills_AD[['preferredLabel','occupationLabel']].copy()
if selectOccupation[0] == "All" or len(selectOccupation) == 0 or selectOccupation is None:
list_occupations = createListOccupations(item)[0]
lenListOccupations = createListOccupations(item)[1]
# Ajout de la légende
annotations = [
dict(
x=position[1]['titlePosiX'],
y=position[1]['titlePosiY'],
xref="paper",
yref="paper",
text=position[1]['title'],
showarrow=False,
font=dict(size=12, color="white"),
),
dict(
x=position[2]['titlePosiX'],
y=position[2]['titlePosiY'],
xref="paper",
yref="paper",
text=position[2]['title'],
showarrow=False,
font=dict(size=10, color="#FF69B4"),
),
dict(
x=position[3]['titlePosiX'],
y=position[3]['titlePosiY'],
xref="paper",
yref="paper",
text=position[3]['title'],
showarrow=False,
font=dict(size=10, color="#4169E1"),
),
dict(
x=position[4]['titlePosiX'],
y=position[4]['titlePosiY'],
xref="paper",
yref="paper",
text=position[4]['title'],
showarrow=False,
font=dict(size=10, color="#32CD32"),
),
dict(
x=position[5]['titlePosiX'],
y=position[5]['titlePosiY'],
xref="paper",
yref="paper",
text=position[5]['title'],
showarrow=False,
font=dict(size=10, color="#FFD700"),
),
]
else:
if len(df_allSkills_AD[df_allSkills_AD['occupationLabel'] == selectOccupation[0]]) == 0:
notification = {"visibility":"visible"}
list_occupations = selectOccupation
lenListOccupations = 1
annotations = []
list_skills = createListSkills(item)[0]
matrix = pd.DataFrame(0, index=list_occupations, columns=list_skills)
for occupation in list_occupations:
for skills in list_skills:
df = df_occupationsSkills[df_occupationsSkills['preferredLabel'] == skills]
if occupation in df.values :
matrix.loc[occupation, skills] = 1
df_skillsInfo = createInfoSkills(item)
df_occupationsInfo = createInfoOccupations(item)
categories = createCategoriesSkills(item)
color_values = matrix.copy()
for col in matrix.columns:
color_values[col] = matrix[col] * categories[col]
# Création du heatmap
fig = go.Figure(data=go.Heatmap(
z=color_values.values,
x=color_values.columns,
y=color_values.index,
colorscale=[
[0, '#242424'],
[0.2, '#242424'],
[0.2, '#FF69B4'], # Rose pour technique
[0.4, '#FF69B4'],
[0.4, '#4169E1'], # Bleu pour management
[0.6, '#4169E1'],
[0.6, '#32CD32'], # Vert pour environnement
[0.8, '#32CD32'],
[0.8, '#FFD700'], # Jaune pour économie
[1.0, '#FFD700']
],
showscale=False,
))
# Ajout des bordures aux cellules
fig.update_traces(
xgap=1,
ygap=1,
)
# Mise en forme
fig.update_layout(
title={
'text': "Skills matrix by profession:<br />" + strTheme(item),
'y':position[0]['titlePosiY'],
'x':position[0]['titlePosiX'],
'xanchor': 'center',
'yanchor': 'top'},
xaxis=dict(
side='top',
tickangle=45,
tickfont=dict(size=10),
),
yaxis=dict(
autorange='reversed',
tickfont=dict(size=10),
),
width=position[0]['chartWidth'],
height= 400 + lenListOccupations * 16,
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=300,
l=600,
r=100,
b=50
),
annotations=annotations,hovermode="x unified",hoverlabel=dict(
bgcolor="black",
font_size=10,
), clickmode='event+select',
)
# Personnalisation du style des axes
fig.update_xaxes(
#showspikes=True,
showgrid=True,
gridwidth=1,
gridcolor='darkgrey',
)
fig.update_yaxes(
#showspikes=True,
showgrid=True,
gridwidth=1,
gridcolor='darkgrey',
)
# Ajout d'un hover template personnalisé
#1: TECHNIQUES AGRICOLES FONDAMENTALES, 2: GESTION ET DÉVELOPPEMENT DURABLE, 3: RÉGLEMENTATION ET POLITIQUE, 4: AGRITOURISME ET SERVICES
hover_text = []
for idx in matrix.index:
row = []
for col in matrix.columns:
if matrix.loc[idx,col] == 1:
if item == "Industrie propre":
category_name = {1: 'TECHNIQUE & OPÉRATIONNEL', 2: 'ENVIRONNEMENT & DURABILITÉ',
3: 'MANAGEMENT & CONSEIL', 4: 'RÉGLEMENTATION & ÉTHIQUE'}[categories[col]]
elif item == "Agriculture plus durable":
category_name = {1: 'TECHNIQUES AGRICOLES FONDAMENTALES', 2: 'GESTION ET DÉVELOPPEMENT DURABLE',
3: 'RÉGLEMENTATION ET POLITIQUE', 4: 'AGRITOURISME ET SERVICES'}[categories[col]]
elif item == "Économie circulaire":
category_name = {1: 'GESTION DE L\'ENERGIE', 2: 'DEVELOPPEMENT DURABLE ET ENVIRONNEMENT',
3: 'TECHNOLOGIES ET SYSTEMES', 4: 'POLITIQUES ET MANAGEMENT'}[categories[col]]
elif item == "Neutralité climatique":
category_name = {1: 'ÉNERGIE', 2: 'CLIMAT ET ENVIRONNEMENT',
3: 'GESTION ET COORDINATION', 4: 'CONSEIL ET EXPERTISE'}[categories[col]]
elif item == "Environnement plus sain":
category_name = {1: 'PROTECTION ET GESTION DE L\'ENVIRONNEMENT', 2: 'ÉNERGIE ET RESSOURCES DURABLES',
3: 'BIEN-ETRE ANIMAL ET BIODIVERSITE', 4: 'REGLEMENTATION ET CONFORMITE ENVIRONNEMENTALE'}[categories[col]]
elif item == "Justice climatique et équité":
category_name = {1: 'AUDIT ET CONSEILS EN DEVELOPPEMENT DURABLE', 2: 'GESTION DES DECHETS ET POLLUTION',
3: 'LEGISLATION ET REGLEMENTATION', 4: 'SENSIBILISATION ET PROTECTION DE L\'ENVIRONNEMENT'}[categories[col]]
broaderSkill = df_skillsInfo.loc[[col]].values.tolist()[0][0]
descriptionSkill = df_skillsInfo.loc[[col]].values.tolist()[0][1]
altLabels = str(df_occupationsInfo.loc[[idx]].values.tolist()[0][2])
descriptionOccupation = df_occupationsInfo.loc[[idx]].values.tolist()[0][3]
label_y = idx.replace("(fiche nationale)","").replace("(essential)","").replace("(optional)","")
row.append(
f'<b>💼 Occupation: {"<br>".join(textwrap.wrap(label_y,width=50))}</b><br>' +
f'<b>📣 Skill: {col.capitalize()}</b><br>' +
f'🏷️ Category: {category_name}<br>' +
f'💡 Alternative skills: {"<br>".join(textwrap.wrap(broaderSkill,width=50))}<br>' +
f'📚 Skill description: {"<br>".join(textwrap.wrap(descriptionSkill,width=50))}' + '<br><br>' +
f'💡 Alternative occupations: {"<br>".join(textwrap.wrap(altLabels,width=50))}<br>' +
f'📚 Occupation description: {"<br>".join(textwrap.wrap(descriptionOccupation,width=50))}')
else:
row.append('')
hover_text.append(row)
fig.update_traces(
hovertemplate="%{customdata}<extra></extra>",
customdata=hover_text,
)
return fig, notification
@callback(
Output(component_id='figStudies', component_property='figure'),
Output('notificationStudy', 'style'),
Input(component_id='selectCertification', component_property='value'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
Input("mantine-provider", "forceColorScheme"),
Input('figOccupations', 'clickData'),
)
def create_study(selectCertification, item, itemDefault, theme, clickData):
if item is None:
item = itemDefault
notification = {"visibility":"hidden"}
if theme == "dark":
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
else:
template = "ggplot2"
paper_bgcolor = 'rgba(255, 255, 255, 1)'
plot_bgcolor = 'rgba(255, 255, 255, 1)'
if item == "Industrie propre":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 1800},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.03, 'title' : "Catégories :"},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.025, 'title' : "■ TECHNIQUE & OPÉRATIONNEL"},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.02, 'title' : "■ ENVIRONNEMENT & DURABILITÉ"},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.015, 'title' : "■ MANAGEMENT & CONSEIL"},
{'titlePosiX' : -0.53, 'titlePosiY' : 1.01, 'title' : "■ RÉGLEMENTATION & ÉTHIQUE"},
]
elif item == "Agriculture plus durable":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 1500},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.10, 'title' : "Catégories :"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.08, 'title' : "■ TECHNIQUES AGRICOLES FONDAMENTALES"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.06, 'title' : "■ GESTION ET DÉVELOPPEMENT DURABLE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.04, 'title' : "■ RÉGLEMENTATION ET POLITIQUE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.02, 'title' : "■ AGRITOURISME ET SERVICES"},
]
elif item == "Économie circulaire":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 1500},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.10, 'title' : "Catégories :"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.08, 'title' : "■ GESTION DE L'ENERGIE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.06, 'title' : "■ DEVELOPPEMENT DURABLE ET ENVIRONNEMENT"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.04, 'title' : "■ TECHNOLOGIES ET SYSTEMES"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.02, 'title' : "■ POLITIQUES ET MANAGEMENT"},
]
elif item == "Neutralité climatique":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 1500},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.20, 'title' : "Catégories :"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.18, 'title' : "■ ÉNERGIE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.16, 'title' : "■ CLIMAT ET ENVIRONNEMENT"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.14, 'title' : "■ GESTION ET COORDINATION"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.12, 'title' : "■ CONSEIL ET EXPERTISE"},
]
elif item == "Environnement plus sain":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 2000},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.07, 'title' : "Catégories :"},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.06, 'title' : "■ PROTECTION ET GESTION DE L'ENVIRONNEMENT"},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.05, 'title' : "■ ÉNERGIE ET RESSOURCES DURABLES"},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.04, 'title' : "■ BIEN-ETRE ANIMAL ET BIODIVERSITE"},
{'titlePosiX' : -0.43, 'titlePosiY' : 1.03, 'title' : "■ REGLEMENTATION ET CONFORMITE ENVIRONNEMENTALE"},
]
elif item == "Justice climatique et équité":
position = [{'titlePosiX' : 0.1, 'titlePosiY' : 0.96, 'chartWidth': 1500},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.10, 'title' : "Catégories :"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.08, 'title' : "■ AUDIT ET CONSEILS EN DEVELOPPEMENT DURABLE"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.06, 'title' : "■ GESTION DES DECHETS ET POLLUTION"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.04, 'title' : "■ LEGISLATION ET REGLEMENTATION"},
{'titlePosiX' : -0.73, 'titlePosiY' : 1.02, 'title' : "■ SENSIBILISATION ET PROTECTION DE L'ENVIRONNEMENT"},
]
df_studiesSkills = createListStudies(item)[2]
if selectCertification[0] == "All" or len(selectCertification) == 0 or selectCertification is None:
list_studies = createListStudies(item)[0]
lenListStudies = createListStudies(item)[1]
# Ajout de la légende
annotations = [
dict(
x=position[1]['titlePosiX'],
y=position[1]['titlePosiY'],
xref="paper",
yref="paper",
text=position[1]['title'],
showarrow=False,
font=dict(size=12, color="white"),
),
dict(
x=position[2]['titlePosiX'],
y=position[2]['titlePosiY'],
xref="paper",
yref="paper",
text=position[2]['title'],
showarrow=False,
font=dict(size=10, color="#FF69B4"),
),
dict(
x=position[3]['titlePosiX'],
y=position[3]['titlePosiY'],
xref="paper",
yref="paper",
text=position[3]['title'],
showarrow=False,
font=dict(size=10, color="#4169E1"),
),
dict(
x=position[4]['titlePosiX'],
y=position[4]['titlePosiY'],
xref="paper",
yref="paper",
text=position[4]['title'],
showarrow=False,
font=dict(size=10, color="#32CD32"),
),
dict(
x=position[5]['titlePosiX'],
y=position[5]['titlePosiY'],
xref="paper",
yref="paper",
text=position[5]['title'],
showarrow=False,
font=dict(size=10, color="#FFD700"),
),
]
else:
if len(df_studiesSkills[df_studiesSkills['frenchStudyLabel'] == selectCertification[0]]) == 0:
notification = {"visibility":"visible"}
list_studies = selectCertification
lenListStudies = 1
annotations = []
list_skills = createListSkills(item)[0]
matrix = pd.DataFrame(0, index=list_studies, columns=list_skills)
for study in list_studies:
for skills in list_skills:
df = df_studiesSkills[df_studiesSkills['preferredLabel'] == skills]
if study in df.values :
matrix.loc[study, skills] = 1
df_skillsInfo = createInfoSkills(item)
categories = createCategoriesSkills(item)
color_values = matrix.copy()
for col in matrix.columns:
color_values[col] = matrix[col] * categories[col]
# Création du heatmap
fig = go.Figure(data=go.Heatmap(
z=color_values.values,
x=color_values.columns,
y=color_values.index,
colorscale=[
[0, '#242424'],
[0.2, '#242424'],
[0.2, '#FF69B4'], # Rose pour technique
[0.4, '#FF69B4'],
[0.4, '#4169E1'], # Bleu pour management
[0.6, '#4169E1'],
[0.6, '#32CD32'], # Vert pour environnement
[0.8, '#32CD32'],
[0.8, '#FFD700'], # Jaune pour économie
[1.0, '#FFD700']
],
showscale=False,
))
# Ajout des bordures aux cellules
fig.update_traces(
xgap=1,
ygap=1,
)
# Mise en forme
fig.update_layout(
title={
'text': "Skills matrix by study:<br />" + strTheme(item),
'y':position[0]['titlePosiY'],
'x':position[0]['titlePosiX'],
'xanchor': 'center',
'yanchor': 'top'},
xaxis=dict(
side='top',
tickangle=45,
tickfont=dict(size=10),
),
yaxis=dict(
autorange='reversed',
tickfont=dict(size=10),
),
width=position[0]['chartWidth'],
height= 400 + lenListStudies * 16,
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=300,
l=600,
r=100,
b=50
),
annotations=annotations,hovermode="x unified",hoverlabel=dict(
bgcolor="black",
font_size=10,
)
)
# Personnalisation du style des axes
fig.update_xaxes(
#showspikes=True,
showgrid=True,
gridwidth=1,
gridcolor='darkgrey',
)
fig.update_yaxes(
#showspikes=True,
showgrid=True,
gridwidth=1,
gridcolor='darkgrey',
)
# Ajout d'un hover template personnalisé
#1: TECHNIQUES AGRICOLES FONDAMENTALES, 2: GESTION ET DÉVELOPPEMENT DURABLE, 3: RÉGLEMENTATION ET POLITIQUE, 4: AGRITOURISME ET SERVICES
hover_text = []
for idx in matrix.index:
row = []
for col in matrix.columns:
if matrix.loc[idx,col] == 1:
if item == "Industrie propre":
category_name = {1: 'TECHNIQUE & OPÉRATIONNEL', 2: 'ENVIRONNEMENT & DURABILITÉ',
3: 'MANAGEMENT & CONSEIL', 4: 'RÉGLEMENTATION & ÉTHIQUE'}[categories[col]]
elif item == "Agriculture plus durable":
category_name = {1: 'TECHNIQUES AGRICOLES FONDAMENTALES', 2: 'GESTION ET DÉVELOPPEMENT DURABLE',
3: 'RÉGLEMENTATION ET POLITIQUE', 4: 'AGRITOURISME ET SERVICES'}[categories[col]]
elif item == "Économie circulaire":
category_name = {1: 'GESTION DE L\'ENERGIE', 2: 'DEVELOPPEMENT DURABLE ET ENVIRONNEMENT',
3: 'TECHNOLOGIES ET SYSTEMES', 4: 'POLITIQUES ET MANAGEMENT'}[categories[col]]
elif item == "Neutralité climatique":
category_name = {1: 'ÉNERGIE', 2: 'CLIMAT ET ENVIRONNEMENT',
3: 'GESTION ET COORDINATION', 4: 'CONSEIL ET EXPERTISE'}[categories[col]]
elif item == "Environnement plus sain":
category_name = {1: 'PROTECTION ET GESTION DE L\'ENVIRONNEMENT', 2: 'ÉNERGIE ET RESSOURCES DURABLES',
3: 'BIEN-ETRE ANIMAL ET BIODIVERSITE', 4: 'REGLEMENTATION ET CONFORMITE ENVIRONNEMENTALE'}[categories[col]]
elif item == "Justice climatique et équité":
category_name = {1: 'AUDIT ET CONSEILS EN DEVELOPPEMENT DURABLE', 2: 'GESTION DES DECHETS ET POLLUTION',
3: 'LEGISLATION ET REGLEMENTATION', 4: 'SENSIBILISATION ET PROTECTION DE L\'ENVIRONNEMENT'}[categories[col]]
broaderSkill = df_skillsInfo.loc[[col]].values.tolist()[0][0]
descriptionSkill = df_skillsInfo.loc[[col]].values.tolist()[0][1]
label_y = idx.replace("(fiche nationale)","").replace("(essential)","").replace("(optional)","")
row.append(
f'<b>🎓 Study: {"<br>".join(textwrap.wrap(label_y,width=50))}</b><br>' +
f'<b>📣 Skill: {col.capitalize()}</b><br>' +
f'🏷️ Category: {category_name}<br>' +
f'💡 Alternative skills: {"<br>".join(textwrap.wrap(broaderSkill,width=50))}<br>' +
f'📚 Skill description: {"<br>".join(textwrap.wrap(descriptionSkill,width=50))}')
else:
row.append('')
hover_text.append(row)
fig.update_traces(
hovertemplate="%{customdata}<extra></extra>",
customdata=hover_text,
)
return fig, notification
### callback for dashboard ###
@callback(
Output(component_id='figBestOfOccupations', component_property='figure'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
Input("mantine-provider", "forceColorScheme"),
running=[(Output("figBestOfSkills", "loading"), True, False)]
)
def create_bestofoc(item, itemDefault, theme):
if item is None:
item = itemDefault
if theme == "dark":
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
else:
template = "ggplot2"
paper_bgcolor = 'rgba(255, 255, 255, 1)'
plot_bgcolor = 'rgba(255, 255, 255, 1)'
df_allSkills = Filterdf(item)
df_occupations = df_allSkills.groupby(['occupationLabel','catGreenDeal']).size().reset_index(name='obs')
df_occupations = df_occupations.sort_values(by=['obs'], ascending=True)
df_occupations = df_occupations.iloc[-20:]
len_occupations = len(df_occupations)
figBestOfOccupations = px.bar(df_occupations, x='obs', y='occupationLabel', color='catGreenDeal', height=600,orientation='h', labels={'occupationLabel':'Green jobs','obs':'nombre'}, color_discrete_sequence=px.colors.sequential.YlGnBu, text_auto=True, template=template)
figBestOfOccupations.update_layout(
title=dict(text="Les " + str(len_occupations) + " métiers les plus cités<br>sur le thème du Green Deal : " + item, font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),font=dict(size=10), clickmode='event+select', autosize=True, showlegend=False)
figBestOfOccupations.update_traces(hovertemplate=df_occupations["occupationLabel"] + '<br>Nombre : %{x}', y=[y[:85] + "..." for y in df_occupations["occupationLabel"]])
return figBestOfOccupations
@callback(
Output(component_id='figBestOfStudies', component_property='figure'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
Input("mantine-provider", "forceColorScheme")
)
def create_bestofst(item, itemDefault, theme):
if item is None:
item = itemDefault
if theme == "dark":
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
else:
template = "ggplot2"
paper_bgcolor = 'rgba(255, 255, 255, 1)'
plot_bgcolor = 'rgba(255, 255, 255, 1)'
df_allSkills = Filterdf(item)
df_allSkills['frenchStudyLabel'] = df_allSkills['frenchStudyLabel'].str.split('|')
df_allSkills = df_allSkills.explode('frenchStudyLabel')
df_allSkills = df_allSkills[df_allSkills['frenchStudyLabel'] != '']
df_studies = df_allSkills.groupby(['frenchStudyLabel','catGreenDeal']).size().reset_index(name='obs')
df_studies = df_studies.sort_values(by=['obs'], ascending=True)
df_studies = df_studies.iloc[-20:]
len_studies = len(df_studies)
figBestOfStudies = px.bar(df_studies, x='obs', y='frenchStudyLabel', color='catGreenDeal', height=600,orientation='h', labels={'frenchStudyLabel':'French UGE Studies','obs':'nombre'}, color_discrete_sequence=px.colors.sequential.YlGnBu, text_auto=True, template=template)
figBestOfStudies.update_layout(
title=dict(text="Les " + str(len_studies) + " formations UGE les plus citées<br>sur le thème du Green Deal : " + item, font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),font=dict(size=10), clickmode='event+select', autosize=True, showlegend=False)
figBestOfStudies.update_traces(hovertemplate=df_studies["frenchStudyLabel"] + '<br>Nombre : %{x}', y=[y[:85] + "..." for y in df_studies["frenchStudyLabel"]])
return figBestOfStudies
@callback(
Output(component_id='figBestOfSkills', component_property='figure'),
Output(component_id='figBestOfAllSkills', component_property='figure'),
#Input('figBestOfOccupations', 'selectedData'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
Input("mantine-provider", "forceColorScheme"),
)
def create_bestofsk(item, itemDefault, theme):
if item is None:
item = itemDefault
if theme == "dark":
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
else:
template = "ggplot2"
paper_bgcolor = 'rgba(255, 255, 255, 1)'
plot_bgcolor = 'rgba(255, 255, 255, 1)'
df_allSkills = Filterdf(item)
#options = []
#if selectedData is not None and type(selectedData['points'][0]['y']) == str:
# options.append(selectedData['points'][0]['y'][:-3])
# customOccupation = selectedData['points'][0]['y'][:-3]
#else:
# options = df_allSkills['occupationLabel'].values.tolist()
# customOccupation = ''
#df_allSkills = df_allSkills[df_allSkills['occupationLabel'].isin(options)]
df_skills = df_allSkills.groupby(['preferredLabel','catGreenDeal']).size().reset_index(name='obs')
df_skills = df_skills.sort_values(by=['obs'], ascending=True)
df_skills = df_skills.iloc[-20:]
len_skills = len(df_skills)
figBestOfSkills = px.bar(df_skills, x='obs', y='preferredLabel', color='catGreenDeal', height=600,orientation='h', labels={'preferredLabel':'Green skills','obs':'nombre'}, color_discrete_sequence=px.colors.sequential.YlGnBu, text_auto=True, template=template)
figBestOfSkills.update_layout(
title=dict(text="Les " + str(len_skills) + " compétences les plus citées<br>sur le thème du Green Deal : " + item, font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),font=dict(size=10),autosize=True, showlegend=False)
figBestOfSkills.update_traces(hovertemplate=df_skills["preferredLabel"] + '<br>Nombre : %{x}', y=[y[:85] + "..." for y in df_skills["preferredLabel"]])
#if customOccupation != '':
# figBestOfSkills.add_annotation(x=-0.9, y=1.0, xanchor='left', yanchor='bottom',
# xref='paper', yref='paper', showarrow=False, align='left',
# text='<b>{}</b>'.format(customOccupation),font=dict(size=10))
return figBestOfSkills, figBestOfSkills
@callback(
Output(component_id='tableauGreenSkills', component_property='children'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
Input("mantine-provider", "forceColorScheme"),
)
def create_tableau(item, itemDefault, theme):
if item is None:
item = itemDefault
if theme == "dark":
style_header = {
'fontFamily': "'Inter', sans-serif",
'fontSize': '10px',
'backgroundColor': 'rgb(30, 30, 30)',
'color': 'white'
}
style_data={
'fontFamily': "'Inter', sans-serif",
'fontSize': '10px',
'backgroundColor': 'rgb(50, 50, 50)',
'color': 'white'
}
style_tooltip='background-color: black; font-family: "Inter", sans-serif; font-size:10px; color: white'
else:
style_header = {
'fontFamily': "'Inter', sans-serif",
'fontSize': '10px',
'backgroundColor': 'transparent',
'color': 'black'
}
style_data={
'fontFamily': "'Inter', sans-serif",
'fontSize': '10px',
'backgroundColor': 'transparent',
'color': 'black'
}
style_tooltip='background-color: black; font-family: "Inter", sans-serif; font-size:10px; color: black'
######## Tableau des Green Skills ########
df = Filterdf(item)
df_tableau = df[['preferredLabel','broaderConceptPT','descriptionSkill','occupationLabel','altLabels','descriptionOccupation','frenchStudyLabel']].copy()
dictHeader = {'preferredLabel': 'Green Skills','broaderConceptPT': 'Related Green Skills','descriptionSkill': 'Green Skills description','occupationLabel':'Occupations','altLabels':'Related Occupations','descriptionOccupation':'Occupation description', 'frenchStudyLabel':'French UGE Studies'}
df_tableau.rename(columns=dictHeader,inplace=True)
tableau_greenSkills = dash_table.DataTable(
data=df_tableau.to_dict('records'),
sort_action='native',
columns=[{'id': c, 'name': c, 'presentation': 'markdown'} if c == 'Lien' else {'id': c, 'name': c} for c in df_tableau.columns],
filter_action="native",
filter_options={"placeholder_text": "Filter column..."},
page_action='native',
page_current= 0,
page_size= 10,
style_header=style_header,
style_data=style_data,
style_cell_conditional=[
{'if': {'column_id': 'Green Skills'},
'backgroundColor': 'lightblue', 'color': 'lightblue'},
{'if': {'column_id': 'Occupations'},
'backgroundColor': 'lightblue', 'color': 'lightblue'},
],
style_table={'overflowX': 'auto'},
style_cell={
'overflow': 'hidden',
'textOverflow': 'ellipsis',
'maxWidth': 0,
},
tooltip_data=[
{
column: {'value': str(value), 'type': 'markdown'}
for column, value in row.items()
} for row in df_tableau.to_dict('records')
],
css=[{
'selector': '.dash-table-tooltip',
'rule': style_tooltip
},{
'selector': '.dash-table-tooltip > p',
'rule': style_tooltip
}],
tooltip_delay=0,
tooltip_duration=None
)
return tableau_greenSkills
@callback(
Output("modal-description-study", "opened"),
Input('figStudies', 'clickData'),
Input('mapCertification', 'n_clicks'),
State("modal-description-study", "opened"),
prevent_initial_call=True,
)
def displayModalStudy(clickData, n_click, opened):
if len(clickData['points'][0]['y']) > 0 or n_click > 0:
return not opened
else:
return opened
@callback(
Output(component_id='modal-description-certification', component_property='children'),
Output('storCertification', 'data'),
Input('figStudies', 'clickData'),
)
def displayDescriptionCertification(clickData):
if len(clickData['points'][0]['y']) > 0:
description = f"""**Fiche Formation** :\n\n{getFicheCertification(clickData)}"""
return description, clickData['points'][0]['y']
else:
return f"""Génération de la fiche formation!""", f"""Génération de la cartographie de la formation!"""
@callback(
Output("modal-description", "opened"),
Input('figOccupations', 'clickData'),
Input('emploisFT', 'n_clicks'),
Input('mapOccupation', 'n_clicks'),
State("modal-description", "opened"),
prevent_initial_call=True,
)
def displayModal(clickData, n_click, n_click_occupation, opened):
if len(clickData['points'][0]['y']) > 0 or n_click > 0 or n_click_occupation > 0:
return not opened
else:
return opened
@callback(
Output(component_id='modal-description-title', component_property='children'),
Output('storEmplois', 'data'),
Input('figOccupations', 'clickData'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
)
def displayDescription(clickData, item, itemDefault):
if item is None:
item = itemDefault
if len(clickData['points'][0]['y']) > 0:
description = f"""**Fiche Métier** : {getFicheMetier(clickData, item)}"""
return description, clickData['points'][0]['y']
else:
return f"""Génération de la fiche métier!""", f"""Génération de la liste des emplois!"""
@callback(
Output("modal-description-mapOccupation", "opened"),
Input('mapOccupation', 'n_clicks'),
State("modal-description-mapOccupation", "opened"),
prevent_initial_call=True,
)
def displayModalMapOccupation(n_click, opened):
if n_click > 0:
return not opened
else:
return opened
@callback(
Output(component_id='figmapOccupation', component_property='figure'),
Input('mapOccupation', 'n_clicks'),
Input('storEmplois', 'data'),
)
def displayDescriptionOccupation(n_click,data):
if n_click is not None or n_click > 0:
return cartoMapOccupation(data)
else:
return f"""Génération de la cartographie formation!"""
@callback(
Output("modal-description-mapCertification", "opened"),
Input('mapCertification', 'n_clicks'),
State("modal-description-mapCertification", "opened"),
prevent_initial_call=True,
)
def displayModalMapCertification(n_click, opened):
if n_click > 0:
return not opened
else:
return opened
@callback(
Output(component_id='figmapCertification', component_property='figure'),
Input('mapCertification', 'n_clicks'),
Input('storCertification', 'data'),
)
def displayDescriptionCertification(n_click,data):
if n_click is not None or n_click > 0:
return cartoMapCertification(data)
else:
return f"""Génération de la cartographie formation!"""
@callback(
Output("modal-description-emploisFT", "opened"),
Input('emploisFT', 'n_clicks'),
State("modal-description-emploisFT", "opened"),
prevent_initial_call=True,
)
def displayModalEmplois(n_click, opened):
if n_click > 0:
return not opened
else:
return opened
@callback(
Output(component_id='modal-liste-emploisFT', component_property='children'),
Input('emploisFT', 'n_clicks'),
Input('storEmplois', 'data'),
)
def displayDescriptionEmplois(n_click,data):
if n_click is not None or n_click > 0:
return f"""**Liste des emplois France Travail**\n\n***Métier : {data}***\n\n{listEmploisFT(data)}"""
else:
return f"""Génération de la liste des emplois!"""
@callback(
Output(component_id='figMetier', component_property='figure'),
Input('figStudies', 'clickData'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
)
def displayDescriptionCertification(clickData, item, itemDefault):
if item is None:
item = itemDefault
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
context = clickData['points'][0]['customdata']
df = similarityStudyOccupation(context)
df = df.drop_duplicates(subset=['metier'])
df = df.sort_values(by=['score'], ascending=True)
fig = px.bar(df, x='score', y='metier', orientation='h', width=600, height=600, color_discrete_sequence=px.colors.sequential.YlGnBu, text_auto=True, template=template)
fig.update_layout(
title=dict(text="Similitude (score > 0.7) des métiers,<br />avec la formation : " + clickData['points'][0]['y'] + "<br />et le thème du Green Deal : " + item, font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),font=dict(size=10),autosize=True, showlegend=False)
fig.update_traces(hovertemplate=df["metier"] + '<br>Score : %{x}', y=[y[:75] + "..." for y in df["metier"]])
return fig
@callback(
Output(component_id='figStudyNQF7', component_property='figure'),
Output(component_id='figStudyNQF6', component_property='figure'),
Input('figOccupations', 'clickData'),
Input('storTheme', 'data'),
Input('storThemeDefault', 'data'),
)
def displayDescription(clickData, item, itemDefault):
if item is None:
item = itemDefault
template = "plotly_dark"
paper_bgcolor = 'rgba(36, 36, 36, 1)'
plot_bgcolor = 'rgba(36, 36, 36, 1)'
context = clickData['points'][0]['customdata']
df_NQF7 = similarityOccupationStudy(context)[0]
df_NQF7 = df_NQF7.drop_duplicates(subset=['formation'])
df_NQF6 = similarityOccupationStudy(context)[1]
df_NQF6 = df_NQF6.drop_duplicates(subset=['formation'])
df_NQF7 = df_NQF7.sort_values(by=['score'], ascending=True)
df_NQF6 = df_NQF6.sort_values(by=['score'], ascending=True)
fig_NQF7 = px.bar(df_NQF7, x='score', y='formation', orientation='h', width=600, color_discrete_sequence=px.colors.sequential.YlGnBu, text_auto=True, template=template)
fig_NQF7.update_layout(
title=dict(text="Similitude (score > 0.7) des formations de niveau 7,<br />avec le métier : " + clickData['points'][0]['y'] + "<br />et le thème du Green Deal : " + item, font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),font=dict(size=10),autosize=True, showlegend=False)
fig_NQF7.update_traces(hovertemplate=df_NQF7["formation"] + '<br>Score : %{x}<br>Niveau : ' + df_NQF7["niveau"], y=[y[:75] + "..." for y in df_NQF7["formation"]])
fig_NQF6 = px.bar(df_NQF6, x='score', y='formation', orientation='h', width=600, color_discrete_sequence=px.colors.sequential.YlGnBu, text_auto=True, template=template)
fig_NQF6.update_layout(
title=dict(text="Similitude (score > 0.7) des formations de niveau 6,<br />avec le métier : " + clickData['points'][0]['y'] + "<br />et le thème du Green Deal : " + item, font=dict(size=10)),
paper_bgcolor=paper_bgcolor,
plot_bgcolor=plot_bgcolor,
margin=dict(
t=100
),font=dict(size=10),autosize=True, showlegend=False)
fig_NQF6.update_traces(hovertemplate=df_NQF6["formation"] + '<br>Score : %{x}<br>Niveau : ' + df_NQF6["niveau"], y=[y[:75] + "..." for y in df_NQF6["formation"]])
return fig_NQF7, fig_NQF6
########### IA Chatbot ###########
@app.callback(
Output("display-conversation", "children"),
[Input("store-conversation", "data")]
)
def update_display(chat_history):
return [
textbox(x, box="user") if i % 2 == 0 else textbox(x, box="AI")
for i, x in enumerate(chat_history.split("<split>")[:-1])
]
@app.callback(
Output("user-input", "value"),
[Input("submit", "n_clicks"), Input("user-input", "n_submit")],
)
def clear_input(n_clicks, n_submit):
return ""
@app.callback(
[Output("store-conversation", "data"), Output("loading-component", "children")],
[Input("submit", "n_clicks"), Input("user-input", "n_submit"), Input("storTheme", "data")],
[State("user-input", "value"), State("store-conversation", "data")],
)
#def run_chatbot(n_clicks, n_submit, user_input, chat_history, array_value):
def run_chatbot(n_clicks, n_submit, item, user_input, chat_history):
if n_clicks == 0 and n_submit is None:
return "", None
if user_input is None or user_input == "":
return chat_history, None
if item is None or item == "":
item = "Industrie propre"
#df_FT = API_France_Travail(array_value)
#df_FT_Select = df_FT[['intitule','typeContratLibelle','experienceLibelle','competences','description','qualitesProfessionnelles','salaire','lieuTravail','formations']].copy()
#list_FT = df_FT_Select.values.tolist()
#context = ''
#for i in range(0,len(list_FT)):
#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"
#context = df_FT.to_string(index=False)
#context = "Emplois"
#context = DfToStr(item)
#context = context.replace(" ","").replace("|","; ")
template = """<s>[INST] Vous êtes un ingénieur pédagogique de l'enseignement supérieur et vous êtes doué pour faire des analyses des formations de l'enseignement supérieur et de faire le rapprochement entre les compétences professionnelles vertes relatives à la transition écologique attendues par le marché de l'emploi, et les métiers verts émergents et ou relatifs à la transition écologique, extraits de l'ESCO. En fonction des informations suivantes et du contexte suivant seulement et strictement, répondez en langue française strictement à la question ci-dessous, en 5000 mots au moins. Lorsque cela est possible, cite les sources du contexte. 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.
Définition : l'acronyme ESCO signifie European Skills Competences and Occupation. Il s'agit d'une classification multilingue qui identifie et catégorise les compétences, les qualifications et les occupations pertinentes pour le marché du travail et l'éducation de l'Union Européenne.
Répondez à la question ci-dessous à partir du contexte relatif aux objectifs du Green Deal:
Contexte : {context}
Question : {question} [/INST] </s>
"""
#context_p = "Définition : l'acronyme ESCO signifie European Skills Competences and Occupation. Il s'agit d'une classification multilingue qui identifie et catégorise les compétences, les qualifications et les occupations pertinentes pour le marché du travail et l'éducation de l'Union Européenne.\n" + context[:93000]
name = "Mistral"
chat_history += f"Vous: {user_input}<split>{name}:"
model_input = template + chat_history.replace("<split>", "\n")
#model_input = template
#prompt = PromptTemplate(template=model_input, input_variables=["question","context"])
client = OpenAI(base_url=os.environ['BASEURL_RENNES_LONGCONTEXT_API_KEY'], api_key=os.environ['ENDPOINT_RENNES_LONGCONTEXT_API_KEY'])
retriever = Retriever(user_input + ", en relation avec " + item)[1]
context_user = "\n\n\n".join([item[0].page_content for item in retriever])
prompt = model_input.format(question=user_input + "Réponds au format markdown, en 4000 mots, à la question, seulement en fonction du contexte Green Deal suivant : " + item + ".", context=context_user)
completion = client.chat.completions.create(
model="gpt-oss-120b",
messages = [
{"role": "user", "content": prompt}
],
temperature=0.3
)
chat_history += f"{completion.choices[0].message.content.strip()}<split>"
return chat_history, None
if __name__ == '__main__':
#app.run(debug=True, threaded=True)
app.run_server(debug=True)