chore: nettoyage .gitignore - retrait venv, __pycache__, .env, data, logs, modèles du tracking
This commit is contained in:
parent
7333a22bcd
commit
604a5affe0
9231 changed files with 1244 additions and 1601201 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
100
brain/memoire.py
100
brain/memoire.py
|
|
@ -253,17 +253,72 @@ async def save_user_memory_async(user_id: int | str, data: Dict[str, Any], guild
|
|||
logger.debug(f"Mémoire marquée dirty pour utilisateur {user_id} (guild {guild_id})")
|
||||
|
||||
|
||||
# Référence globale au LLM manager (set par le bot au démarrage)
|
||||
_llm_manager = None
|
||||
|
||||
|
||||
def set_llm_manager(llm_manager) -> None:
|
||||
"""Enregistre le LLM manager pour les résumés."""
|
||||
global _llm_manager
|
||||
_llm_manager = llm_manager
|
||||
|
||||
|
||||
async def summarize_messages(messages: List[Dict[str, Any]]) -> str:
|
||||
"""
|
||||
Fonction de résumé améliorée. Utilise une extraction de mots-clés et de phrases clés
|
||||
pour un résumé plus intelligent. Placeholder pour intégration IA future.
|
||||
|
||||
Cette fonction est `async` pour faciliter un remplacement par un appel réseau/IA.
|
||||
Résume une liste de messages via le LLM.
|
||||
Fallback sur l'extraction de mots-clés si le LLM n'est pas disponible.
|
||||
"""
|
||||
if not messages:
|
||||
return ""
|
||||
|
||||
# Extraire tous les textes utilisateur et bot
|
||||
# Construire le transcript à résumer
|
||||
transcript_lines = []
|
||||
for m in messages:
|
||||
um = m.get("user_message", "").strip()
|
||||
bm = m.get("bot_message", "").strip()
|
||||
if um:
|
||||
transcript_lines.append(f"Utilisateur: {um}")
|
||||
if bm:
|
||||
transcript_lines.append(f"Bot: {bm}")
|
||||
|
||||
transcript = "\n".join(transcript_lines)
|
||||
|
||||
# Tronquer le transcript pour éviter les appels trop longs
|
||||
if len(transcript) > 4000:
|
||||
transcript = transcript[-4000:]
|
||||
|
||||
# Essayer d'utiliser le LLM pour un vrai résumé
|
||||
if _llm_manager is not None:
|
||||
try:
|
||||
prompt = (
|
||||
"Tu es un assistant spécialisé dans la synthèse de conversations.\n"
|
||||
"Résume les échanges suivants de manière concise et factuelle.\n"
|
||||
"Extrais les sujets abordés, les décisions prises, et les informations importantes.\n"
|
||||
"Le résumé ne doit PAS dépasser 500 caractères.\n\n"
|
||||
f"CONVERSATION À RÉSUMER :\n{transcript}\n\n"
|
||||
"RÉSUMÉ :"
|
||||
)
|
||||
payload = _llm_manager.build_payload(
|
||||
prompt=prompt,
|
||||
system_prompt="Tu es un assistant de synthèse. Sois concis et factuel.",
|
||||
force_json=False
|
||||
)
|
||||
summary = await _llm_manager.call_llama(payload)
|
||||
if summary and len(summary.strip()) > 10:
|
||||
# Nettoyer le résumé
|
||||
summary = summary.strip()
|
||||
if len(summary) > 1500:
|
||||
summary = summary[:1497] + "..."
|
||||
return summary
|
||||
except Exception as e:
|
||||
logger.warning(f"Erreur résumé LLM, fallback extractif: {e}")
|
||||
|
||||
# Fallback : extraction de mots-clés et phrases clés
|
||||
return _extractive_summary(messages)
|
||||
|
||||
|
||||
def _extractive_summary(messages: List[Dict[str, Any]]) -> str:
|
||||
"""Résumé extractif basé sur les mots-clés et phrases clés (fallback)."""
|
||||
all_texts = []
|
||||
for m in messages:
|
||||
um = m.get("user_message", "")
|
||||
|
|
@ -272,7 +327,7 @@ async def summarize_messages(messages: List[Dict[str, Any]]) -> str:
|
|||
|
||||
combined_text = " ".join(all_texts)
|
||||
|
||||
# Extraction simple de mots-clés (mots fréquents, >3 chars)
|
||||
# Extraction de mots-clés (mots fréquents, >3 chars)
|
||||
words = re.findall(r'\b\w{4,}\b', combined_text.lower())
|
||||
word_freq = {}
|
||||
for word in words:
|
||||
|
|
@ -282,28 +337,25 @@ async def summarize_messages(messages: List[Dict[str, Any]]) -> str:
|
|||
top_keywords = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)[:10]
|
||||
keywords_str = ", ".join([kw for kw, _ in top_keywords])
|
||||
|
||||
# Extraire phrases clés (premières phrases des messages importants)
|
||||
# Extraire phrases clés
|
||||
key_phrases = []
|
||||
for m in messages:
|
||||
um = m.get("user_message", "").strip()
|
||||
bm = m.get("bot_message", "").strip()
|
||||
if um:
|
||||
sentences = re.split(r'[.!?]', um)[:1] # première phrase
|
||||
sentences = re.split(r'[.!?]', um)[:1]
|
||||
key_phrases.extend(sentences)
|
||||
if bm:
|
||||
sentences = re.split(r'[.!?]', bm)[:1]
|
||||
key_phrases.extend(sentences)
|
||||
|
||||
phrases_str = " | ".join(key_phrases[:5]) # limiter à 5 phrases
|
||||
phrases_str = " | ".join(key_phrases[:5])
|
||||
|
||||
# Construire le résumé
|
||||
summary = f"Mots-clés: {keywords_str}\nPhrases clés: {phrases_str}"
|
||||
|
||||
# Tronquer si trop long
|
||||
if len(summary) > 1500:
|
||||
summary = summary[:1497] + "..."
|
||||
|
||||
await asyncio.sleep(0) # point d'await pour remplacer par un vrai appel
|
||||
return summary
|
||||
|
||||
|
||||
|
|
@ -444,12 +496,32 @@ def list_memory_files() -> List[str]:
|
|||
return files
|
||||
|
||||
|
||||
def delete_user_memory(user_id: int | str) -> None:
|
||||
path = _user_filepath(user_id)
|
||||
def delete_user_memory(user_id: int | str, guild_id: str | None = None) -> None:
|
||||
"""Supprime la mémoire d'un utilisateur, optionnellement pour un guild spécifique."""
|
||||
path = _user_filepath(user_id, guild_id)
|
||||
try:
|
||||
os.remove(path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
# Si aucun guild_id spécifique, supprimer aussi tous les fichiers de mémoire pour cet utilisateur
|
||||
if guild_id is None:
|
||||
_ensure_memory_dir()
|
||||
user_str = str(user_id)
|
||||
for root, dirs, files in os.walk(MEMORY_DIR):
|
||||
for name in files:
|
||||
if name == f"{user_str}.json" or name == f"{user_id}.json":
|
||||
full_path = os.path.join(root, name)
|
||||
if full_path != path: # Éviter double suppression
|
||||
try:
|
||||
os.remove(full_path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
# Nettoyer le cache
|
||||
key_no_guild = f"_{user_id}" if guild_id is None else f"{guild_id}_{user_id}"
|
||||
memory_cache.pop(key_no_guild, None)
|
||||
_dirty.pop(key_no_guild, None)
|
||||
|
||||
|
||||
# Fonction pour obtenir les métriques
|
||||
|
|
|
|||
16
brain/memory.py
Normal file
16
brain/memory.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
"""User memory management - JSON/Redis with in-memory cache."""
|
||||
|
||||
# Renamed from memoire.py for consistency (English naming)
|
||||
from .memoire import ( # noqa: F401
|
||||
add_interaction,
|
||||
build_context_for_model,
|
||||
flush_all,
|
||||
MEMORY_DIR,
|
||||
set_llm_manager,
|
||||
delete_user_memory,
|
||||
purge_old_memories,
|
||||
get_metrics,
|
||||
_extractive_summary,
|
||||
load_user_memory_async,
|
||||
save_user_memory_async,
|
||||
)
|
||||
|
|
@ -3,7 +3,7 @@ import datetime
|
|||
import logging
|
||||
from typing import Optional
|
||||
|
||||
logger = logging.getLogger('Superviseur')
|
||||
logger = logging.getLogger('Beta')
|
||||
|
||||
DB_PATH = 'data/mod.db'
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue