PLANDACTIONIFSV8 / appquestOK.py
MMOON's picture
Rename app.py to appquestOK.py
6497efc verified
import streamlit as st
import pandas as pd
from pocketgroq import GroqProvider
# Configuration de la page
st.set_page_config(layout="wide")
# Ajouter les styles CSS personnalisés
st.markdown(
"""
<style>
.main-header {
font-size: 24px;
font-weight: bold;
color: #004080;
text-align: center;
margin-bottom: 25px;
}
.dataframe-container {
margin-bottom: 20px;
}
.banner {
background-image: url('https://github.com/M00N69/BUSCAR/blob/main/logo%2002%20copie.jpg?raw=true');
background-size: cover;
height: 200px;
background-position: center;
margin-bottom: 20px;
}
div.stButton > button {
background-color: #004080;
color: white;
border-radius: 5px;
border: none;
padding: 8px 16px;
font-weight: bold;
margin-top: 10px;
}
div.stButton > button:hover {
background-color: #0066cc;
color: white;
}
/* Style pour l'expander */
.st-emotion-cache-1h9usn1 {
background-color: #e0f7fa !important; /* Fond bleu clair pour l'expander */
border: 1px solid #004080 !important; /* Bordure bleu foncé */
border-radius: 5px;
}
/* Style pour le formulaire */
.stForm {
background-color: #f0f8ff; /* Fond clair pour le formulaire */
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
}
</style>
""",
unsafe_allow_html=True
)
# Ajouter la bannière
st.markdown('<div class="banner"></div>', unsafe_allow_html=True)
# Initialiser PocketGroq
def get_groq_provider():
if not st.session_state.get('api_key'):
st.error("Veuillez entrer votre clé API Groq.")
return None
return GroqProvider(api_key=st.session_state.api_key)
# Charger le fichier Excel avec le plan d'action
def load_action_plan(uploaded_file):
try:
action_plan_df = pd.read_excel(uploaded_file, header=11)
action_plan_df = action_plan_df[["requirementNo", "requirementText", "requirementExplanation"]]
action_plan_df.columns = ["Numéro d'exigence", "Exigence IFS Food 8", "Explication (par l’auditeur/l’évaluateur)"]
return action_plan_df
except Exception as e:
st.error("Erreur lors de la lecture du fichier: {}".format(str(e)))
return None
# Récupérer les informations du guide
def get_guide_info(num_exigence, guide_df):
try:
guide_row = guide_df[guide_df['NUM_REQ'].str.contains(str(num_exigence), na=False)]
if guide_row.empty:
st.error("Aucune correspondance trouvée pour le numéro d'exigence : {}".format(num_exigence))
return None
return guide_row.iloc[0]
except Exception as e:
st.error("Erreur lors de la recherche dans le guide : {}".format(str(e)))
return None
# Générer des questions dynamiques adaptées
def generate_dynamic_questions(guide_row, non_conformity):
exigence_text = non_conformity['Exigence IFS Food 8']
audit_comment = non_conformity['Explication (par l’auditeur/l’évaluateur)']
bonnes_pratiques = guide_row.get('Good practice', 'Non spécifié')
elements_a_verifier = guide_row.get('Elements to check', 'Non spécifié')
exemple_questions = guide_row.get('Example questions', 'Non spécifié')
# Questions adaptées en fonction de l'exigence, des bonnes pratiques et du commentaire de l'auditeur
questions = [
"Quel est le processus actuel pour respecter l'exigence : {} ?".format(exigence_text),
"Selon le commentaire de l'auditeur, quels aspects spécifiques du processus ont été identifiés comme non conformes ?",
"Comment les bonnes pratiques suivantes sont-elles appliquées dans votre organisation : {} ?".format(bonnes_pratiques),
"Quels sont les éléments à vérifier pour cette exigence : {} ?".format(elements_a_verifier),
"Avez-vous identifié des lacunes dans les ressources ou les outils disponibles pour respecter cette exigence ?",
]
return questions
# Générer une recommandation avec Groq et CoT
def generate_ai_recommendation_groq(non_conformity, guide_row, additional_context):
groq = get_groq_provider()
if not groq:
return "Erreur: clé API non fournie."
# Construire le prompt avec des questions ciblées
prompt = """
En tant qu'expert en IFS Food 8 et en technologies alimentaires, pour chaque non-conformité constatée lors d'un audit, veuillez fournir :
- une recommandation de correction : action immédiate visant à éliminer la non-conformité détectée en s'assurant qu'elle est adaptée au domaine d'activités du site industriel.
- le type de preuve attendu : élément tangible (photo, document,...) démontrant la mise en place de la correction.
- l'analyse de la cause probable : investigation approfondie pour identifier l'origine de la non-conformité en t'assurant que l'analyse est cohérente avec l'acvité du site (industrie alimentaire).
- une recommandation d'action corrective : mesure à prendre pour éliminer la cause racine et prévenir la réapparition de la non-conformité.
Points importants à prendre en compte :
- Distinction correction / action corrective : La correction est une action immédiate pour rectifier une situation, tandis que l'action corrective vise à éliminer la cause racine et à empêcher la récurrence.
- Pertinence et exhaustivité : Les recommandations de correction et d'action corrective doivent être adaptées à la non-conformité et traiter tous les aspects du problème.
Voici une non-conformité issue d'un audit IFS Food 8 :
- Exigence : {}
- Description : {}
- Constat détaillé : {}
Basé sur le guide IFSv8 pour cette exigence :
- Bonnes pratiques : {}
- Éléments à vérifier : {}
- Questions exemples : {}
Informations supplémentaires fournies par l'utilisateur :
- {}
Veuillez fournir une recommandation complète avec analyse détaillée en appliquant une approche 'Chain of Thought' (réflexion étape par étape).
""".format(
non_conformity["Numéro d'exigence"],
non_conformity["Exigence IFS Food 8"],
non_conformity["Explication (par l’auditeur/l’évaluateur)"],
guide_row['Good practice'],
guide_row['Elements to check'],
guide_row['Example questions'],
additional_context
)
try:
return groq.generate(prompt, max_tokens=1500, temperature=0, use_cot=True)
except Exception as e:
st.error("Erreur lors de la génération de la recommandation : {}".format(str(e)))
return None
# Fonction principale
def main():
st.markdown('<div class="main-header">Assistant VisiPilot pour Plan d\'Actions IFS</div>', unsafe_allow_html=True)
# Initialiser les états de session
if 'recommendation_expanders' not in st.session_state:
st.session_state['recommendation_expanders'] = {}
if 'responses' not in st.session_state:
st.session_state['responses'] = {}
if 'show_popup' not in st.session_state:
st.session_state['show_popup'] = {}
if 'current_index' not in st.session_state:
st.session_state['current_index'] = None
# Clé API Groq
api_key = st.text_input("Entrez votre clé API Groq :", type="password")
if api_key:
st.session_state.api_key = api_key
# Télécharger le fichier Excel
uploaded_file = st.file_uploader("Téléchargez votre plan d'action (fichier Excel)", type=["xlsx"])
if uploaded_file:
action_plan_df = load_action_plan(uploaded_file)
if action_plan_df is not None:
guide_df = pd.read_csv("https://raw.githubusercontent.com/M00N69/Action-planGroq/main/Guide%20Checklist_IFS%20Food%20V%208%20-%20CHECKLIST.csv")
st.write("## Plan d'Action IFS")
for index, row in action_plan_df.iterrows():
cols = st.columns([1, 4, 4, 2])
cols[0].write(row["Numéro d'exigence"]) # Utilisation du bon nom de colonne
cols[1].write(row["Exigence IFS Food 8"])
cols[2].write(row["Explication (par l’auditeur/l’évaluateur)"])
# Bouton pour générer les recommandations
if cols[3].button("Générer Recommandation", key="generate_{}".format(index)):
st.session_state['current_index'] = index
st.session_state['show_popup'][index] = True
# Afficher le popup si nécessaire
if st.session_state.get('show_popup', {}).get(index, False):
guide_row = get_guide_info(row["Numéro d'exigence"], guide_df)
if guide_row is not None:
questions = generate_dynamic_questions(guide_row, row)
with st.form(key="form_{}".format(index)):
st.write("Veuillez répondre aux questions suivantes pour fournir plus de contexte :")
responses = [st.text_input(question) for question in questions]
if st.form_submit_button("Soumettre"):
additional_context = "\n".join(responses)
recommendation_text = generate_ai_recommendation_groq(row, guide_row, additional_context)
st.session_state['recommendation_expanders'][index] = recommendation_text
st.session_state['show_popup'][index] = False
st.session_state['responses'][index] = responses
# Afficher la recommandation si elle existe
if index in st.session_state['recommendation_expanders']:
expander = st.expander("Recommandation pour {}".format(row["Numéro d'exigence"]), expanded=True)
expander.markdown(st.session_state['recommendation_expanders'][index])
# Afficher les réponses si elles existent
if index in st.session_state['responses']:
st.write("Réponses fournies :")
for i, response in enumerate(st.session_state['responses'][index]):
st.write("Question {}: {}".format(i + 1, response))
if __name__ == "__main__":
main()