chat_ia.py

Bienvenue sur CFTPfr.fr Forums scripts chat_ia.py

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

    Sauvegarde de travail — version du 25/07/2026 (Windows, avant portage OS-MIRE)

    « `python
    import tkinter as tk
    from tkinter import scrolledtext, simpledialog, messagebox
    from pathlib import Path
    import json
    import os
    import re
    import webbrowser
    import subprocess
    import ast
    import operator as op
    import importlib.util
    import sqlite3
    import hashlib
    import secrets
    import random
    from datetime import datetime
    from difflib import get_close_matches

    BASE_DIR = Path(r »D:\MIRA_Project\mira_ai »)
    PLUGINS_DIR = BASE_DIR / « plugins »
    CONFIG_FILE = BASE_DIR / « config.json »
    KNOWLEDGE_FILE = BASE_DIR / « connaissances.json »
    HISTORY_FILE = BASE_DIR / « history » / « questions_non_comprises.txt »
    DB_FILE = BASE_DIR / « memory.db »

    SAFE_OPERATORS = {
    ast.Add: op.add,
    ast.Sub: op.sub,
    ast.Mult: op.mul,
    ast.Div: op.truediv,
    ast.FloorDiv: op.floordiv,
    ast.Mod: op.mod,
    ast.Pow: op.pow,
    ast.UAdd: op.pos,
    ast.USub: op.neg,
    }

    def hacher_mot_de_passe(mot_de_passe: str) -> str:
    salt = secrets.token_hex(16)
    h = hashlib.sha256((mot_de_passe + salt).encode(« utf-8″)).hexdigest()
    return f »{salt}:{h} »

    def verifier_mot_de_passe(mot_de_passe: str, stocke: str) -> bool:
    try:
    salt, h = stocke.split(« : »)
    return hashlib.sha256((mot_de_passe + salt).encode(« utf-8 »)).hexdigest() == h
    except Exception:
    return False

    class AutoImprover:
    def __init__(self, db_file=DB_FILE):
    self.db_file = Path(db_file)
    self.db_file.parent.mkdir(parents=True, exist_ok=True)
    self.conn = sqlite3.connect(self.db_file)
    self.conn.execute(«  » »
    CREATE TABLE IF NOT EXISTS messages(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ts TEXT,
    sender TEXT,
    content TEXT
    )
    «  » »)
    self.conn.execute(«  » »
    CREATE TABLE IF NOT EXISTS needs(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ts TEXT,
    message TEXT,
    domain TEXT,
    priority INTEGER,
    suggestion TEXT,
    done INTEGER DEFAULT 0
    )
    «  » »)
    self.conn.execute(«  » »
    CREATE TABLE IF NOT EXISTS improvements(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ts TEXT,
    title TEXT,
    description TEXT,
    score INTEGER DEFAULT 0,
    applied INTEGER DEFAULT 0
    )
    «  » »)
    self.conn.commit()

    def log_message(self, sender, content):
    self.conn.execute(
    « INSERT INTO messages(ts, sender, content) VALUES(?,?,?) »,
    (datetime.now().isoformat(timespec= »seconds »), sender, content)
    )
    self.conn.commit()

    def classify_message(self, message):
    msg = message.lower()
    if any(w in msg for w in [« code », « python », « script », « corrige »]):
    return « code », 4, « Ajouter une analyse de code plus poussée »
    if any(w in msg for w in [« fichier », « dossier », « ouvrir », « lire »]):
    return « fichiers », 3, « Améliorer l’ouverture et la prévisualisation des fichiers »
    if any(w in msg for w in [« recherche », « web », « internet », « trouve »]):
    return « recherche », 3, « Ajouter un moteur de recherche et de résumé »
    if any(w in msg for w in [« plugin », « module », « extension », « ajouter »]):
    return « extensions », 5, « Créer un système d’installation automatique de plugins »
    if any(w in msg for w in [« erreur », « bug », « panne », « crash », « ne marche pas »]):
    return « diagnostic », 4, « Créer un module de diagnostic plus précis »
    if any(w in msg for w in [« mémoire », « souviens », « historique »]):
    return « memoire », 4, « Ajouter une mémoire conversationnelle plus intelligente »
    return « general », 1, « Améliorer la compréhension générale »

    def analyze_and_learn(self, message):
    domain, priority, suggestion = self.classify_message(message)
    self.conn.execute(
    « INSERT INTO needs(ts, message, domain, priority, suggestion) VALUES(?,?,?,?,?) »,
    (datetime.now().isoformat(timespec= »seconds »), message, domain, priority, suggestion)
    )
    self.conn.execute(
    « INSERT INTO improvements(ts, title, description, score, applied) VALUES(?,?,?,?,0) »,
    (datetime.now().isoformat(timespec= »seconds »), f »Besoin détecté: {domain} », message, 1)
    )
    self.conn.commit()
    return domain

    def top_needs(self, limit=5):
    cur = self.conn.execute(«  » »
    SELECT domain, suggestion, COUNT(*) as cnt, MAX(priority) as maxp
    FROM needs
    WHERE done=0
    GROUP BY domain, suggestion
    ORDER BY cnt DESC, maxp DESC
    LIMIT ?
    «  » », (limit,))
    return cur.fetchall()

    def suggest_next_update(self):
    rows = self.top_needs()
    if not rows:
    return « Je n’ai pas encore assez de données pour proposer une amélioration. »
    lines = [« Améliorations suggérées : »]
    for domain, suggestion, cnt, maxp in rows:
    lines.append(f »- {domain} ({cnt} demandes, priorité {maxp}) : {suggestion} »)
    return « \n ».join(lines)

    class PluginManager:
    def __init__(self):
    self.plugins = {}
    PLUGINS_DIR.mkdir(parents=True, exist_ok=True)

    def charger_plugins(self):
    self.plugins = {}
    for file in PLUGINS_DIR.glob(« *.py »):
    if file.name.startswith(« _ »):
    continue
    try:
    spec = importlib.util.spec_from_file_location(file.stem, file)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    if hasattr(module, « INTENTION ») and hasattr(module, « executer »):
    self.plugins[module.INTENTION] = module
    except Exception as e:
    print(f »Erreur plugin {file.name}: {e} »)

    def executer(self, intention, message, app):
    module = self.plugins.get(intention)
    if module:
    try:
    return module.executer(message, app)
    except Exception as e:
    return f »Erreur plugin {intention}: {e} »
    return None

    class ChatIA:
    def __init__(self):
    self.fenetre = tk.Tk()
    self.fenetre.title(« MIRA_IA – Assistant Intelligent »)
    self.fenetre.geometry(« 900×700 »)

    self.auto = AutoImprover()
    self.plugin_manager = PluginManager()
    self.plugin_manager.charger_plugins()
    self.historique = []
    self.contexte = {« derniere_intention »: None, « derniere_question »: None}

    self.connaissances = self.charger_connaissances()

    self.chat_area = scrolledtext.ScrolledText(
    self.fenetre, width=95, height=32, wrap=tk.WORD,
    font=(« Segoe UI », 10), bg= »#f8f9fa »
    )
    self.chat_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)

    self.append_system(« Bonjour ! Je suis MIRA_IA. Je peux apprendre de vos demandes et proposer des améliorations. »)

    panel = tk.Frame(self.fenetre)
    panel.pack(fill=tk.X, padx=10, pady=6)

    self.entry = tk.Entry(panel, font=(« Segoe UI », 10))
    self.entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
    self.entry.bind(« « , self.send)

    tk.Button(panel, text= »Envoyer », command=self.send, bg= »#4CAF50″, fg= »white »).pack(side=tk.LEFT, padx=5)
    tk.Button(panel, text= »Suggestions », command=self.show_suggestions).pack(side=tk.LEFT, padx=5)
    tk.Button(panel, text= »Plugins », command=self.reload_plugins).pack(side=tk.LEFT, padx=5)
    tk.Button(panel, text= »Historique », command=self.export_history).pack(side=tk.LEFT, padx=5)

    def charger_connaissances(self):
    default = {
    « salutations »: {« mots_cles »: [« bonjour », « salut », « hello », « hey », « coucou »], « reponses »: [« Bonjour ! », « Salut ! »]},
    « presentation »: {« mots_cles »: [« qui es-tu », « ton nom », « présente toi »], « reponses »: [« Je suis MIRA_IA, un assistant local modulaire. »]},
    « remerciements »: {« mots_cles »: [« merci », « super », « génial »], « reponses »: [« Avec plaisir ! », « Je vous en prie ! »]},
    « au_revoir »: {« mots_cles »: [« au revoir », « bye », « exit », « quit »], « reponses »: [« Au revoir ! »], « action »: « quitter »},
    « aide »: {« mots_cles »: [« aide », « commandes », « que peux-tu faire »], « reponses »: [« Je peux calculer, rechercher, ouvrir des fichiers, diagnostiquer et charger des plugins. »]},
    « calcul »: {« mots_cles »: [« calcule », « calcul », « combien font », « + », « -« , « * », « / »], « reponses »: [« Donnez une opération. »], « action »: « calculer »},
    « recherche »: {« mots_cles »: [« recherche », « cherche », « trouve », « web », « internet »], « reponses »: [« Quel sujet ? »], « action »: « recherche_web »},
    « fichier »: {« mots_cles »: [« ouvre », « lire », « fichier », « dossier »], « reponses »: [« Quel fichier ? »], « action »: « ouvrir_fichier »},
    « probleme »: {« mots_cles »: [« erreur », « bug », « problème », « ne marche pas »], « reponses »: [« Décrivez le problème. »], « action »: « resoudre_probleme »},
    }
    if KNOWLEDGE_FILE.exists():
    try:
    with open(KNOWLEDGE_FILE, « r », encoding= »utf-8″) as f:
    return {**default, **json.load(f)}
    except Exception:
    pass
    KNOWLEDGE_FILE.parent.mkdir(parents=True, exist_ok=True)
    with open(KNOWLEDGE_FILE, « w », encoding= »utf-8″) as f:
    json.dump(default, f, indent=4, ensure_ascii=False)
    return default

    def append(self, sender, message):
    self.chat_area.config(state=tk.NORMAL)
    self.chat_area.insert(tk.END, f »{datetime.now().strftime(‘%H:%M’)} | {sender}: {message}\n »)
    self.chat_area.config(state=tk.DISABLED)
    self.chat_area.see(tk.END)

    def append_system(self, message):
    self.append(« MIRA_IA », message)

    def normalize(self, text):
    return re.sub(r »\s+ »,  » « , text.lower().strip())

    def send(self, event=None):
    msg = self.entry.get().strip()
    if not msg:
    return
    self.entry.delete(0, tk.END)
    self.append(« Toi », msg)
    self.historique.append((datetime.now().isoformat(timespec= »seconds »), « Toi », msg))
    self.auto.log_message(« Toi », msg)
    self.auto.analyze_and_learn(msg)
    response = self.generate(msg)
    self.append_system(response)
    self.historique.append((datetime.now().isoformat(timespec= »seconds »), « MIRA_IA », response))
    self.auto.log_message(« MIRA_IA », response)

    def generate(self, message):
    msg = self.normalize(message)

    if self.contexte[« derniere_intention »] == « recherche » and msg not in [« oui », « non »]:
    return self.search_web(message)

    intent = self.detect_intent(message)
    if intent:
    info = self.connaissances[intent]
    self.contexte[« derniere_intention »] = intent
    self.contexte[« derniere_question »] = message
    action = info.get(« action »)
    if action == « quitter »:
    self.fenetre.after(100, self.fenetre.destroy)
    return random.choice(info.get(« reponses », [« Au revoir ! »]))
    if action:
    return self.execute_action(action, message)
    return random.choice(info.get(« reponses », [« Je ne sais pas répondre. »]))

    plugin_intent = self.detect_plugin_intent(message)
    if plugin_intent:
    rep = self.plugin_manager.executer(plugin_intent, message, self)
    if rep:
    return rep

    self.save_unknown(message)
    return self.fallback_answer(message)

    def detect_intent(self, message):
    msg = self.normalize(message)
    best_intent = None
    best_score = 0
    for intent, info in self.connaissances.items():
    score = 0
    for kw in info.get(« mots_cles », []):
    if kw in msg:
    score += 2
    if score > best_score:
    best_score = score
    best_intent = intent
    return best_intent

    def detect_plugin_intent(self, message):
    msg = self.normalize(message)
    for intent in self.plugin_manager.plugins:
    if intent in msg:
    return intent
    return None

    def execute_action(self, action, message):
    if action == « calculer »:
    return self.calculate(message)
    if action == « recherche_web »:
    return self.search_web(message)
    if action == « ouvrir_fichier »:
    return self.open_file(message)
    if action == « resoudre_probleme »:
    return self.solve_problem(message)
    return « Action non reconnue. »

    def calculate(self, message):
    expr = self.extract_expression(message)
    if not expr:
    expr = simpledialog.askstring(« Calcul », « Entrez une expression: ») or «  »
    if not expr:
    return « Aucune expression fournie. »
    try:
    node = ast.parse(expr, mode= »eval »)
    return f »Résultat : {self.eval_node(node.body)} »
    except Exception:
    return « Calcul invalide. »

    def extract_expression(self, message):
    msg = self.normalize(message)
    msg = re.sub(r »^(calcule|calcul|combien font|résous|resous)\s* », «  », msg)
    return msg.strip()

    def eval_node(self, node):
    if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
    return node.value
    if isinstance(node, ast.BinOp) and type(node.op) in SAFE_OPERATORS:
    return SAFE_OPERATORS[type(node.op)](self.eval_node(node.left), self.eval_node(node.right))
    if isinstance(node, ast.UnaryOp) and type(node.op) in SAFE_OPERATORS:
    return SAFE_OPERATORS[type(node.op)](self.eval_node(node.operand))
    raise ValueError(« Expression interdite »)

    def search_web(self, message):
    msg = self.normalize(message)
    for word in [« recherche », « cherche », « trouve », « web », « internet », « google »]:
    msg = msg.replace(word, «  »)
    subject = msg.strip()
    if not subject:
    subject = simpledialog.askstring(« Recherche web », « Quel sujet ? ») or «  »
    if not subject:
    return « Recherche annulée. »
    webbrowser.open(« https://www.google.com/search?q= » + subject.replace( » « , « + »))
    self.contexte[« derniere_intention »] = « recherche »
    return f »Recherche lancée pour : {subject} »

    def open_file(self, message):
    path_text = re.sub(r »\b(ouvre|lire|fichier|dossier)\b », «  », message, flags=re.I).strip().strip(‘ »‘).strip(« ‘ »)
    if not path_text:
    path_text = simpledialog.askstring(« Fichier », « Chemin complet du fichier: ») or «  »
    if not path_text:
    return « Aucun fichier indiqué. »
    p = Path(path_text)
    if not p.is_absolute():
    p = Path(r »D:\MIRA_Project ») / path_text
    if not p.exists():
    return f »Le fichier n’existe pas : {p} »
    try:
    if p.suffix.lower() in [« .txt », « .py », « .json », « .md », « .log », « .csv »]:
    return « Voici un aperçu:\n » + « \n ».join(p.read_text(encoding= »utf-8″, errors= »replace »).splitlines()[:30])
    if os.name == « nt »:
    os.startfile(str(p))
    else:
    subprocess.run([« xdg-open », str(p)])
    return f »Fichier ouvert : {p} »
    except Exception as e:
    return f »Erreur fichier : {e} »

    def solve_problem(self, message):
    msg = self.normalize(message)
    if « python » in msg:
    return « Python : envoyez l’erreur exacte, le code et le résultat attendu. »
    if « mira_os » in msg:
    return « MIRA_OS : vérifiez les chemins, les dépendances et les logs. »
    return « Décrivez le contexte, le message d’erreur et ce que vous avez essayé. »

    def fallback_answer(self, message):
    all_keys = list(self.connaissances.keys())
    close = get_close_matches(self.normalize(message), all_keys, n=1, cutoff=0.4)
    if close:
    key = close[0]
    info = self.connaissances[key]
    return random.choice(info.get(« reponses », [« Je ne sais pas. »]))
    return f »Je n’ai pas compris : ‘{message}’. Essayez par exemple ‘Calcule 5+3’ ou ‘Recherche Python’. »

    def save_unknown(self, message):
    HISTORY_FILE.parent.mkdir(parents=True, exist_ok=True)
    with open(HISTORY_FILE, « a », encoding= »utf-8″) as f:
    f.write(f »{datetime.now().isoformat(timespec=’seconds’)} | {message}\n »)

    def show_suggestions(self):
    msg = self.auto.suggest_next_update()
    messagebox.showinfo(« Suggestions d’évolution », msg)

    def reload_plugins(self):
    self.plugin_manager.charger_plugins()
    messagebox.showinfo(« Plugins », « Plugins rechargés. »)

    def export_history(self):
    out = BASE_DIR / f »historique_{datetime.now().strftime(‘%Y%m%d_%H%M%S’)}.txt »
    with open(out, « w », encoding= »utf-8″) as f:
    for ts, sender, msg in self.historique:
    f.write(f »{ts} | {sender}: {msg}\n »)
    self.append_system(f »Historique exporté : {out.name} »)

    def run(self):
    self.fenetre.mainloop()

    if __name__ == « __main__ »:
    ChatIA().run()
    « `

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