diff --git a/backend/app/agent_config.py b/backend/app/agent_config.py index cd4ace8..0553c35 100644 --- a/backend/app/agent_config.py +++ b/backend/app/agent_config.py @@ -10,7 +10,7 @@ from . import db CONFIG_KEY = "agent" MODEL_PROFILES_KEY = "model_profiles" PROFILE_STATE_KEY = "model_profiles_state" -PROFILE_VERSION = 6 +PROFILE_VERSION = 7 DEFAULT_SYSTEM_PROMPT = ( "Tu es Loki, un assistant de développement local agentique. Tu disposes " @@ -116,8 +116,12 @@ DEFAULT_CONFIG: dict = { "plan_mode": True, # Auto-critique : une passe de relecture/révision avant la réponse finale. "self_review": False, - # Mémoire long-terme (RAG) entre sessions, via un modèle d'embedding. - "rag_enabled": True, + # Mémoire long-terme (RAG) ENTRE sessions, via un modèle d'embedding. + # Désactivée par défaut : chaque discussion ne se souvient que d'elle-même + # (résumé + messages récents). Sinon une ancienne demande sans rapport (ex. + # « appli sport ») ressurgit dans une nouvelle discussion (ex. « jeu + # d'échecs ») et embrouille les petits modèles. Réactivable dans Réglages. + "rag_enabled": False, "embed_model": "auto", # Skills : méthodes expertes injectées automatiquement selon la tâche. "skills_enabled": True, @@ -157,6 +161,15 @@ def _migrate_profiles() -> None: if prof.get("num_ctx") in (4096, 8192): prof["num_ctx"] = 16384 db.set_config_value(MODEL_PROFILES_KEY, profiles) + + # v7 : la mémoire inter-sessions (RAG) faisait ressurgir d'anciennes + # demandes sans rapport dans une nouvelle discussion. On la désactive une + # fois sur les installs existantes ; réactivable manuellement dans Réglages. + stored = db.get_config_value(CONFIG_KEY) + if stored and stored.get("rag_enabled"): + stored["rag_enabled"] = False + db.set_config_value(CONFIG_KEY, stored) + db.set_config_value(PROFILE_STATE_KEY, {"version": PROFILE_VERSION}) diff --git a/backend/app/rag.py b/backend/app/rag.py index 35ea48a..30f5046 100644 --- a/backend/app/rag.py +++ b/backend/app/rag.py @@ -28,7 +28,10 @@ _EMBED_HINTS = ("nomic-embed", "mxbai-embed", "bge-", "snowflake-arctic-embed", "all-minilm", "embed") _TOP_K = 3 -_MIN_SCORE = 0.45 +# Seuil de similarité volontairement élevé : une mémoire n'est rappelée que si +# elle est FORTEMENT proche de la demande. Trop bas (0.45), un « jeu d'échecs » +# rappelait une « appli sport » et déroutait le modèle. +_MIN_SCORE = 0.6 _MAX_MEMORIES = 2000 # au-delà, on élague les plus anciens _embed_model_cache: dict = {"value": None, "checked_at": 0.0} diff --git a/backend/app/routes/chat.py b/backend/app/routes/chat.py index 455b386..86a41f2 100644 --- a/backend/app/routes/chat.py +++ b/backend/app/routes/chat.py @@ -334,7 +334,7 @@ async def chat(req: ChatRequest) -> StreamingResponse: # Préparation du contexte APRÈS le start SSE et en PARALLÈLE : rappel # RAG, plan et choix du modèle code partent ensemble au lieu de # s'enchaîner en bloquant le premier token. - want_rag = cfg.get("rag_enabled", True) + want_rag = cfg.get("rag_enabled", False) want_plan = cfg.get("plan_mode", True) and ( use_code or enhance.needs_plan(req.content) ) @@ -443,7 +443,7 @@ async def chat(req: ChatRequest) -> StreamingResponse: asyncio.create_task(memory.maybe_summarize( req.session_id, model, options=run_opts, keep_alive=keep, )) - if cfg.get("rag_enabled", True): + if cfg.get("rag_enabled", False): last = db.list_messages(req.session_id) answer = last[-1]["content"] if last else "" asyncio.create_task(rag.index_exchange( @@ -577,7 +577,7 @@ async def chat(req: ChatRequest) -> StreamingResponse: asyncio.create_task(memory.maybe_summarize( req.session_id, model, options=run_opts, keep_alive=keep, )) - if cfg.get("rag_enabled", True) and final_content: + if cfg.get("rag_enabled", False) and final_content: asyncio.create_task(rag.index_exchange( req.session_id, req.content, final_content, embed_model=cfg.get("embed_model"), diff --git a/frontend/src/panels/SettingsView.tsx b/frontend/src/panels/SettingsView.tsx index 20932e4..2091c78 100644 --- a/frontend/src/panels/SettingsView.tsx +++ b/frontend/src/panels/SettingsView.tsx @@ -432,8 +432,8 @@ export function SettingsView() { "Décompose les demandes complexes en étapes"] as const, ["self_review", "Auto-critique (Qualité +)", "Relit et révise la réponse avant de la donner"] as const, - ["rag_enabled", "Mémoire long-terme (RAG)", - "Se souvient des anciennes sessions (modèle d'embedding requis)"] as const, + ["rag_enabled", "Mémoire entre sessions (RAG)", + "Rappelle d'AUTRES discussions dans celle-ci. Désactivé par défaut : sinon une ancienne demande sans rapport ressurgit. Chaque discussion garde toujours sa propre mémoire."] as const, ["skills_enabled", "Skills automatiques", "Méthodes expertes injectées selon la tâche (débogage, web, refactor…)"] as const, ].map(([key, label, desc], i) => (