noyau_phase3.py — noyau Phase 3 outils déterministes (22/10/2026)

–– coding: utf-8 ––

"""
MIRA — Noyau Phase 3
Fichier : noyau_phase3.py
Phase : 3 — Outils déterministes branchés sur le noyau
Date : 18/10/2026

Nouveautés par rapport à noyau_phase2.py :

  • Import de outils.py
  • _reponse_degradee() appelle executer_outil() en priorité
  • Si l’outil répond → M5 rempli, source = ‘outil’
  • Si None → chemin normal (_reponse_factice puis Phi-4)
  • Historique alimenté dans tous les cas
  • Détection intention ‘calcul’ et ‘etat_systeme’ ajoutée

Tests : 3 passages, toutes les intentions couvertes.
"""

import os
import sqlite3
import sys
from datetime import datetime, timezone

———————————————————-

CHEMINS

———————————————————-

CHEMIN_DATA = "/mnt/sda1/home/MIRA_Project/data"

if CHEMIN_DATA not in sys.path:
sys.path.insert(0, CHEMIN_DATA)

———————————————————-

IMPORT DES GESTIONNAIRES ET OUTILS

———————————————————-

ERREUR_GESTIONNAIRES = ""
try:
import gestionnaire_historique as gh
import gestionnaire_utilisateur as gu
import outils
GESTIONNAIRES_OK = True
except Exception as e:
GESTIONNAIRES_OK = False
ERREUR_GESTIONNAIRES = str(e)

———————————————————-

NUMÉRO DE TOUR GLOBAL

———————————————————-

def _lire_prochain_tour():
if not GESTIONNAIRES_OK:
return 1
try:
connexion = sqlite3.connect(gh.CHEMIN_BASE)
curseur = connexion.cursor()
curseur.execute("SELECT MAX(tour) FROM echanges")
resultat = curseur.fetchone()
connexion.close()
if resultat and resultat[0] is not None:
return resultat[0] + 1
return 1
except Exception:
return 1

==========================================================

INITIALISATION

==========================================================

def initialiser_bases():
if not GESTIONNAIRES_OK:
print("ATTENTION : gestionnaires indisponibles — "

  • ERREUR_GESTIONNAIRES)
    return False

    gh.initialiser()
    gu.initialiser()

    identite = gu.lire_identite()
    if identite is None:
    gu.definir_identite("MIRA-0001", "createur")
    print("Identité MIRA-0001 définie.")

    ok_h, err_h = gh.verifier_integrite()
    ok_u, err_u = gu.verifier_integrite()

    if not ok_h:
    print("ERREUR historique.db : " + str(err_h))
    return False
    if not ok_u:
    print("ERREUR utilisateur.db : " + str(err_u))
    return False

    return True

def charger_historique_depuis_base(limite=20):
if not GESTIONNAIRES_OK:
return []
echanges = gh.lire_historique_recent(limite)
return [
{
"tour" : e["tour"],
"horodatage" : e["horodatage"],
"question" : e["question"],
"reponse" : e["reponse"],
"source" : e["source"]
}
for e in echanges
]

==========================================================

FONCTIONS DU NOYAU

==========================================================

def _nouveau_contexte(question, historique=None):
return {
"M1_question" : question,
"M2_historique" : historique if historique else [],
"M3_intention" : None,
"M4_specialiste": None,
"M5_reponse" : None,
"M6_meta" : {
"source_reponse" : None,
"erreurs" : [],
"mode" : "normal"
}
}

def _detecter_intention(contexte):
"""
Détecte l’intention à partir de la question (M1).
Phase 3 : ajout de ‘calcul’ et ‘etat_systeme’.
"""
q = contexte["M1_question"].lower()

if any(m in q for m in ["date", "jour", "heure", "aujourd"]):
    contexte["M3_intention"] = "question_date"
elif any(m in q for m in ["qui t'a", "cree", "createur", "auteur"]):
    contexte["M3_intention"] = "identite"
elif any(m in q for m in ["calcul", "combien", "calcule",
                            "fois", "divise", "plus", "moins"]):
    contexte["M3_intention"] = "calcul"
