# utils/vector_store.py — Le Socle Technique Unique """ Module central de gestion de la base de données vectorielle FAISS pour l'Assistant de Caisse projet14 objectif1. Anciennement "coquille vide", ce script centralise désormais la logique de chargement de l'index et de formatage des documents afin d'alléger 'streamlit_app.py' et 'MistralChat.py', évitant ainsi toute duplication de logique LangChain (Phase 4 : Optimisation). """ import streamlit as st # Embaucher un conseiller expert (l’IA Mistral) qui sait comprendre et guider sur les procédures de caisse from langchain_mistralai import MistralAIEmbeddings # Organiser les fiches de procédures dans des casiers intelligents (FAISS) from langchain_community.vectorstores import FAISS # Utilisation de la configuration centralisée from utils.config import ( MISTRAL_API_KEY, FAISS_INDEX_DIR, EMBEDDING_MODEL ) def load_vector_store(): """ Charge la base de données vectorielle FAISS existante en utilisant les chemins configurés. Cette responsabilité a été déportée ici pour respecter la séparation des responsabilités (logique d’UI vs logique de stockage vectoriel). """ if not MISTRAL_API_KEY: st.error("Clé API Mistral manquante dans la configuration.") return None # Etape 2 : Chargement de l'Index Vectoriel # Didier : d'après IA il est CRUCIAL d'utiliser les mêmes embeddings que lors de l'indexation embeddings = MistralAIEmbeddings( mistral_api_key=MISTRAL_API_KEY, model=EMBEDDING_MODEL ) if not FAISS_INDEX_DIR.exists(): st.error(f"L'index FAISS est introuvable dans {FAISS_INDEX_DIR}. Veuillez lancer indexer.py.") return None try: # allow_dangerous_deserialization est nécessaire pour charger les fichiers .pkl de l'index local vector_store = FAISS.load_local( str(FAISS_INDEX_DIR), embeddings, allow_dangerous_deserialization=True ) return vector_store except Exception as e: st.error(f"Erreur lors du chargement de l'index : {e}") return None def format_docs(docs): """ Etape 6 : Création de la Chaîne de Formatage des Documents. Didier : Mutation majeure pour le Projet14 objectif1. On extrait les métadonnées sémantiques de nos blocs de procédures (Processus, Action, Écran de départ) au lieu des anciens tags iCalendar. """ formatted = [] for d in docs: # Reprise dynamique des clés de métadonnées du Front Matter gérées par le md_parser header = f"--- PROCESSUS : {d.metadata.get('process', 'Général')} | ACTION MÉTIER : {d.metadata.get('action', 'N/A')} ---" details = f"Écran de départ: {d.metadata.get('ecran_depart', 'N/A')} | Mots-clés: {d.metadata.get('mots_cles', 'N/A')}" content = f"Instructions de l'interface :\n{d.page_content}" formatted.append(f"{header}\n{details}\n{content}") return "\n\n".join(formatted)