–– 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 Falsegh.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 Falsereturn 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. ===")