elif any(m in q for m in ["systeme", "système", "memoire",
                            "mémoire", "disque", "etat", "état"]):
    contexte["M3_intention"] = "etat_systeme"
elif any(m in q for m in ["maintenance", "analyser", "rapport"]):
    contexte["M3_intention"] = "maintenance"
else:
    contexte["M3_intention"] = "inconnue"

return contexte

def _reponse_degradee(contexte):
"""
Phase 3 : appelle executer_outil() en priorité.
Si l’outil répond → M5 rempli, source = ‘outil’.
Si None → réponse dégradée classique pour ‘identite’.
"""
intention = contexte["M3_intention"]

# === PHASE 3 : court-circuit déterministe ===
if GESTIONNAIRES_OK:
    reponse_outil = outils.executer_outil(
        intention,
        contexte["M1_question"]
    )
    if reponse_outil is not None:
        contexte["M5_reponse"]                = reponse_outil
        contexte["M6_meta"]["source_reponse"] = "outil"
        return contexte
# ============================================

# Réponses dégradées classiques
if intention == "identite":
    contexte["M5_reponse"] = (
        "Je suis MIRA, conçue et façonnée "
        "par Da Conceição Mario."
    )
    contexte["M6_meta"]["source_reponse"] = "degradee"

return contexte

def _reponse_factice(contexte):
"""
Répond pour les intentions non couvertes.
Sera remplacé par Phi-4 Mini en Phase 4.
"""
if contexte["M5_reponse"] is None:
contexte["M5_reponse"] = (
"Je suppose mais je ne garantis pas cette réponse, "
"je n’ai pas accès au réseau."
)
contexte["M6_meta"]["source_reponse"] = "factice"
return contexte

def _enregistrer_historique(contexte):
tour_num = _lire_prochain_tour()
entree = {
"tour" : tour_num,
"horodatage" : datetime.now(timezone.utc).isoformat(),
"question" : contexte["M1_question"],
"reponse" : contexte["M5_reponse"],
"source" : contexte["M6_meta"]["source_reponse"]
}
contexte["M2_historique"].append(entree)

if GESTIONNAIRES_OK:
    try:
        gh.ajouter_echange(
            tour_num,
            contexte["M1_question"],
            contexte["M5_reponse"],
            contexte["M6_meta"]["source_reponse"]
        )
    except Exception as e:
        contexte["M6_meta"]["erreurs"].append(
            "historique.db : " + str(e)
        )
return contexte

==========================================================

INTERFACE PRINCIPALE

==========================================================

def executer(contexte):
try:
contexte = _detecter_intention(contexte)
contexte = _reponse_degradee(contexte)
contexte = _reponse_factice(contexte)
contexte = _enregistrer_historique(contexte)
except Exception as e:
contexte["M6_meta"]["erreurs"].append(str(e))
if contexte["M5_reponse"] is None:
contexte["M5_reponse"] = "Erreur interne dans le noyau."
contexte["M6_meta"]["source_reponse"] = "erreur"
return contexte

==========================================================

POINT D’ENTRÉE — TEST RAPIDE (3 passages)

==========================================================

if name == "main":
print("=== MIRA — Noyau Phase 3 ===\n")

print("Initialisation des bases...")
ok = initialiser_bases()
if not ok:
    print("Arrêt : bases inaccessibles.")
    sys.exit(1)
print("Bases OK.\n")

questions = [
    "quel jour sommes-nous ?",
    "qui t'a créé ?",
    "combien font 15 * 6 ?",
    "quel est l'état du système ?",
    "comment fonctionne Python ?",
]

for passage in range(1, 4):
    print("=== PASSAGE {} ===".format(passage))
    historique = charger_historique_depuis_base(20)

    for q in questions:
        ctx = _nouveau_contexte(q, historique)
        ctx = executer(ctx)
        print("  Q: {}".format(q))
        print("  R: {}".format(ctx["M5_reponse"]))
        print("  Source : {} | Erreurs : {}".format(
            ctx["M6_meta"]["source_reponse"],
            ctx["M6_meta"]["erreurs"]
        ))
        historique = ctx["M2_historique"]
        print()

    print()

print("=== 3 passages terminés. ===")

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Défiler vers le haut