gestionnaire_specialites.py — garde-fou et briques de connaissance

Bienvenue sur CFTPfr.fr Forums modules gestionnaire_specialites.py — garde-fou et briques de connaissance

  • Ce sujet est vide.
Affichage de 1 message (sur 1 au total)
  • Auteur
    Messages
  • #254
    Mario Da Conceicao
    Maître des clés

    Nouveau composant du 01/08/2026 — gestionnaire des spécialités de MIRA, avec garde-fou de validation utilisateur intégré. Ce module ne dépend pas encore du moteur neuronal (qui reste à choisir selon le matériel) — il gère juste le cycle de vie d’une "brique" : proposée → en attente → validée par toi → active.

    Principe du garde-fou

    Une spécialité passe par 3 états :

    1. Proposée — MIRA (ou toi) crée une fiche dans telechargements/, jamais utilisée automatiquement
    2. En attente — reste là tant que tu n’as pas donné ton accord explicite
    3. Active — seulement après valider_specialite(), appelé uniquement par une action utilisateur explicite (jamais par MIRA elle-même)
    import json
    import os
    import shutil
    from pathlib import Path
    from datetime import datetime
    
    BASE_DIR = Path(__file__).resolve().parent
    SPECIALITES_DIR = BASE_DIR / "specialites"
    TELECHARGEMENTS_DIR = BASE_DIR / "telechargements"
    REGISTRE_FILE = SPECIALITES_DIR / "manifest.json"
    
    class GestionnaireSpecialites:
        """
        Gère les modules de connaissance spécialisés de MIRA ("briques").
        Une brique ne devient active qu'après validation explicite de l'utilisateur.
        """
    
        def __init__(self):
            SPECIALITES_DIR.mkdir(parents=True, exist_ok=True)
            TELECHARGEMENTS_DIR.mkdir(parents=True, exist_ok=True)
            if not REGISTRE_FILE.exists():
                self._sauvegarder_registre({"specialites": []})
    
        def _charger_registre(self):
            with open(REGISTRE_FILE, "r", encoding="utf-8") as f:
                return json.load(f)
    
        def _sauvegarder_registre(self, data):
            with open(REGISTRE_FILE, "w", encoding="utf-8") as f:
                json.dump(data, f, indent=4, ensure_ascii=False)
    
        def proposer_nouvelle_specialite(self, nom, description, documents_sources=None):
            """
            Étape 1 : MIRA propose une nouvelle spécialité (ex: après avoir téléchargé
            une notice). Elle est créée EN ATTENTE, jamais active automatiquement.
            """
            dossier_attente = TELECHARGEMENTS_DIR / nom
            dossier_attente.mkdir(parents=True, exist_ok=True)
    
            fiche = {
                "nom": nom,
                "type": "specialite_logiciel",
                "version": "1.0",
                "description": description,
                "source_documents": documents_sources or [],
                "date_creation": datetime.now().isoformat(timespec="seconds"),
                "valide_par_utilisateur": False
            }
    
            with open(dossier_attente / "manifest.json", "w", encoding="utf-8") as f:
                json.dump(fiche, f, indent=4, ensure_ascii=False)
    
            return f"Nouvelle spécialité '{nom}' préparée dans telechargements/. En attente de ta validation."
    
        def lister_en_attente(self):
            """Liste les spécialités préparées mais pas encore validées."""
            en_attente = []
            for dossier in TELECHARGEMENTS_DIR.iterdir():
                manifest_path = dossier / "manifest.json"
                if manifest_path.exists():
                    with open(manifest_path, "r", encoding="utf-8") as f:
                        en_attente.append(json.load(f))
            return en_attente
    
        def valider_specialite(self, nom):
            """
            Étape 2 : L'UTILISATEUR valide explicitement une spécialité.
            C'est le seul moyen de la faire passer d'en_attente vers active.
            Cette fonction ne doit JAMAIS être appelée automatiquement par MIRA.
            """
            dossier_attente = TELECHARGEMENTS_DIR / nom
            manifest_path = dossier_attente / "manifest.json"
            if not manifest_path.exists():
                return f"Aucune spécialité en attente nommée '{nom}'."
    
            with open(manifest_path, "r", encoding="utf-8") as f:
                fiche = json.load(f)
            fiche["valide_par_utilisateur"] = True
            fiche["date_validation"] = datetime.now().isoformat(timespec="seconds")
    
            dossier_final = SPECIALITES_DIR / nom
            shutil.move(str(dossier_attente), str(dossier_final))
    
            with open(dossier_final / "manifest.json", "w", encoding="utf-8") as f:
                json.dump(fiche, f, indent=4, ensure_ascii=False)
    
            registre = self._charger_registre()
            registre["specialites"].append({"nom": nom, "description": fiche["description"]})
            self._sauvegarder_registre(registre)
    
            return f"Spécialité '{nom}' validée et activée."
    
        def rejeter_specialite(self, nom):
            """L'utilisateur peut refuser/supprimer une proposition en attente."""
            dossier_attente = TELECHARGEMENTS_DIR / nom
            if dossier_attente.exists():
                shutil.rmtree(dossier_attente)
                return f"Spécialité '{nom}' rejetée et supprimée."
            return f"Aucune spécialité en attente nommée '{nom}'."
    
        def lister_actives(self):
            """Liste les spécialités déjà validées et actives."""
            return self._charger_registre()["specialites"]
    
        def consulter_specialite(self, nom, mot_cle=None):
            """
            Recherche dans les documents d'une spécialité active.
            Version simple par mots-clés pour l'instant — à remplacer par une
            vraie recherche sémantique une fois le moteur neuronal choisi et
            installé (dépend du matériel disponible).
            """
            dossier = SPECIALITES_DIR / nom / "documents"
            if not dossier.exists():
                return None
            resultats = []
            for fichier in dossier.glob("*.txt"):
                contenu = fichier.read_text(encoding="utf-8", errors="replace")
                if not mot_cle or mot_cle.lower() in contenu.lower():
                    resultats.append({"fichier": fichier.name, "extrait": contenu[:500]})
            return resultats

    Dossiers à créer (à faire sur le PC/la clé quand tu es prêt)

    mira_ai/ia_neuronale/
    ├── moteur/              (vide pour l'instant — dépend du modèle choisi)
    ├── modeles/              (vide pour l'instant — dépend du modèle choisi)
    ├── specialites/
    │   └── manifest.json     (créé automatiquement au premier lancement)
    └── telechargements/      (créé automatiquement au premier lancement)

    Pas besoin de créer manuellement specialites/ ni telechargements/ — le code les crée tout seul au premier lancement (mkdir(parents=True, exist_ok=True)). Seuls moteur/ et modeles/ restent à préparer une fois le modèle choisi.

Affichage de 1 message (sur 1 au total)
  • Vous devez être connecté pour répondre à ce sujet.
Retour en haut