|
|
import streamlit as st |
|
|
from PyPDF2 import PdfReader |
|
|
import pandas as pd |
|
|
from groq import Groq |
|
|
from referentials import REFERENTIALS |
|
|
|
|
|
|
|
|
st.set_page_config(layout="wide", page_title="Analyse de CV - GFSI (Version 25.11)", page_icon="📄") |
|
|
|
|
|
|
|
|
def get_groq_client(api_key): |
|
|
""" |
|
|
Initialise et renvoie un client Groq avec la clé API. |
|
|
Vérifie que la clé API est valide avant de renvoyer le client. |
|
|
""" |
|
|
try: |
|
|
return Groq(api_key=api_key) |
|
|
except Exception as e: |
|
|
st.error(f"Erreur lors de la configuration du client Groq : {str(e)}") |
|
|
return None |
|
|
|
|
|
|
|
|
def extract_text_from_pdf(file): |
|
|
""" |
|
|
Extrait le texte d'un fichier PDF. |
|
|
Renvoie le contenu texte extrait ou signale une erreur. |
|
|
""" |
|
|
try: |
|
|
reader = PdfReader(file) |
|
|
text = " ".join(page.extract_text() for page in reader.pages if page.extract_text()) |
|
|
return text |
|
|
except Exception as e: |
|
|
st.error(f"Erreur lors de l'extraction du texte : {str(e)}") |
|
|
return None |
|
|
|
|
|
|
|
|
def analyze_cv_with_groq(cv_text, referential, groq_client, model="llama-3.3-70b-versatile"): |
|
|
""" |
|
|
Analyse le texte d'un CV par rapport aux exigences d'un référentiel GFSI. |
|
|
Utilise l'API Groq pour générer une analyse détaillée. |
|
|
""" |
|
|
referential_data = REFERENTIALS.get(referential, {}) |
|
|
general_requirements = referential_data.get("General_Requirements", {}) |
|
|
qualifications = referential_data.get("Qualifications", {}) |
|
|
audit_experience = referential_data.get("Audit_Experience", {}) |
|
|
advanced_requirements = referential_data.get("Advanced_Requirements", {}) |
|
|
|
|
|
prompt = f""" |
|
|
Vous êtes un expert en évaluation des compétences selon les référentiels GFSI ({referential}). |
|
|
Analysez ce CV demanière approfondie, sans citer le nom du candidat (toujours faire référence en le nommant : le candidat), pour vérifier sa conformité avec les exigences suivantes : |
|
|
Général : |
|
|
{general_requirements} |
|
|
Qualifications : |
|
|
{qualifications} |
|
|
Expérience en audit : |
|
|
{audit_experience} |
|
|
Exigences avancées : |
|
|
{advanced_requirements} |
|
|
Contenu du CV : |
|
|
{cv_text} |
|
|
Pour chacun des points précédents veiller à bien étudier les expériences et formation réalisées par le candidat car il se peut que les mentions de formations |
|
|
ne soient pas rédigées de manière exacte comme écrites dans ({referential}), évaluer chaque formation du candidat 2 fois. |
|
|
Fournissez une analyse détaillée rédigée en langue française, de manière professionnelle et complète, en identifiant : |
|
|
1. Les exigences remplies. |
|
|
2. Les lacunes ou non-conformités. |
|
|
3. Des recommandations pour combler les lacunes par rapport aux exigences strictes du référentiel. |
|
|
""" |
|
|
|
|
|
try: |
|
|
messages = [ |
|
|
{"role": "system", "content": "Vous êtes un assistant spécialisé dans l'analyse de conformité selon des référentiels GFSI."}, |
|
|
{"role": "user", "content": prompt} |
|
|
] |
|
|
response = groq_client.chat.completions.create( |
|
|
messages=messages, |
|
|
model=model, |
|
|
max_tokens=1000, |
|
|
temperature=0.2 |
|
|
) |
|
|
return response.choices[0].message.content |
|
|
except Exception as e: |
|
|
st.error(f"Erreur lors de l'analyse du CV : {str(e)}") |
|
|
return None |
|
|
|
|
|
|
|
|
def generate_conclusion(analysis): |
|
|
""" |
|
|
Génère une conclusion basée sur l'analyse du CV. |
|
|
Vérifie la présence de "non-conformité" dans le texte pour déterminer si des lacunes existent. |
|
|
""" |
|
|
if "non-conformité" in analysis.lower(): |
|
|
return "Le candidat répond partiellement aux exigences du référentiel sélectionné. Des améliorations spécifiques sont recommandées." |
|
|
else: |
|
|
return "Le candidat satisfait pleinement aux exigences du référentiel sélectionné." |
|
|
|
|
|
|
|
|
def main(): |
|
|
""" |
|
|
Interface principale Streamlit pour l'analyse des CV selon les référentiels GFSI. |
|
|
Permet à l'utilisateur de fournir une clé API, de télécharger un CV, et de sélectionner un référentiel. |
|
|
""" |
|
|
st.title("Analyse de CV selon les Référentiels GFSI (Version 25.11)") |
|
|
|
|
|
st.markdown(""" |
|
|
<div style="background-color:#f0f0f0;padding:10px;border-radius:10px;"> |
|
|
<h3>Bienvenue sur l'outil d'analyse de CV GFSI</h3> |
|
|
<p>Utilisez cet outil pour évaluer un CV selon les référentiels tels que BRCGS, FSSC 22000, et IFS.</p> |
|
|
<ul> |
|
|
<li><strong>Étape 1 :</strong> Entrez votre clé API Groq.</li> |
|
|
<li><strong>Étape 2 :</strong> Téléchargez un CV au format PDF.</li> |
|
|
<li><strong>Étape 3 :</strong> Sélectionnez un référentiel pour effectuer l'analyse.</li> |
|
|
</ul> |
|
|
</div> |
|
|
""", unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
api_key = st.text_input("Entrez votre clé API Groq :", type="password") |
|
|
if not api_key: |
|
|
st.warning("Veuillez entrer votre clé API pour continuer.") |
|
|
return |
|
|
|
|
|
groq_client = get_groq_client(api_key) |
|
|
if not groq_client: |
|
|
return |
|
|
|
|
|
|
|
|
uploaded_file = st.file_uploader("Téléchargez un fichier PDF (CV)", type="pdf") |
|
|
if not uploaded_file: |
|
|
st.info("Veuillez télécharger un fichier PDF pour continuer.") |
|
|
return |
|
|
|
|
|
|
|
|
referential = st.selectbox("Sélectionnez un référentiel", list(REFERENTIALS.keys())) |
|
|
if not referential: |
|
|
st.warning("Veuillez sélectionner un référentiel pour continuer.") |
|
|
return |
|
|
|
|
|
|
|
|
cv_text = extract_text_from_pdf(uploaded_file) |
|
|
if cv_text: |
|
|
st.markdown("### Résultat de l'Analyse") |
|
|
analysis = analyze_cv_with_groq(cv_text, referential, groq_client) |
|
|
if analysis: |
|
|
|
|
|
st.markdown( |
|
|
f""" |
|
|
<div style='font-size:22px;line-height:1.8;margin-top:20px;'> |
|
|
{analysis} |
|
|
</div> |
|
|
""", |
|
|
unsafe_allow_html=True |
|
|
) |
|
|
|
|
|
|
|
|
conclusion = generate_conclusion(analysis) |
|
|
st.markdown( |
|
|
f""" |
|
|
<div style="background-color:#dff0d8;padding:20px;border-radius:10px;margin-top:30px;font-size:22px;line-height:1.8;"> |
|
|
<strong>Conclusion :</strong> {conclusion} |
|
|
</div> |
|
|
""", |
|
|
unsafe_allow_html=True |
|
|
) |
|
|
else: |
|
|
st.error("Une erreur est survenue lors de l'analyse du CV. Veuillez réessayer.") |
|
|
else: |
|
|
st.error("Impossible d'extraire le texte du CV. Vérifiez que le fichier PDF est lisible.") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |
|
|
|