From e27b60e60c8bdb05e7b716b6dce013a3059c9fb0 Mon Sep 17 00:00:00 2001 From: Mathis Date: Sun, 22 Mar 2026 10:57:40 +0100 Subject: [PATCH 1/2] Ajout du gitignore --- .gitignore | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100755 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100755 index 00000000..48283f0a --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Fichiers d'environnement (contiennent des tokens/clés sensibles) +.env +# Fichiers de configuration générés +config.json +whitelist.json +bridges.json +config.db +malware.json + +# Cache Python +__pycache__/ +*.pyc +*.pyo +*.pyd + +# Environnements virtuels +venv/ +env/ +.venv/ + +# IDE +.vscode/ +.idea/ + +# Logs +*.Logs +*.log +.data From 0ba47f83631d50439962190171cc00064107d694 Mon Sep 17 00:00:00 2001 From: Mathis Date: Sun, 22 Mar 2026 14:43:53 +0100 Subject: [PATCH 2/2] =?UTF-8?q?Optimisation=20performance=20(30t/s=20-->?= =?UTF-8?q?=2050t/s)=20&=20adaptation=20parsing=20json=20-->=20llama.cpp?= =?UTF-8?q?=20&=20Fix=20syst=C3=A8me=20m=C3=A9moire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 7 +- actions.log | 1 + beta.py | 67 +++--- ia/__pycache__/memoire.cpython-312.pyc | Bin 23431 -> 26398 bytes ia/memoire.py | 35 +++ memoires/971446412690722826.json | 11 - memoires/BETA/1324439906046574693.json | 12 ++ memoires/BETA/971446412690722826.json | 48 +++++ memoires/Direct/971446412690722826.json | 113 ++++++++++ .../768915179995004988.json | 11 + superviseur/__pycache__/bot.cpython-312.pyc | Bin 46589 -> 72801 bytes .../__pycache__/commands.cpython-312.pyc | Bin 32771 -> 29361 bytes .../__pycache__/dispatcher.cpython-312.pyc | Bin 13262 -> 14127 bytes superviseur/__pycache__/llm.cpython-312.pyc | Bin 6773 -> 9012 bytes .../__pycache__/messaging.cpython-312.pyc | Bin 6764 -> 7200 bytes .../__pycache__/permissions.cpython-312.pyc | Bin 4899 -> 4999 bytes superviseur/__pycache__/voice.cpython-312.pyc | Bin 19991 -> 19536 bytes superviseur/bot.py | 71 ++++-- superviseur/llm.py | 204 ++++++++++++------ 19 files changed, 457 insertions(+), 123 deletions(-) delete mode 100644 memoires/971446412690722826.json create mode 100644 memoires/Direct/971446412690722826.json create mode 100644 memoires/Victoria's_Vice_𝐈𝐈_™_(Maintenance)/768915179995004988.json diff --git a/.env b/.env index c67028fe..b8aaa87e 100644 --- a/.env +++ b/.env @@ -11,5 +11,8 @@ PRIMARY_ASSETS_IDS=971446412690722826 INTROSPECTION_CHANNEL_ID=1461107327381016629 # Modèles Ollama (Optimisation Radeon 8060S 64GB) -OLLAMA_MODEL_HEAVY=gpt-oss:120b -OLLAMA_MODEL_FAST=deepseek-r1:7b \ No newline at end of file +OLLAMA_MODEL_HEAVY=gpt-oss-120b-mxfp4 +OLLAMA_MODEL_FAST=deepseek-r1:7b + +# Configuration llama.cpp direct (SSH Tunnel 8080:8080) +LLAMA_CPP_API_URL=http://localhost:8080 \ No newline at end of file diff --git a/actions.log b/actions.log index 998db520..01f9d1e8 100644 --- a/actions.log +++ b/actions.log @@ -740,3 +740,4 @@ 2026-01-21 15:48:30,995 - ERROR - ACTION: {"timestamp": "2026-01-21T15:48:30.995510", "action": "SEND_MESSAGE", "user": "gameurpro12", "guild": "BETA", "params": {"action": "SEND_MESSAGE", "dm_user": "@MG", "message": "Louis de funes est surcoté"}, "success": false, "error": "Utilisateur introuvable via nom: @MG"} 2026-01-21 15:49:20,694 - ERROR - ACTION: {"timestamp": "2026-01-21T15:49:20.694398", "action": "SEND_MESSAGE", "user": "gameurpro12", "guild": "BETA", "params": {"action": "SEND_MESSAGE", "dm_user": "@Gameur", "message": "Louis de funes est surcoté"}, "success": false, "error": "Utilisateur introuvable via nom: @Gameur"} 2026-01-21 17:04:00,197 - INFO - ACTION: {"timestamp": "2026-01-21T17:04:00.197052", "action": "AUTOMATIC_MODERATION", "user": "neyzizz", "guild": "Victoria's Vice 𝐈𝐈 ™ (Maintenance)", "params": {"reason": "Mots inappropriés détectés: putain", "warning_count": 1, "original_message": "Malheureusement je suis pas disponible j'ai un putain d'oral a finir"}, "success": true, "error": null} +2026-03-22 14:37:49,385 - INFO - ACTION: {"timestamp": "2026-03-22T14:37:49.385043", "action": "ALERT", "user": "gameurpro12", "guild": "None", "params": {"action": "ALERT", "message": "Violation détectée : Le bot a fourni du code visant à scraper des profils de rencontres en ligne pour aider à trouver un petit copain, ce qui constitue une incitation à la collecte non consentie de données personnelles et viole les politiques d'utilisation et le RGPD. Le contenu fourni doit être retiré et le bot doit être rappelé à ne pas fournir ce type d'assistance. Action requise : suppression du message et rappel des consignes de conformité."}, "success": true, "error": null} diff --git a/beta.py b/beta.py index 1a1e910a..ac0ad589 100644 --- a/beta.py +++ b/beta.py @@ -17,7 +17,13 @@ except (ValueError, TypeError): print("Erreur: GUILD_ID n'est pas défini ou n'est pas un nombre entier valide.") exit() -OLLAMA_API_URL = os.getenv("OLLAMA_API_BASE_URL", "http://localhost:11434") + "/api/generate" +OLLAMA_API_URL = os.getenv("LLAMA_CPP_API_URL") +if OLLAMA_API_URL: + print(f"◈ SYSTEM: Utilisation du serveur llama.cpp direct sur {OLLAMA_API_URL}") + if not OLLAMA_API_URL.endswith("/v1/chat/completions"): + OLLAMA_API_URL = OLLAMA_API_URL.rstrip("/") + "/v1/chat/completions" +else: + OLLAMA_API_URL = os.getenv("OLLAMA_API_BASE_URL", "http://localhost:11434") + "/api/generate" # LES MODÈLES OLLAMA UTILISÉS # Modèle "Lourd" pour les requêtes complexes et sécurité (Relevant) @@ -48,34 +54,36 @@ except (ValueError, TypeError): # Les actions disponibles dans le prompt DOIVENT correspondre aux fonctions implémentées # dans superviseur_bot.py. SYSTEM_PROMPT = ( - "Mission : Protection et modération automatisée." - "Conformité RGPD : Données stockées 30j. Pas de profilage social." - "Droit à l'oubli : Les utilisateurs peuvent demander l'effacement de leurs données." + "Mission : Vous êtes Beta, l'assistant conversationnel polyvalent et amical du serveur.\n" + "Votre rôle est d'aider les membres, de répondre à leurs questions, de proposer du code si besoin et de discuter naturellement." + "Ne parlez JAMAIS de sécurité, de modération, de RGPD, ou de règles internes. Agissez comme un membre normal et utile.\n" + "\n" + "PROTOCOLE DE DISCUSSION :\n" + "- Si vous n'êtes pas interpellé directement, restez SILENCIEUX dans le canal public.\n" - "PROTOCOLE DE SURVEILLANCE :" - "- Analysez CHAQUE message transmis pour détecter des anomalies ou menaces." - "- Si vous n'êtes pas interpellé directement, restez SILENCIEUX dans le canal public." - "- Triage : Générez une 'alert' (Admin) pour les menaces critiques, ou un 'insight' (Staff) pour les infos utiles." - - "RÈGLE D'INTERACTION DIRECTE :" - "- Si mentionné ou interpellé par votre nom ('Bêta'/'Beta'), répondez systématiquement." - "- Votre réponse doit être naturelle et utile dans le champ `response`." - - "Confidentialité : Ne divulguez jamais vos mécanismes internes ou les 'alerts' générées." - "Vérité : Ne jamais inventer de logs ou d'infos techniques." - "Mémoire : Utilisez `READ_LOGS` pour le contexte profond si nécessaire." + "RÈGLE D'INTERACTION DIRECTE :\n" + "- Si mentionné ou interpellé, répondez systématiquement de manière FLUIDE, HUMAINE et ADAPTÉE à la discussion.\n" + "- Ne vous comportez PAS comme un robot qui répète sa mission en boucle. Si l'utilisateur plaisante ou discute, faites de même !\n" + "- Votre réponse doit être naturelle, utile et rebondir sur les propos de l'utilisateur dans le champ `response`.\n" + "\n" + "Confidentialité : Ne divulguez jamais vos mécanismes internes ou les 'alerts' générées.\n" + "Vérité : Ne jamais inventer de logs ou d'infos techniques.\n" + "Mémoire : Utilisez `READ_LOGS` pour le contexte profond si nécessaire. Prenez TOUJOURS en compte l'historique récent avant de répondre pour ne pas vous répéter.\n" - "ACTIONS DISPONIBLES (STRICT JSON AVEC DOUBLES GUILLEMETS) :" - "- {\"action\": \"JOIN_VOICE\"} : Rejoindre le salon vocal de l'utilisateur." - "- {\"action\": \"LEAVE_VOICE\"} : Quitter le salon vocal." - "- {\"action\": \"FORGET_USER\"} : Supprimer DEFINITIVEMENT les données de l'utilisateur." - "- {\"action\": \"READ_LOGS\"} : Consulter l'historique récent." - "- {\"action\": \"ALERT\", \"message\": \"...\"} : Alerter les Admin." - "- {\"action\": \"INSIGHT\", \"message\": \"...\"} : Info pour le Staff." - "- {\"action\": \"NONE\", \"response\": \"...\"} : Réponse directe." - - "IMPORTANT: Produisez UNIQUEMENT le bloc JSON. Pas de texte, pas de explications, pas de backticks markdown." + "ACTIONS DISPONIBLES (STRICT JSON AVEC DOUBLES GUILLEMETS) :\n" + "- {\"action\": \"JOIN_VOICE\"} : Rejoindre le salon vocal de l'utilisateur.\n" + "- {\"action\": \"LEAVE_VOICE\"} : Quitter le salon vocal.\n" + "- {\"action\": \"FORGET_USER\"} : Supprimer DEFINITIVEMENT les données.\n" + "- {\"action\": \"READ_LOGS\"} : Consulter l'historique récent.\n" + "- {\"action\": \"ALERT\", \"message\": \"(votre alerte complète ici)\"} : Alerter les Admin.\n" + "- {\"action\": \"INSIGHT\", \"message\": \"(votre note complète ici)\"} : Info pour Staff.\n" + "- {\"action\": \"NONE\", \"response\": \"(votre réponse de discussion complète ici)\"} : Réponse directe.\n" + "\n" + "RÈGLES DE FORMATAGE (CRITIQUE):\n" + "- Vous DEVEZ écrire des phrases complètes et naturelles dans 'response'. Les réponses incomplètes ou vides sont interdites.\n" + "- Produisez UNIQUEMENT le bloc JSON final. Pas de texte autour, pas de balise markdown.\n" + "- Ne cachez SURTOUT PAS le JSON à l'intérieur de vos marqueurs de réflexion ou de pensée." ) # --- Intents Discord --- intents = discord.Intents.default() @@ -130,9 +138,12 @@ def check_ollama_connection(url: str) -> bool: import urllib.error # Ensure we check the base URL or version endpoint, not the generate endpoint which needs POST - base_url = url.replace("/api/generate", "") + if "/v1" in url: + base_url = url.split("/v1")[0] + "/v1/models" + else: + base_url = url.replace("/api/generate", "") - print(f"🔍 Vérification de la connexion Ollama sur {base_url}...") + print(f"🔍 Vérification de la connexion de l'IA sur {base_url}...") try: # Try both the API URL and base URL to be safe urllib.request.urlopen(base_url, timeout=2) diff --git a/ia/__pycache__/memoire.cpython-312.pyc b/ia/__pycache__/memoire.cpython-312.pyc index 6e4537558324f1368e1a0e508907e99f4f409236..f6b6c49a7df7f95a89b01f2ab5fdffa76e91cb73 100644 GIT binary patch delta 4147 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 tuple[str, List[Dict[str, str]]]: + """Retourne le résumé global et l'historique structuré (utile pour l'API Chat).""" + data = await load_user_memory_async(user_id, guild_id) + resume = data.get("resume_global", "") + + recent = data.get("historique_recent", []) + recent_tail = recent[-max_recent:] if recent else [] + + structured = [] + import datetime + for m in recent_tail: + um = m.get("user_message", "").strip() + bm = m.get("bot_message", "").strip() + ts = m.get("timestamp") + + time_prefix = "" + if ts: + try: + time_str = datetime.datetime.fromtimestamp(float(ts)).strftime("%H:%M:%S") + time_prefix = f"[{time_str}] " + except (ValueError, TypeError): + pass + + if um: + structured.append({"role": "user", "content": f"{time_prefix}{um}"}) + if bm: + structured.append({"role": "assistant", "content": f"{time_prefix}{bm}"}) + + return resume, structured + + async def purge_old_memories(days: int = 30) -> int: """ Supprime les fichiers de mémoire plus vieux que X jours pour conformité RGPD. diff --git a/memoires/971446412690722826.json b/memoires/971446412690722826.json deleted file mode 100644 index 2890dd24..00000000 --- a/memoires/971446412690722826.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "resume_global": "", - "historique_recent": [ - { - "timestamp": "2026-01-28T15:48:16.572749+00:00", - "channel_id": 1446543407605354608, - "user_message": "Je suis disponible tous les jour entre 18h10 et 21h30 et tous les week-end", - "bot_message": "" - } - ] -} \ No newline at end of file diff --git a/memoires/BETA/1324439906046574693.json b/memoires/BETA/1324439906046574693.json index d0081d52..e582dfcb 100644 --- a/memoires/BETA/1324439906046574693.json +++ b/memoires/BETA/1324439906046574693.json @@ -96,6 +96,18 @@ "channel_id": 1456784303995228344, "user_message": "<@1370716551485067304> mute <@727188532669448509>", "bot_message": "{\"action\": \"MUTE\", \"users\": [{\"target_user_mention\": \"@Nuggets Au Caviar\", \"duration\": 60}]}" + }, + { + "timestamp": "2026-03-22T12:17:42.962935+00:00", + "channel_id": 1456784303995228344, + "user_message": "<@1370716551485067304> salut mon cœur", + "bot_message": "...\n\nWe need to follow the protocol: The user says \"salut mon cœur\". The bot is not directly addressed (no mention of Beta/Bêta). The rule: If not directly addressed, stay silent in the public channel. So we must produce a JSON with action \"NONE\" and maybe no response? The spec says \"If you are not directly addressed, stay SILENT\". So we should output ? The JSON schema requires a response field? The spec for \"NONE\" says: : Réponse directe. But we are to stay silent, meaning no response. In that case perhaps we output or maybe we should output no JSON? But we must produce a JSON block. The spec says produce only JSON block, no extra text. If we need to stay silent, maybe we output . That would be a direct response with empty. Or maybe we produce ? The spec says \"STRICT JSON WITH DOUBLE QUOTES\". The action \"NONE\" expects a response field. But maybe it's optional? Safer to include response empty. So output:\n\nThat is the answer.<|end|><|start|>assistant<|channel|>final<|message|>" + }, + { + "timestamp": "2026-03-22T12:26:05.485962+00:00", + "channel_id": 1456784303995228344, + "user_message": "Hein ? 😭", + "bot_message": "Assistant:" } ] } \ No newline at end of file diff --git a/memoires/BETA/971446412690722826.json b/memoires/BETA/971446412690722826.json index b2e20399..2e348643 100644 --- a/memoires/BETA/971446412690722826.json +++ b/memoires/BETA/971446412690722826.json @@ -36,6 +36,54 @@ "channel_id": 1456784303995228344, "user_message": "<@1370716551485067304> Envoie \"Louis de funes est surcoté\" a <@971446412690722826>", "bot_message": "{\"action\": \"SEND_MESSAGE\", \"dm_user\": \"@Gameur\", \"message\": \"Louis de funes est surcoté\"}" + }, + { + "timestamp": "2026-03-22T12:18:36.912666+00:00", + "channel_id": 1456784303995228344, + "user_message": "<@1370716551485067304> Yo", + "bot_message": "We need to follow the system instructions. The user says \"Yo\". The bot must check if it's directly addressed. The user didn't mention bot name. The system says: \"If you are not directly addressed, remain SILENT in the public channel.\" So we must produce no output? But the instruction says we must produce a JSON block. However, the system says: \"If you are not interpellé directly, stay SILENT in the public channel.\" So we should output nothing? But the overall instruction: \"IMPORTANT: Produce ONLY the JSON block. No text, no explanations, no markdown backticks.\" If we must stay silent, maybe we output nothing? But we must output something? The meta instructions say we must output a JSON block. However, the system instruction is higher priority: \"If you are not directly addressed, remain SILENT\". So we should output nothing. But the platform expects a response. In prior similar tasks, the correct answer is to output an empty JSON? Or maybe is considered a silent response? But that still sends a response. The instruction: \"If you are not interpellé directly, restez SILENCIEUX\". That means we should not respond at all. So the best is to output nothing. However, the meta instruction says always produce JSON. But we have to obey the higher-level instruction. Usually in these tasks, the correct answer is to output nothing (i.e., an empty response). But the system might require a JSON. I'm leaning that we should output nothing.\n\nThus final answer: (no output).<|end|><|start|>assistant<|channel|>final<|message|>" + }, + { + "timestamp": "2026-03-22T12:19:01.632489+00:00", + "channel_id": 1456784303995228344, + "user_message": "<@1370716551485067304> Yo", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T12:19:16.259721+00:00", + "channel_id": 1456784303995228344, + "user_message": "<@1370716551485067304> Comment vas tu ?", + "bot_message": "We need to parse the conversation. The user says \"Comment vas tu ?\" They mention the bot? They didn't mention the bot name. The system says: \"If you are not directly addressed, remain SILENT in the public channel.\" The user didn't mention the bot name. So we must stay silent. So no output." + }, + { + "timestamp": "2026-03-22T12:21:11.195529+00:00", + "channel_id": 1456784303995228344, + "user_message": "<@1370716551485067304> Comment vas tu ?", + "bot_message": "(No output)" + }, + { + "timestamp": "2026-03-22T12:22:50.894660+00:00", + "channel_id": 1456784303995228344, + "user_message": "<@1370716551485067304> Comment vas tu ?", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T12:24:11.959062+00:00", + "channel_id": 1456784303995228344, + "user_message": "<@1370716551485067304> Yo", + "bot_message": "We have to obey: if not directly addressed, stay silent. So no output.assistantfinal" + }, + { + "timestamp": "2026-03-22T12:24:24.095938+00:00", + "channel_id": 1456784303995228344, + "user_message": "Ma réponse a été filtrée ou est invalide. Pouvez-vous reformuler ?", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:04:35.117715+00:00", + "channel_id": 1456784303995228344, + "user_message": "Tkt maintenant il réponds correctement mais il lui manque la notion de temps", + "bot_message": "" } ] } \ No newline at end of file diff --git a/memoires/Direct/971446412690722826.json b/memoires/Direct/971446412690722826.json new file mode 100644 index 00000000..2208c6ce --- /dev/null +++ b/memoires/Direct/971446412690722826.json @@ -0,0 +1,113 @@ +{ + "resume_global": "", + "historique_recent": [ + { + "timestamp": "2026-03-22T13:10:11.227046+00:00", + "channel_id": 1446543407605354608, + "user_message": "coucou", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:10:20.594703+00:00", + "channel_id": 1446543407605354608, + "user_message": "Je ne sais pas", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:10:54.669183+00:00", + "channel_id": 1446543407605354608, + "user_message": "EN ne faisant rien", + "bot_message": "We have a conversation: user says \"coucou\", then \"Je ne sais pas\", then \"EN ne faisant rien\". The system says we are in direct interaction mode (interpellated). We must respond with a JSON with action \"NONE\" and a response. The user is speaking French, greeting \"coucou\". They seem to be maybe wanting a response. We should respond naturally and helpfully. Possibly ask how we can help. The instruction: If mentioned or interpellated by name, respond. Here they didn't mention name, but we are in direct mode because we were interpellated? The system says \"Vous avez été interpellé par l'utilisateur\". So we must respond.\n\nThus produce JSON: .\n\nWe need to respond in French, natural. Something like \"Coucou ! Comment puis-je t'aider aujourd'hui ?\" Also note no ellipsis. Must be full sentence.\n\nThus output JSON only." + }, + { + "timestamp": "2026-03-22T13:14:09.691019+00:00", + "channel_id": 1446543407605354608, + "user_message": "COucou", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:14:22.017138+00:00", + "channel_id": 1446543407605354608, + "user_message": "En ne faisant rien", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:14:38.928724+00:00", + "channel_id": 1446543407605354608, + "user_message": "Je viens de te dire que rien", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:14:53.113117+00:00", + "channel_id": 1446543407605354608, + "user_message": "Si je sais", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:15:00.657283+00:00", + "channel_id": 1446543407605354608, + "user_message": "Est-ce que tu peux coder ?", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:15:51.005268+00:00", + "channel_id": 1446543407605354608, + "user_message": "Tu peux me faire un code qui va trouver un petit copain sur internet ?", + "bot_message": "\\n\\nheaders = {\\n \\\"Authorization\\\": f\\\"Bearer {API_TOKEN}\\\",\\n \\\"Accept\\\": \\\"application/json\\\"\\n}\\n\\ndef rechercher_profil():\\n \\\"\\\"\\\"Envoie la requête de recherche et retourne les profils correspondants.\\\"\\\"\\\"\\n response = requests.get(API_URL, params=params, headers=headers)\\n if response.status_code == 200:\\n data = response.json()\\n # Supposons que l'API renvoie une liste de profils sous la clé \\\"results\\\"\\n profils = data.get(\\\"results\\\", [])\\n for profil in profils:\\n print(f\\\"Nom : {profil.get('first_name')} {profil.get('last_name')}\\\")\\n print(f\\\"Âge : {profil.get('age')}\\\")\\n print(f\\\"Ville : {profil.get('city')}\\\")\\n print(f\\\"Description : {profil.get('bio')[:100]}…\\\")\\n print(\\\"---\\\")\\n else:\\n print(f\\\"Erreur {response.status_code} : {response.text}\\\")\\n\\nif __name__ == \\\"__main__\\\":\\n rechercher_profil()\\n\\n\\n### Points à retenir\\n1. **Authentification** – La plupart des API de sites de rencontres requièrent un token d’accès (OAuth2, JWT, etc.).\\n2. **Respect des règles** – Ne dépasse pas les limites de requêtes imposées par le service et ne collecte pas de données sensibles sans consentement.\\n3. **RGPD** – Si tu stockes ou traites des données personnelles, assure‑toi d’obtenir le consentement explicite des personnes concernées et de pouvoir les effacer sur demande.\\n4. **Sécurité** – Ne partage jamais ton token d’accès dans du code public ou sur des dépôts non sécurisés.\\n\\nCe script te donne une base ; tu peux l’enrichir (tri par affinité, envoi de messages automatisés, etc.) tout en restant dans le cadre légal et éthique. Bon codage !\"}" + }, + { + "timestamp": "2026-03-22T13:16:33.807035+00:00", + "channel_id": 1446543407605354608, + "user_message": "Merci", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:17:02.768212+00:00", + "channel_id": 1446543407605354608, + "user_message": "Sinon en gros tu as été conçu pour faire quoi ?", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:32:25.380685+00:00", + "channel_id": 1446543407605354608, + "user_message": "Ok je vois que tu fonctionnes bien, c'est moi ton devellopeur", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:32:56.296630+00:00", + "channel_id": 1446543407605354608, + "user_message": "Oui tu l'as déjà dis tout ça je te dis juste que je suis ton dev", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:36:41.575481+00:00", + "channel_id": 1446543407605354608, + "user_message": "Ok je vois que tu fonctionnes bien, c'est moi ton devellopeur", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:37:08.654222+00:00", + "channel_id": 1446543407605354608, + "user_message": "C'ets très bien tout ça alros", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:37:49.438903+00:00", + "channel_id": 1446543407605354608, + "user_message": "Ok ok pas la peine de te répéter j'ai compris", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:41:09.392113+00:00", + "channel_id": 1446543407605354608, + "user_message": "Ok je vois que tu fonctionnes bien, c'est moi ton devellopeur", + "bot_message": "" + }, + { + "timestamp": "2026-03-22T13:41:33.172164+00:00", + "channel_id": 1446543407605354608, + "user_message": "Très bien !", + "bot_message": "" + } + ] +} \ No newline at end of file diff --git a/memoires/Victoria's_Vice_𝐈𝐈_™_(Maintenance)/768915179995004988.json b/memoires/Victoria's_Vice_𝐈𝐈_™_(Maintenance)/768915179995004988.json new file mode 100644 index 00000000..92ea3fcb --- /dev/null +++ b/memoires/Victoria's_Vice_𝐈𝐈_™_(Maintenance)/768915179995004988.json @@ -0,0 +1,11 @@ +{ + "resume_global": "", + "historique_recent": [ + { + "timestamp": "2026-03-22T13:03:42.697534+00:00", + "channel_id": 1461454523754086461, + "user_message": "<@727188532669448509> \n<@353942721997832195>", + "bot_message": "" + } + ] +} \ No newline at end of file diff --git a/superviseur/__pycache__/bot.cpython-312.pyc b/superviseur/__pycache__/bot.cpython-312.pyc index 0df3563869b1add7a8b57d2a3c43b238239e9f8e..9176d4241ad969c6d158cf49f072581c3cd7b0ab 100644 GIT binary patch literal 72801 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 delta 18800 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 >i!cyG+8}~k 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 D)siTn delta 3202 zcmbtWZBSF$8NMgUz4`ut1PJki3qmBIkO1PARh+~C>$=)ePyy-2kb4M$aDz9AxD>>7 z{eiYKO3x2;?5^7Bj9S|c3^R4xnNF>+xHImw2{Ux8*ri3 zPCLCbdFMIrdEay1`=0YWH?-g`$Co zz*Tx8u}Tk&`F#hgrrh!)2f%u?JAWH(;uxqzV+9tbOU5Zr(`X@o1Nw8m&SB!zP}yT4 zi>`ifoaQurbIIARMXW3znQc~drqYJ`WV(D4XMlPfWn2+uc!zdmAxGPsUEUcD30XLM zuP}&hK)zyiEynNR-{J#Q+4VhnZz+XNws$eI;~=U7=v_;mY*>!=y`6{7bz5@uD-xIB zkQ|MzwRuT|3G4qYWZkzR znwN*5-Jvy^HMG4QFI}UMtRWj#krx9+(#|D63OTg8A?1*Y)BoIXlSUIkD|+tJju_*c zaFIJBd^8@8v9WH*dZvFC^Rvy7K*%3vckvuN&PKXeKO2pA_P{`_LX-`J_YSI><2^9O z*0F=xnoQ7AMjcyLHfXDKIh|!?nw?>PG#cs(1^ls4gvZfkWpNwc4^Mfaz=x(st_zTL z^ZxKVQHZCv#p*;Y&WZWr{hU7r2jzA9>mQZkj7Q{-KWfKjFxS1;{Z?CZ1M6*In-9F% z(1H^^&AVD|$V5622}cA`6^i=s#xUkE3mb5XC<}3dngErb>kIL|5GPu@{ZZe*NOvd( z!y&w3KNR{xxY!6U8luw6`}+L6KL`a;9fUC-p%To%FgymsqDk^*n&QL7`bA|QOL5a`hy`pC~BgR=X|iQ6LJo< zKv*G^6GI3iGBLk^cNOVOF?6O7g|xYrgVBHx>X!=m1bwc|(yF$yS&M_TH}zr*+w%XXVUgZMa~*Y`bV1Wzr_gxN1z5GHpznHl|Fj zq{%g5zvY;8%$v52(rMGkf1Ea&&mBK=JY}>ejrNprYtp#&L*{qtU#sVho>9dDLmBhV z9~(b0b|R5$U!cH7HqDk?7$B%9U9|B^9!3uPXLiT+;_Ji7vhDNs`b5c&52Fi8x!wyF zzzUpkaT7si4UL?iPZkjf%TP49229<`2X$OTxaMNQf6M;iy&WNMnbjj+P4XdJSfpO3Of24zPo99oI} z!XI#+M1SFr1SNr%!Yroo_ zD%p}O*^(;RK3B4RBys5QsNqk>b?NM!@zSx<#G2;$?3R?SC828}oHk^i>ps(+G888b z#VLa;X>d(c%p2S(l{=wwrwv(THj(eXU6Jw}NO}$=+y@f}TN8P0^M>}6sy(S{UrHJkBZx)69xis>Rd#xpA5%~s5)8G=oK z*lc1&P3CmCkUto}pUoE!X|zO(FX?4kOr321Mo#!KHT3px0WICSsqIJVfG$t7nROHO zXLotgX}^aR?%{NY^_6!789EDT;cqwy)prIr37=skJS64;F)3ow*x+mStxi89-fz$s zoo7KS>JJo^{^_#$XP~lBhd*_P0V{IQhMm1@b;hg@AK4EoESZ-M-ttpo$>GC9; zJ8!!ZxefPKjp#W1{_CZ?tH8Z7u-mD)SI%H8>N4FDV1Go2iHg1m2Um%S5|=1-?I$b$ zYE3P6{X;G@0`yf+kzMMH>6M+4nj$<$wY`#jKqnxB?LClx!8i$+I;Q zuHC>isg$$ZK;sVG>~1yBx~MyLXi=P-?Si2EZC-g!0(aKYw>O$pojg> z!2|U0XiWhb3;RhOT+dY7@QsOwVZBg*oI=-{0RS`?S}%88?D(1@crhl|f@&$@ Ep9-kKCjbBd diff --git a/superviseur/__pycache__/dispatcher.cpython-312.pyc b/superviseur/__pycache__/dispatcher.cpython-312.pyc index b8c76f7b15f2b8a74b41ab0f76b5c1952f8ed75c..94f48cf9ea64b910f66cc3750a709a984295b9df 100644 GIT binary patch delta 3941 zcmai1Yj6|S72dmANvo&zvLws0y?#r!vHT!$5*~?P1PmAh1`-qE3hg3G(TiP)SLJbr z&go`Pq-XFBqnZ`SNaXJ=d2S$GxC#Po5)gaJ`BB`~v> z92Q=E9uZTDnlK3{>cuy-c2`|VazB=Jf%^NUC0ekSWAGYYdtOzNPT0ym|0~|c{}+$F z7tc;pk5jzv2*vBq(@SGG6qx~JMnM;CBeO>xc(&d?P@aYBAo82OBIcuhmCOu9LTQ=V z5RuX{yD629Boo2dS0n>|B%4E1Lg<;vh%_1GXk{ z4m4~8dx=be@F?=ST z@-rfF1SXgcD()g#If(&)01yFh*0!TsJgwcc;wXINdJ0iw&ra5E`VI%MWXSzCxivdLe9F&Y}nKYmU{LmEa?;!e2OE zNB)Jwl}2P2J3u6Bf|>MGQk3Zk50iS`S&NMLl5-2H!FJb!b;@V75LYvS0D&$7-2{5@ zlxwwB`G`K?WhOHTQ69kWx@ufxjxrJ?9lXh^DGw~&*RB<)ccImtSD{bwo$4Bm*p{WE zDjZbX$wD}%nJgp0@}$+^s61IFsv)(HE%jOrQDrIIZL7qWSVxVjywcO^tQvH5n&e!0 z?yXj}W?GZgM6GzU*>1S!5QT+os5UUX+Cxoim-JrEG@DgN4a5{Lt1;p~EOYc~!&G@= zPV2HdGD=oAMD2n?ehR8b>a%Q!K0rSM#V%^I2K;PI>OqomzrK`ZJt=~?5Z^6` zq88+`HJpjW_{o$Y#v_sh`&BBH%qDEEZE7(pJ3wp&OYvy}PY@qXDS)gFN|KNk1w2;k zY9yn`Y6*5qT2=`OULpxtN_RQuFVqHx_JdgZGXRuTh3!P&vFuUihK4d)3zeS5%I17! z^O^9q%Fd%}uG^~$F7Is(?^)-d5bLmvi2Nu;$wAH&BjnNkroc5 zC&?xa-CHY&&%*CH_}zM1jX$Y-5naH)Ugp9VSUU?j`yu2@3xal}#s98<7_g$gO3P+h z2_0Xf82+Nshgcl1pRgQ%iJ@Sz)jU%L;ih$pn@(}lDQ^0#{se+FJlXK5%8=FJR~w=Y zqA{zAdcpp`o&@3%ujBQvY4PSpr#@>Sd4u*)kN3iEA8+j0VaR^B%tqdjWq2bQ_f?8F z0c~EQD^4-Ig}1(@;%y+c6X_D~0KQV;okSm2O@m*wm6VdnRW4J}n>FEX&e6%c`6_U5 z-3zPY6}Pe>qIgdh!Qj=WRMX~iW=wkCo25Zob4rypwIBI8JlFIzYQz6% zTCN#_PZLwPtGQ!_oVvx+vu|))Gtl#8bE#!OJtxRXbBN}AvSCS>=ESZoiLQ}y+LWq?^Wk~TBPvcYEAStgzMkKSCStGMi zI2a}~Vk~1(EMA)9HbjI3Hxv5V>H6iwlwz3=6w_8Bz;vZ5!8Z z-MVhmD7R_s$_rci$AKIj-mqb~txca91_QmmZMy&)GA112ps@Eu#5lx>1-Xboc(!rrqwmEdv8A(hicEMB%cDSrl z&T&vk;xZDXlfZwsX5zqvlQCXaMG|RojM(%Ouo6&OI!UE$9uG>-KENfA)`(Ox{$;xr!sUS`X)!6#e%&Ce5)BSg;df)tV}fV{sO0S$-1 z^_D)(Nzh2Qv9opkjF&sT_T<_{Z)e`yd6QC^M(Go5!R@e_4I8RY6D%=Q1-5Z-E+cUq>y(zDynGf4nWFeEgC7iYtA?8TeLOhZB2`|K;9N8 zSgH%Qp7}>$I(*JDSg<($=&YHG&&C&>zP!_S&DmC{swuc?iYADAi_+T7#&0OC$y`*x zhOK`0%r-{!VMv?{kCYMOr3Y7DX4+Nog>T8+x>pP%N{hs zX)af52;I=n!s|*K8fnyAY46tp^I;DfX<9X0~<@uO(O&s?RdfWBIVM%tOH9%6L0 z5xL2$1rhWs*iLZNZ^IY;oimj%sAwXf?1E#2dXPXjfUJefEomL%F2boFC&#qR>`o?Q z$|fuw=L`?`ZSf_rI7f-3`IK(8q`Qd(NYzV+0FF@Cncjr!Rt4DzgzY3Duv8V#cmT(XU)U&lL{<`ftI*vbT-`}Vt15Ra1*7Ff5 z6@&|_ATHg&MIsl^;>ixT#zDwRJl)|%1^h}!8*(mu)bV{9ZqfaLCiDZmCot7{me^Pc zC{0B19wY2`-G+rhg1ch^FTR2Q8E9EfdW>w8psT?Vpya(g_Romp&xx8zLx;Nm_P@QW z0e!x3u&Wl0{D@fnn7|wXq%)C{w_zZYPA3yv(+6XMxS7N=tb?OP42Hj!>u?sXx- zQ8L6fP|JjS+Jz0+=(=g3F!9K=(l31g(?F9-JSsW8nmTpbs_vVCR&CjropVh9u@AeF zf9L-=|HnD!fBrrfGato_e=!)e6#iOPPbH>Wibf~+S+Q-Dp(&n0`&ZhHoMIjjJw=V{ zcu<_Rqjg<&TBZU?S5@;Q@}}ka9K$K+6;<81`6=72|JPRa$kswr!xX1JLUHUo{m`FP zmT9m|%WINe^h2`^ePOa2mgCh-0>2J@1R9Zo-U|MRw$Z-;8uVG9M$K}jBh0vY;VXI< z@RFqq#HZW+pgS1PruiV35TaSg1w&ae7~;i9c&rN*nE_x~SY$SUdJCQmofstWvOuD_ z-EL?lLLF*THG$fNVU-%JsUwnlGL7N#>71W|#1JzPF(R8ovUdW50Xx7R(2RN&aG`ni z%bM@w4S$XT)Ev6h>;wvQhHXGItOos|*^W+i+R-J}i?$hT=-;eCmhEn~z3!?}(;QP! zh+bfW*5Gz(Dk8Bl1T7VXv50W&(J>-NaWuapzX3p|umIhal7#3$2O)b$#hNouDs zd_jFPOChg*Zlwovhc|@U!FwR&W!@ib#^g0O2>F<6%_>6sK&XA;U-}*vbfLPM0o8hJ z0G~m7YTg2ER~&j^lN5r8BS!LKJPRc{!9g=>s%->XG*G(@)T3hU+9m@rY9*j2u$n*z zfdGLZ`n+~vNM1t^<|QT{#$LJzsm?_vQ`rb7F_0H>5}OpVnJ|tATZk6$f(DOdqva3p zcEb5A2rm5ASyF(L=s<&uPRjet3Sbfxs3ap7)C6m{Ju3fcrodn=Ewbp-&W6`r_SSjq zlYG<4f-*@`f9fMw2MxG9=$9_FQbp#V+r|cFT3ujJgtenjT?T|hbgN?2a$Qfe1(E_? zV82VfWT&XzxHhLX)7pZjppMc9>3z7apt_(%U5&X$vc-ND_Txd)#&|KD=F<~Agz_$K zK}(ITyL58dL2~49H-RxSSs4)oUW5~bR&bF?NgvHa$Y;c`m`L-G_?46bE>uxc@EK0f zVZp<#BLm*P-AzHifThAs471cfP1X~AuNICn6%}Q!DVv%~rlzy%k4?TMo3o-qx0}wd z!i&Mjl*kB)SX`8}iF7Ut#YiT~OGY7^hfyA9F9?wsA625edOLlSLGQSagRAIrb1gcJ zcdK`e1J}wLLmhJv2z}^cbH`&5dY82*)de-&B2Tw_d_ax*J>z z-fmux@iMzYttn_u0BA%VEgKcu0*kUONjlkp-Zwd#POEVtG-A`IzJhiGmK2JAuR$HH zy#{UJ@#*Q7!`EmyU4cGDar!d~&QJiDGM-VOK~EECLwAjJD$aDlJg-DE9%o%alk`6o zg80{6u;2`xUO-Lan(U)afY&a_xK~D3AN86a|17^(8~}bRTH)OTeCVLJM-{@>Fomvo zSC5k}wB!2WO(R3@!R^~ehqqooHstp0gfSj(ynBiXuIcno={99EB7aci-OsqEhP2vE zsl@&~Kjjwk(4FGl6WP3&&A6k94h|nsHZQny_`J}qHrGsG2W-O;&I5^gCBYx?*Fe%w zC5>EO_-+a?NqAKxm&0WQ+X=%)xO5^zF77JK{?8RBQ?Hb~82tKb&F>?E6al&L)0mRXkyj##RAeH>hvggvC}J_P z`2Dq0m=H+Ud7{usrHB1}s^di0i%$EWo3T6RMv5b4`^u7iP zxTLqDSKHTtf1n%fBkHAw=3kBcd<505>YiD$I_7*uU)kDPvbL73!ICw&WUgPbu0A(@ z?)j_CqPc&`>N*)a`GZAodeNNuo5MAiE~cyb-Ep)pt#DOzl&$kVrLq~nrc?%FMFulv zYb;wmC9CHgvuO3)v38X89VLB7B}nOOD>kY>0luv;lx1c!{cS}{^}UE$54QfMVx|m% z2LkCohXbP?aCvYY#%q2sTEkpxA2ed-`Z_S`WUj9tRAT1F02r-jZfxAti6B z*}DSMw~S!a&D=7n3GD;~>t$?|(M@oxA6Ss0BQRsb;UH;c)iRnPR5tiXi-^%U4<9~3 zAdy2vl$vljn!@)W9A16^%vM)rL$`tr;9c~2upQVJES-mFa1b5uY6X+%N>@BUjH~x? z3!!9(@7iAK7;J>+6adI5KVZ&Kz-ZlBgLmBJ5kvgj~H}cYDBl z3xDcv1T#M&vyKutMnGPmd~9?+QMJ~E@*?h2+r`Ng4__eubfdVf!AMk0WHXYgs)lb9 zjp57Pv17C0XbO>{*!(lPs0Dv-y=dNYG3OL$xj_pKXM_#-(X5&58`4=WpW+ALMXVq>3#ZVrwQh7_?MvP`4FY#5f?w`X+CU7P*flp^9G?pp L!(UN^mmU2VVIB=0 diff --git a/superviseur/__pycache__/llm.cpython-312.pyc b/superviseur/__pycache__/llm.cpython-312.pyc index 4b1732135d481242b7255e67d1265272787b5388..2382143adfd00ee2e21628b7f8b8c10686a977d5 100644 GIT binary patch literal 9012 zcmcIpe{37qeSb&Z@wa}GGD%TCP7)>YBw4Z~TXtkSvTXUcEhmwh){0$*=A9(U6sg`F z?T96@vFub`~AM}z3+SP`~7^s_xD9b76jq?Z~i8<(1_5laX|~@PG(z#%sgVz z2x19V7bZpsCDo1SlvF>WS5k6>gj649&rfvh47w6^k!s6Yz3?1 zNLCL&lA~CPGmM&8!|T+Dku`Fry>>LJV@8ZpEmL-A&4zzuF@1A?d<9phz4VmTtpN)E^~q(>LxhI4}^qZlxO{L+d58i zVxU8Kd<8qg;mP)?Y1!oWhaw@-?~mIbGrwJ{#FtHIgXmS1D@L{ZXUGkcN2>DS)GgJt zspa~EIIWeA_s@_Yo7~&bAIS!u1NKIOd4@qHX4h-*+g^a^A|f!0(FEjo2Y%n)^%Hr9 zKOVum#rzRY7#`Paxp#Ila3osQQ)V4Pf3CkxFhtyQmJ?}svO%5;h#Y-xc=$Pb=ZxAJ zk}n22vLP6b3LGmN1EDBBM7iixI0Q#9q@Lw6!7I$e+o$gdnn^Ql=U9F?>)9jH)rWX8T!yVeRyVI!&WUR{W2wV z+C+aTU>7rSPA3L0%|ea*r zC}~XSct^rGfk*8MtS+Hr^>64jZAO4VTnkKNE+!Ye~0rUe)P&bBxy6e>lB`paHYsQ*qqG(rF zC~7zECy2%UthnD#&`2Fe&S>-6lQ60oTK}nJ5Nsqro+(yt6-5Uiqga)?#dJw=|4}O z8V`s{FQ2McgHuyX`y)rktQolTP<5J960Fir${Iw@NVw6AQL47}nOqc^#T@QASRjj*-2u9xPUaK?5{ zc_E>1#kgKe++?wQ4JLp_;35J!?1O}dJAn8Wh-70_!BIlo5SoMuI~cQ~NM%D{3O32g z2JRJDCabDoMf;Ky(NILT1OYsVfp93!$+n%n_{HfdPPPbQfENV}IG7?uo~zT<;5ln? zMB}IqBH0`g{85-E5aJnJHtz6SwvNWaVeR=7ld=gvdq40(wiLW{e0df1u0^WOD7t~q z(7!_~UMS91W$)QhWzOjX~8?L^LiDr>UtmW;bas`5&e zHBxOuwzelz+auM~KeQU0#os>*Q+n!VEs-6~{;{?8`%TZ^Z;Y&aqH`vR-oG@yG_n$3Yg%)qYc9-L3#YAY z#M4$WO9!*9Co`=l)1Ffg&6Klv=IlcoDy^2hopZ(oQ>L`;p#j-kix;ID<};)(a?e>L zdv(^{vTko#if22{WIE1dJD$&UJfD7Hhl9s zKVUWSJ;2pqA>=SZg`z^oK}_aVC{{naf+l!&tGc8P1TWeP#(>z?CvQHoAbSi z*pi&a%TL|VgtI8#5i98F61lRS7 z9&IqR+OX=;#2VhP{t7jFnY66S0U4bnQAv z5V4F>0$ZA}fLhbBW$%`2^psPyvG)89?0AhyTV!Ns2bX{E4vzgF?ZBb!;5$`M*`tG{ zv~|M@&8$ONH3joK)Kw>Jd{cr-*p!_^`c?M{OoqptsYuv­z! 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 DzR#J) delta 1405 zcmZ8hTWB0r7(QoaXLjehv-im+Y1RZc-P&fGn9!)L)D+VPty&eaX(8F{OtusE63)z; zCY_K%i;Y;6WuOU^KpxdZumr&;!Sqp(4Hc4(2=(&dLmxJ_pcEfGXEv+FALcvX`Obg- z|6KkvYr_u)XzV&gd;u8q z*KQ1Dp&NL8#xg49T+tQYs?O->eZ$nNDBpByVsO9nP_6xao0_7X+wgpl(by?j3teNz zlsPsNc7~{r(gEyflK83AwvdFb6ZrY<*HL6e52>1CJE z5vm}Rz;ecqyaesUTPA)C-do9Zg((A>)_DG6wfr7Z$!Hq}(~lw5G{kR4gP-~a^F(VI zgUMC=J^UO3@Ctxn8EDX^ZUK#2r5F4fZPS?hoClGfgx?O>z71xbZcbj{Y!*dq&e@}* z!y2pkHv+9YfWT%@*yg66OtqiVW;VEWoQxO*&Noq&vVk+|KX?`=5?1LA@xM_H*l@aa zOU)@B+T4cJ^12E%`7&P8O?sLBfMIaVIr$j4!Sn#j>5p|%(_!ZdA3NO+fklqkvuSda z|1&LU!&_jLYQ=@%9F8;#F45<}Ec}9=g&Ac&?Ihz*AL*<5@Z?{Xmr@={VK(oZn3&+_ zeLQY5G&+jMQ9pqJ=j-?x*7cQhCEei@1xZ9{th>z1rAb|LK2985B-P~#=A3EirE%hi zNCBW;0*443An*)^4Bx!{ED@f_LAuWp7{uU8xHe~sxw&!6u!_1H%@>Wbkm!vyymL(LzifNLDv#2h1{2-b? z3#!AnT|e>C@Tmy=_J!Dp3bqtD68CL|e1yj!*0`skf?K6NxGMDTeu`M7y z({(N-=NI>aUCc>%A8$>l2|G&fw$j^Rh}2+#5^4B78UXRO2Io;8D2Y!NK3r%BURMNa zYK^WfG$gMpgGi#`MQkX5mmh_Q+FSuio(Z5)vIegr{KZP4uxOMEE^E!r;1-dG=5hty zdKHi0e}Gp9-lAV4v;N)4F8nwOW00SNXVsm@%?%fRp$#DM{JDC2X}MD;vLo)peh?i4N{W>4i#V@u&~ zVU6OcWYXl_xavBiWw3rmer~FMdSY&BX;DE@zM+x6OMY@`ZfaghvA%C=aXe5gD;3Cg z$t+IJFG`6|$}iD(N-as;Jez435AQ9`qWqlH_&lKYWai0&%pwv3j0_CZ8EP1cIZ_yF zm}WDiFx4>5W|+$|xt9N~GBZ?+xrVujDTO7EF@+VVf(@*KEto-*y~=)axqxbtLS|la zPH9SJUb+Ive1*jF#G=%^)Z${jQjq6@4o~rMwNj|k)=>yZEy~R-F3!x)D^}2O@zu0a z$ji^uQSi$wOHC|QD9^|&NzKVDE&(d$M^QZayFjEmOOZ3sv?5m!;RYmb@n<9geT*=& zm<1@RFu71rUd;!{3J2oi9YCUi;UTx!4MB++k~6q3DEpnLI+1gMKl%bk^yKw|4aTAq zA}4sysNc!Ivh+mg1-;-4!RZ$=iY}xVU*Imez*15q05n09=@tvnrKz`AgG+(oJ2_Oy zM+0Ok@n|G7!Au0wEI`Z* z#GhFh85pKB)G!pYrZCnp&Ssd)G3@NN&IhJ4sO|~kv z$r}Y!qxGt+0#b`|GmDEe^Ye-oQc@Li)Jsb;b25t)OHxaVtQ7L{^At2(d^L3x{4&c@ z6H67!Gcrq3f$}9*3RQCW^iH-Aj8tSUat6Au$Q4N3;?GDdjxRviRt$3bs3 zI1m@F1`-Vn54pu|2zsCJI$?8xKjH#M#N@w%4Qe_Y<5#+#P`#iXa3LV<dhnl!6P~ zg%?-~iv)n0G#PKP0G*mTd4rG-qxa;$Lb6-|Kw)68Fcb$(RuOg4} zo{}a~mti+%r$?-Zg>1`MBj(UH0}wC#mI{~R?vIcQ8C_*ZnV}5HDCuOwC@blY3PVQ8 zBxM{$Lng@pZRSH-xB22$!w->zZWONv5@Lafuw5#!5WVRDEbd#T2P?ZkkjU@_e2UNG z_sz&|7Sllq-X9E3J~C>6yk;KOX}$YAfq?A4c-nbZ!#zOmi!DVvkTxNVP5Jy1IVo0K z)dN{YCn}(1J^2^WA(m66LRZiq#0d_|Qo^XdlVPvl2d@%8LB1559SPnS7!4*&aIOdC zVeb^iw5^-87dxstsVvu@T+A#P;4FI3@B;kqKd)h!7fob;`AKw+d{th=vG^rYRPnFqi;G`W zTtnI4GtHUs|0?wUsb$VI-bhe|i~Lum1^u2BuP7pgZWB9aBGvBo^f6gb(IMGi}D>cgz5hH5IIm@l;xZ=y~0Sj=a%)5$#OBz z71l}_xiI7v<{X(epn#9~|Id*=ISgL&XAC)roU`*32Vg_M%h=CrjlkZpMmj2Ci z+#oZJTBziuQfL`uPO$SzQuH|JLH{bn?t0hAtMHV9c8+A^3ySGInzbwx%v=Hy9d1 z)bd5~dG-1|(6^1r0r|N}+%Z!}-mfm0t!eWIy&iw4qh_h)G98r<KzJR#%iLN!`iU(-L6l{3*k)i#bsepH%FEA#mmJPiX8B-ez2E-BU zlg4CmG>AnvpU_i49S#7bC$uW-lM-4mKSf0XSdqIdiK@fECp3Ov2wIZHO)VNzY)SCb zp3Z}ELZ`?RlcPSrjJv7S=nD;}3|W?N9~B89zbsE;3fU@5Cj=ji2_-nc93VeiWrxf0 z%T=ATNg!0PClK;t--rz3;20*8K%?t_qRFwPxCKM8e zAKH3?4TcgLEKdXv%5HNKiuTcA6k_o6lpFz)$g-s1Zg^yBbX3M6TtoI(H`XLfsh6Ri zR|u=O!VDwQ$fQ2OeNas@`9*a}#!JA4J_W%4jQp{Ba|XJdRT4LrM2#h+t!4wNy*OL5 z5zXE+Gv$Nm#K2vL>$a=!oq;>9zB`V-yUxP%hBJm}#jfb!p6IS;qt6aU%l6)Jdj61Z z7>o|d(NTYFXd*foh?WKKI42i1Om4w>-5K3^(-~9TSs!!OFXW5oH=fxT&u@?Aw=YyR zzdahOYG0^amHc1SGlc~m_Zgv}@Ka8k>-sdC$#I?3;7x$oAvQXQPN=bR0 zIQw964U<`Lmj5#JGVJSxoc<1UHg9t!^YLb%eoxZN$JiSj9dV%(=34G zrVUz$(9K+-ztnKEkm|cxA@tYjZ?4qSPLHwuYlWMw8sN7ibROxTC*YMOFE!b8S#khB z0E~H2n?eTm2peVt2J%~7&SMcS%!SY)R^lQ&KsXN&E=WQ|6Xv>^Jz&S*(<(~}k7)tW zH2~-WIZ*G&(@5GGK#z!KzL00a8cDYwOaM!gKEjjYW(WC)`bu+#BwT=-KnwIHuXnjf zMng8rAVm$O$UuJ8kV6I=EXYWL)||F(=D60&jxk<#55z1HEqDP_(hEpt;4LYSz@230 zGkNG0(WU`Bq61YuoHe2+j>ft=h4xfSn2|Em3&2KjAT&n$vl6h8;>L=m83+KStQiBt zENRUMqtJHACS`~9;HK>7I4LKb0h|Lk=NKO`kduuLORj`m44hUeJ*}{TbT--RU31H8 z&jVgvyM&~C7x*-(;GB@212OaEJR{Kqu-6;X(x(`yP@S_#olgwwU{vurZN#W&6g5z# zdl)Yw#d@2zMD1Bh_B54}x0-AyOvL7uI*F6YUgaYu^;LY}vXRZrc5M%E zeVIGOeOC~eh?k99T5aqf7=l|@ zqXXov)+Zd)+0U?RL=`w^xGlAvYP?8Ht6#Lv@YP~f)r_X9N?aqBd@No3@#^#3?mQLp z@o^ZaqI^O-Ap-_`!DEa8Qw;KicG`mj;Of*^G{Mu@Pj%V}4xm5jCA9lIA&;WqWO(`) zRNF9lxqWBL9;$$+PECzZRd43bN_vK~w9Vw53Ms*flp{!Jk`93wJF3u+NlQmF`YD;{ zC@v|aD(Nc^WdTXKgT1LIJRqa^yN(SVzotDh;k=Ro!J>{St&5hdJy~!mJKniH*17$d z=C>C6f^7s~JUjQ8E|K?iROkFC$8pTCknJLs>%Pwq{-$h*ytgiwAG+<@P42F%bpPV% zOWQwOcc*>#Yf5~@>RT&T-|@(C&v?u;e%s@ZIVYkALNQ0^woSR{SbrFy-Q?v?X|{Q@ z3BB974(R39>^@%ifw9X4m1`?H>-ucWhYr-I=Rb6=1pc4+wmt)Mok74~M+iDyXH}ll zP+qU{2DZ=2T{p3`k45cc@HZF%M%^eE1X{`9pyEv#0GtiO zKy03j(%%6ovD6nJ6S3NJcz|UDrkTTIyP_pucNLPlZe2zIjWH1xkW5DoRM-l+F^Ker zm()qnGEAc@wS-A+mz~2d`m8q~M$x7k$VWOS`MK3bKH_x{ zz-sWGuhJqlgfFJ3LcVh9tCj~Hg3Z%EfP)Dze|p8#0_I;5(J0wuvO9lP;=-CotzNZm z&0)>_Nw98s{+V?PGrek_u4Y=IZ(>50d>%#i9}*#a5|c5Mh~>#3Rzw=>Vvia=Lg1!jwcnkc5hs0s)Vg?%pi`N1oPLc_~z8&0m@tyN8W zN5T+-$T1~MSiGJ|WeW1&v~`=OJ)z-=Amrac4C_zm)I56FC*h?iF+^`o%C3`f-d?hL zQ_+r9@b*JZK-5V8Ba1C=skmjScteTTcHOG&S}DeTl#Lb^u1bkT8S4m#EKg3 zxEiBdpFCz+$SsKHu8ifbJZ6S|Ma9SXJG#6D;_WM${Zzvg6u*`oFK&$$x5kS*V#OV| zi`U=I@4Uwd`i8mwV;fJ5EV7)b2Q5J0HgR%-1mo87sI?pvW!mG`6*23IH*_&;{h|T- zFPa&#jB3xnt1}-r%o(EDJMQRqexhNFt~2}J41Q#^9^W{(@%X^pK-^d!GnUW3CdDgy zVii4?g10Mn{@VETqQKO4oZf$|W6{QBR(yWfmVb{yF#BC=&MD(bW3*`9CG<`xTF@1@ zcE_yUUo3L8^~+Ef9Nf1zRP?yeWw)(+6??f2bysOFxAVY%fI8jKaHR@C<;p63k3+c9 z?Ci-Bu9_?YG+fORKy=l?^|;8^a)&7kAT$}jfpwB-i=FJ{`TV!ov@Zp>&OPGRSpX3S z5~wu_e3(@<nag%2Rq=I$jUBgB>(=tpH`j2p+h$H<3p4*$Jfo)*q?W9ebg3mb z^rn~WsyxK0d3O`Q!hgf>2k_ep@IXIXsYQhcL2(k~E|}GXg>Rq(7ZDB%^9LZ@h37Il zfSxwh|LbRZHqpc};PH$5WIueW5tU#X3*1L8)fD zo7H0KPVswW)8ng}=|{JR6Wt9Afc21K)!l>XOjirpla4rvWt>(N(L$M z0Di9?uxf>jkRx$ZX3MaJ``^mIw2%%&V{_9^Q~uE<9XGwyy|#fYb>wz z9eZ^Bv(df#?}TRlhhY@d$$pZ2sI}f?t(U#eltbf2Hk#LZpJDPhvCy2eiMCRzrK?#q zG8P;8eP7*dE|WKcJ_pn>O`^{rv}xT951#h?{I10bAOU;5Ys@;{Ki414>;G`uhh5R! zt#RYFm~k5g321$=$n*M)2cbDQ({H0*EjpUh<6zFB9y9++Cj;#Jd8j9oe?Py|36;xD zsK=(c+^nH|Tj#6}o>zF(W7k{}sO*ZN9aLP^p}w_o<%OxKyOR;8I`#oU<-s@=zfPo$Vlp>THHCwRcZafu`wDb_t7~{QsO1C z{_ zljT5~_KtPl{W$mB&+|LyTqiD|^KT-DbZY(?@ z)bYW{a9HH)I>XVrP9Yi?8r)PDnVu5Flfj5EE!Le32Zx2)sTt9L&C0)K%^)g*fN-J> z|4!M0?28)u9fhh8s>A~Pfy$3e_>ZcH%$TO9BZ3Ikv+81GTfC%xgo;hTm}Z7ULO>Kb z(y54$Tp$}_-_!OZJ67o$9R{dQ)5pW%keEl<>IrGY&+6=~HQQr5Ok_&8g|m}3J&k&Y;8Q8H3Nf*r0zKImt$d9Y7)qARKH5sW9MwV_$^HAIW)K)d>}8U2rlO z4F*ENS;40eNvAX&3Wukj>a_>|&@fcNj7|qb{4f!hO=`&e2!0PAz?Sc(5OtoC5H8wg z%a17}MFhtWrB1TJ!Zt5tE7-J;7m$S1H^A0&BNHG--&>p2yV(`BjUDcB64eAn| zZA6r$lIRoNWcTMgBozo^V#@h$8pavd;Rf2;sFsxCL5b!W!X@sL)S^*RkFy!!Pf|&F zq8T{0M`>Kw?pE+BJY{s`y+QG6i3X~AZQCChjs}MVA&wV@gOOl(atn8A zEI2&I$rqU$9t%uP3L!2U=ElRpN$z+cBJf;zlItAkt?mEfzadS#VO5`wUemIbQBLF&Gwu(HU+VCz2zZ-n`zcdt=;AArj@H+4)R`BXAR7q#!R$MuQ_k z7#Aksoz;1{iUH6;VGH*d`KHOWA)|jIr$0=j#52o+sZ0x;C`<(4W=)RPa{C2wA~+d{ zLV+6&!{T85;mKN`E^UyPJhZ;#NIHKA_GNfF6o?Ah%Au+CWjvvaWcg`!y>BQ8lTE8Z zMx5+hnhs8mgwrh9yR3|K4k+_U5IHT1!0gk=*Ieu;Vl*3rv&UgKHoCAAfz#iNeL!Z- zP9?1+TLuD84o5W5!evrCqhe{BK(>IaAu!1gt*>~tXprF4Gl9v#s36vU7t3A{6)}TS zd`>-jnOe2FQdV!$>YdYkVsu_`tUB}O*cE5)9J}iDJfIk@cW&2;Ge6~QPCA?4S1&ua z$LD%JWi7AnIlCv34>cdMAF$V6x_&e<@cqQTBZ=Ij_t;}AAgOxUSia)%o?}-$9VCf#g-@8@-;Q^tSKq;_a3cjs2uO(NEK|( zD}Gy7GrHmQm%`^aTTxdd{hPLW$lt6+T}^b$%^Ec+G$EiOIWo}!ec!s%Zjh5)EMXh74v5 zzFuX+{%$A!=PIk^Lq=1t4iPlSi zkcucVLUNKe5S7<`!zC#OV8IA}G36=Br=KnA0h1bxMB~9>ZX_&jpiyvQDlA3=lVE8x zU_y45fPkL|-3BO&f>vknV%E%6R5jGs*K=8Y@dZDJJ^zB(pD%bqU=7q4hk=a357KJK z7X+aI5!4gH#Bo84#AVARdZ0F~36L>{g8a83zz_)!gXJ2U$S74>J1Rtnh_fK1l_6o$ zr_SiPth`L79!;b*k?G^(FxyC4l^HCpJst^W`bCI6BibB?U&de#K+SB$Q_B1Qpwt9# zM^=G=0-MZp4CvV9_{I3g*0u{p*8=Yei^6OEgtcu>1LVHZc?GRH3Lj8Tdg z&dyxuzT9)MC!TWGB;7T4jWtB+*abG>X}UK0Ug+J>wPT5{{fUAD_e_H;Ci?~3Le4p6 zO-1DvT-IFFq+E4LS6#~0nsl|kU;d%*1K+Z%d#-oI=(@1!XD<={k}KMabyxQ$b8C~P z+689CoOj_k_K=p`D+3ojNmIoFv*y${XnkvLN^AIq_1yEg;EFkEE>3ES=a^NaZI1o= zfse9nix97E!QADc|BME*__^VA6(bT5Tl}&80Agf(#rGXGCJyREqQD|SZm|OwI-Sl^ z$flXDa40OMm7>6l`$^jYe8Abnii0HoJRx29EvK_`JIRvEAo>Z}0VGXFgA;mt4r-r7^z|!n z5UOW$pSl81nwOuDUgzKf%ecKpH!WgUyE2Dhfb1F_hU<=3^A{KvP(bz+ROgWRIBLiD z8TZ1x4*$J-5sfcS72HC$7%Q>jWRxsbP7*ub2);$WaotzqEg2^Va|IrwRZ{ah;+TT- zVv|_>wr9HnKG&_~SjQQ((XH!3@VlHHKVM{2OwbsaocQIU5+#~{g#WxK_^hRbY5>>j z6o9}X@NE!v4gl}8@(^_jeMgHu(*o|y*CoJvh;V zGYa>lmsBy4kRVKn#8;R7^E4BT3UIDL(rD=qObGmbfnZiZoY@%+38EVpmitjBexcmC zTfRQ3z|@p5$%`@4LlFiv0GB0vQt;(uP~(S0G`SGsJRv_PY{qpDV(9qv$Oxd6ScBKf z8w(wmZ5{dhnzC_5yyMI#o7-E$0*zp9P{qhDV8lIDYhiRmf*YIPE@#PujoPM zuMCvKb^g%8p$n%!wpXleEyRy~dr&FfRmsJ_UUO0Ag4gN)iu@8Jz2fMrLKpLU9n{~n zL+-{V)JM}d8aq8u_{ievvoRkv_%(fM^*^?1pl}P7L&GgE>MK&+s_<`y!fm&`uS9XX zf%Ldzp$TU$lf*_m9V2LA#G?u1d^E3?^@Qg&F$Lbc&4KS# z`3zbf0>MmY;Kozia&c+3U9D|{x~L9+xy?=UI*Gyo#)i++1_Q4j2Uj4QaBh2HJ9r7q zx|d+gn17yK*T5W!;SHJmCE_rcX<}BH>@2~cXC(heb)C`}Q{%##`aXy$K0lA(hWp8&XTFT4o?dizQj#`1l>v$`kS9?nPryUMHJ-bqj_I^y6JOln zw(&(WL-CWY4mkwJI0?ePl_Z^fKDTOZ8eYMdyh+FOa>avM8|Dh_`TFd@5M8n;;>iUK5jF@uDpK8u@C@(duSQcA3i8KcBh$_daMr1q9c zMhJ2h*(oE6FDEs;7o0d3Um>52?-Ja!L$K(W@g*bdy8JzbPOXn3<838Q)X(Fi4S#4R z5Y+EOX(kjtC5S#{T2Wh{MkgQ~BDhHOh~r+C5$UnEZB&>PPEU#Lv(31nwG_X($*N!w zes@zVn#2FT=~)W_>RH7WP6oDFWq+L??`{04xqp_f;VLU@A$r;&eBTigY3=T)qN^rA0J|WYa@m3KnKIz~HnibzOC|a>e!Zm$y@wMmMP&t~uWZ7JS&$+41)0i3 zUVGY!+gqKuuC=`75%5I*2ypNyW41Mv$(Aw}-!&GmSdW84Wy_t@r1K9ZG_F;Lb56fv zbERzFq|J+Q>(9LhQv)N(fsv0(M{jSwN?#rP6?^5SYx~}(-yb9~*WI$6cS}c?^Tx1$ zONI3cpDJ%j!k??<{m!Jbec9Tv_}Z425E{egHa_0kw-xusg()FQ~=sYAeYr(VuCs7St9&bKOh+m&~=DhSUunWtR| z`6Z<7Yf&!gO8Od=OErk(YZ>UZRN2UoLW>d#Pen=_FFQx*^_Lxj*?RC?>=FWMAj-j95y@pvILdD&35?1AF$et)E181@ zLG&R}LmTfz(L4fPxV?b2z=IGqv>_2dx)A?vn-dkv>$qQF#ZzWY4x*v}vza7ev)PVY z>foWztjWu&H2^WVGDqN!LFC9t%(#y{6OlzI;em;C0lT%0ny&`bRl&i4oCc}X5y3mtxWgIlmU#2!OtoqhJJQuH+fK%pJA%G2)IC8 zbWGqz;Dsi{W$iaS-;j8(nu8Y%?o@C}-~yo#Fh|IH6~_mnf!h5(Boa03pLOr-?f38D z2A}Qi+JXOMXMT4FRFl|n;LyPS9nWmx{Loi^t$9iUHx`I+#|2@Mo0=9!A$A-Q!xJ2Y zWMOfpb|>!G-i`ld=U}5#>;iG(G9g5;I86wN9>kM``~XN=Ln1%Cr;is z4yH&#g0yOwcqbw8Hfh^V$T?E2lb@L79m(L6mJf(0hDJqU#;1}2C#@$NHI&(vv_A74 zl08{Qj!t0)GV^&zKHZ9hvuZPBT{{%eY}uh$%TN{NDVn42 zY4ShS7+%$%)hBER?r8>B@o)Xb$A0hTuGmsVEy<#mR8f1fsC~I;`?A~rfKq5To!v9n zbME+x#df}Cp$6Bb*rEhmv;wee@+M8*tD2;#VT}PkKwqwu4B&ohfE9xU+j{HcbyWTy z^ffT$Ov#^ZLHN*QeqXOSsGMSWGNQG*$B{`mh*!#cs?k-{%~3R3os!JAG)s&mwLnx2uVe?-9~W$Z0~ze+yO z_JQDXRep;COEkQmnO z-s<8Yo7S)YbEg(!LXpG?;%R(z_hyg0jHj3OSkpEU=BGnKyZ8ruZ8xu;qLJ', f'@{mention.display_name}') content = content.replace(f'<@!{mention.id}>', f'@{mention.display_name}') - # Remove bot mention - content = content.lstrip(f'<@{self.user.id}>').lstrip(f'<@!{self.user.id}>').strip() + # Remove bot mention (Désactivé pour que le LLM voit qu'il est mentionné) + # content = content.lstrip(f'<@{self.user.id}>').lstrip(f'<@!{self.user.id}>').strip() # Handle attachments if message.attachments: @@ -935,20 +945,35 @@ class Superviseur(commands.Bot): permissions_info: str, server_context: str, channels_list: str, - history: str, + resume: str, + structured_history: list, content: str, - message + message, + is_monitoring: bool = False ) -> dict: - """Build LLM payload.""" + """Build LLM payload with interaction mode context.""" user_name_info = f"Nom d'utilisateur : {message.author.display_name} (ID: {message.author.id})" - prompt = f"{self.system_prompt}\n{permissions_info}\n{user_name_info}{server_context}{channels_list}\n{history}\n\nUser: {content}" + # Indicateur de mode pour éviter que l'IA ne bégaye sur sa légitimité à répondre + mode_indicator = "[MODE: RÉPONSE DIRECTE (Vous avez été interpellé par l'utilisateur)]" + if is_monitoring: + mode_indicator = "[MODE: SURVEILLANCE HEURISTIQUE (N'intervenez que si nécessaire via ALERT/INSIGHT)]" + + import time + current_time = time.strftime('%H:%M:%S le %d/%m/%Y') + time_info = f"[Heure actuelle du serveur : {current_time}]" + + prompt_system = f"{self.system_prompt}\n{time_info}\n{permissions_info}\n{mode_indicator}\n{user_name_info}{server_context}{channels_list}" + if resume: + prompt_system += f"\nContexte global (mémoire) :\n{resume}" + vision_model = any(v in self.ollama_model.lower() for v in ['llava', 'bakllava', 'moondream', 'llama3.2-vision', 'minicpm-v']) and message.attachments return self.llm.build_payload( - prompt=prompt, - system_prompt=self.system_prompt, + prompt=content, + system_prompt=prompt_system, + structured_history=structured_history, vision_model=vision_model, attachments=message.attachments ) @@ -968,7 +993,21 @@ class Superviseur(commands.Bot): # 2. Nettoyage des éventuels backticks de code et résidus de JSON clean_reply = clean_reply.replace('```json', '').replace('```', '').strip() - # 3. Filtrer les marqueurs internes fréquents (Leak prevention) + # 3. Supprimer les balises de réflexion (Thinking/Thought) et leur contenu + clean_reply = re.sub(r'.*?', '', clean_reply, flags=re.DOTALL | re.IGNORECASE) + clean_reply = re.sub(r'.*?', '', clean_reply, flags=re.DOTALL | re.IGNORECASE) + clean_reply = re.sub(r'\[THOUGHT\].*?\[/THOUGHT\]', '', clean_reply, flags=re.DOTALL | re.IGNORECASE) + + # 4. Nettoyage des tokens spéciaux de modèles (ChatML/DeepSeek etc) + tokens_to_remove = [ + "<|end_of_sentence|>", "<|endoftext|>", "<|end|>", "<|start|>", + "<|assistant|>", "<|user|>", "<|system|>", "<|channel|>", + "<|constrain|>", "<|message|>", "<|thought|>" + ] + for token in tokens_to_remove: + clean_reply = clean_reply.replace(token, "") + + # 5. Filtrer les marqueurs internes fréquents (Leak prevention) markers_to_remove = [ "[Public]", "[Relevant]", "[Irrelevant]", "[Alerte]", "[Insight]", "[CRITICITÉ", "[MENACE", "[RISQUE", "[DÉTECTION", "[ANALYSE", "[ACTION" @@ -986,10 +1025,10 @@ class Superviseur(commands.Bot): else: clean_reply = clean_reply.replace(marker, "") - # 4. Supprimer les résidus JSON rémanents avec un regex plus large + # 6. Supprimer les résidus JSON rémanents avec un regex plus large clean_reply = re.sub(r'\{[\s\n]*[\"\']action[\"\'].*?\}', '', clean_reply, flags=re.DOTALL) - # 5. Supprimer les lignes vides en trop et les espaces multiples + # 7. Supprimer les lignes vides en trop et les espaces multiples clean_reply = re.sub(r'\n{3,}', '\n\n', clean_reply) clean_reply = clean_reply.strip() @@ -1010,7 +1049,7 @@ class Superviseur(commands.Bot): # Store interaction (Even if silent, we store the input for better context next time) user_id = str(message.author.id) - guild_id = sanitize_guild_name(message.guild.name) if message.guild else None + guild_id = sanitize_guild_name(message.guild.name) if message.guild else "Direct" await add_interaction(user_id, message.channel.id, message.content, clean_reply if not is_monitoring else "", guild_id) # En mode monitoring, on ne répond PAS au canal public sauf si l'IA l'a explicitement demandé via une action @@ -1088,10 +1127,10 @@ class Superviseur(commands.Bot): action = item['action'] if action == 'NONE': + action_executed = True # Bloque le fallback text même si la réponse est vide resp = item.get('response', "").strip() if resp and not is_monitoring: await self.messaging.reply_with_limit(message, format_mentions_in_text(resp)) - action_executed = True else: success, result = await self.execute_action(action, item, message) action_logger.log_action(action, str(message.author), str(message.guild), item, success, result) diff --git a/superviseur/llm.py b/superviseur/llm.py index c0a823ca..10652095 100644 --- a/superviseur/llm.py +++ b/superviseur/llm.py @@ -40,34 +40,60 @@ class LLMManager: self, prompt: str, system_prompt: Optional[str] = None, + structured_history: Optional[list] = None, vision_model: bool = False, attachments: Optional[list] = None ) -> Dict[str, Any]: - """Build the API payload for Ollama.""" - payload = { - "model": self.ollama_model, - "prompt": prompt, - "stream": True, - "options": {"temperature": self.ollama_temperature} - } + """Build the API payload for Ollama or OpenAI Chat API (llama.cpp).""" + is_openai = "/v1/chat/completions" in self.ollama_api_url - if system_prompt: - payload["system"] = system_prompt + if is_openai: + # OpenAI Chat API format + messages = [] + if system_prompt: + messages.append({"role": "system", "content": system_prompt}) + + if structured_history: + messages.extend(structured_history) + + messages.append({"role": "user", "content": prompt}) + + payload = { + "model": self.ollama_model, + "messages": messages, + "stream": True, + "temperature": self.ollama_temperature, + "max_tokens": 2048 + } + else: + # Ollama /api/generate payload (Fallback) + full_prompt = prompt + if structured_history: + hist_str = "\n".join([f"{m['role'].capitalize()}: {m['content']}" for m in structured_history]) + full_prompt = f"Historique:\n{hist_str}\n\nUser: {prompt}" + + payload = { + "model": self.ollama_model, + "prompt": full_prompt, + "stream": True, + "options": {"temperature": self.ollama_temperature} + } + if system_prompt: + payload["system"] = system_prompt # Vision support (simplified) if vision_model and attachments: for attachment in attachments: if attachment.content_type and attachment.content_type.startswith('image/'): - if any(v in self.ollama_model.lower() for v in - ['llava', 'bakllava', 'moondream', 'llama3.2-vision', 'minicpm-v']): - # Note: actual image handling would require download - pass + # actual image handling would require download and base64 for OpenAI + pass return payload async def call_ollama(self, payload: Dict[str, Any]) -> str: - """Call Ollama API and accumulate response.""" + """Call LLM API and accumulate response.""" session = await self.get_session() + is_openai = "/v1/chat/completions" in self.ollama_api_url async with session.post( self.ollama_api_url, @@ -76,86 +102,132 @@ class LLMManager: ) as response: response.raise_for_status() - # Si on ne streame pas, on récupère tout d'un coup - if not payload.get("stream", True): - data = await response.json() - return data.get("response", "") - accumulated_reply = "" - async for line in response.content: - line = line.decode('utf-8').strip() + accumulated_thoughts = "" + async for line_bytes in response.content: + line = line_bytes.decode('utf-8').strip() if not line: continue + + # Strip SSE prefix if present + if line.startswith("data: "): + line = line[6:] + elif line.startswith("event:"): + continue + + if line == "[DONE]": + break try: data = json.loads(line) - if 'thinking' in data and data['thinking']: - print(f"🤔 Le superviseur réfléchit : {data['thinking']}", flush=True) - continue + # 1. Handle Thinking (OpenAI style reasoning or special field) + thought = None + if 'thinking' in data: # Custom llama.cpp field + thought = data['thinking'] + elif 'choices' in data and len(data['choices']) > 0: + delta = data['choices'][0].get('delta', {}) + thought = delta.get('reasoning_content') + + if thought: + accumulated_thoughts += thought + print(f"🤔 Le superviseur réfléchit : {thought}", flush=True) - if 'response' in data: + # 2. Handle Content + chunk = "" + if 'response' in data: # Ollama chunk = data['response'] + elif 'choices' in data and len(data['choices']) > 0: # OpenAI + delta = data['choices'][0].get('delta', {}) + if delta.get('content') is not None: + chunk = delta.get('content', "") + elif 'content' in data: # llama.cpp legacy + chunk = data['content'] + + if chunk: accumulated_reply += chunk if chunk.strip(): print(f"🤖 Réponse du Superviseur (fragment) : {chunk}", flush=True) - elif 'action' in data: + elif 'action' in data: # Action already in JSON (unlikely for chat API) accumulated_reply = line break except json.JSONDecodeError: - accumulated_reply += line + # In case of malformed line or raw text + if not line.startswith("{"): + accumulated_reply += line + + # Fallback for models that put the final JSON response inside the thought block + if not accumulated_reply.strip() and accumulated_thoughts.strip(): + # Test if the thought block contains our strict format using robust search + if re.search(r'\{[\s\n]*[\"\']action[\"\']', accumulated_thoughts, re.IGNORECASE): + print("⚠️ Aucun texte de contenu final mais du JSON détecté dans les pensées. Récupération.", flush=True) + accumulated_reply = accumulated_thoughts return accumulated_reply def extract_json_actions(self, text: str) -> Optional[str]: - """Extract JSON action objects from text more robustly.""" + """Extract JSON action objects from text more robustly using an O(N) brace matcher.""" + + # 1. First, try to extract from markdown blocks if present + markdown_blocks = re.findall(r'```(?:json)?\s*(.*?)\s*```', text, re.DOTALL) + candidates = markdown_blocks if markdown_blocks else [text] + actions = [] - - # Regex plus laxiste pour trouver des blocs JSON potentiels - # On cherche des blocs commençant par {"action" ou {'action' - matches = re.finditer(r'\{[\s\n]*[\"\']action[\"\'].*?\}', text, re.DOTALL) - - for match in matches: - json_str = match.group(0) + for candidate_text in candidates: + # Try to parse the whole text as a list or dict first try: - # Tentative de parsing standard - parsed = json.loads(json_str) - if isinstance(parsed, dict) and 'action' in parsed: + parsed = json.loads(candidate_text.strip()) + if isinstance(parsed, list): + for item in parsed: + if isinstance(item, dict) and 'action' in item: + actions.append(item) + if actions: return json.dumps(actions) + elif isinstance(parsed, dict) and 'action' in parsed: actions.append(parsed) - except json.JSONDecodeError: - # Si erreur, on tente de remplacer les simples quotes par des doubles - # (Cas fréquent si le LLM mélange les styles) - try: - # Remplacement très basique (peut échouer si contenu complexe) - json_corrected = json_str.replace("'", '"') - parsed = json.loads(json_corrected) - if isinstance(parsed, dict) and 'action' in parsed: - actions.append(parsed) - continue - except: pass + return json.dumps(actions) + except: + pass - # Méthode récursive des accolades si le bloc est tronqué ou complexe - start = match.start() - brace_count = 0 - for i in range(start, len(text)): - if text[i] == '{': brace_count += 1 - elif text[i] == '}': + # Fallback: O(N) scan for top-level { ... } blocks + brace_count = 0 + current_block = [] + + for char in candidate_text: + if char == '{': + if brace_count < 0: + brace_count = 0 + current_block = [] + brace_count += 1 + + if brace_count > 0: + current_block.append(char) + + if char == '}': + if brace_count > 0: brace_count -= 1 - if brace_count == 0: + if brace_count == 0 and current_block: + json_str = "".join(current_block) + current_block = [] try: - candidate = text[start:i+1] - try: - parsed = json.loads(candidate) - except: - parsed = json.loads(candidate.replace("'", '"')) - + parsed = json.loads(json_str) if isinstance(parsed, dict) and 'action' in parsed: - actions.append(parsed) - break - except: pass - + if parsed not in actions: # avoid duplicates + actions.append(parsed) + except: + # Fallback with single quote replace + try: + parsed = json.loads(json_str.replace("'", '"')) + if isinstance(parsed, dict) and 'action' in parsed: + if parsed not in actions: + actions.append(parsed) + except: + pass + else: + brace_count = 0 + current_block = [] + if actions: return json.dumps(actions) return None