Isole la mémoire par discussion : RAG inter-sessions désactivé par défaut

La mémoire long-terme rappelait des échanges d'AUTRES sessions dans la
discussion en cours : demander « un jeu d'échecs » ressortait une « appli
sport » demandée ailleurs, et déroutait les petits modèles.

- rag_enabled désactivé par défaut : chaque discussion ne se souvient que
  d'elle-même (résumé + messages récents, déjà en place).
- Migration v7 : désactive le RAG une fois sur les installs existantes
  (la valeur persiste en base /data) ; réactivable dans Réglages.
- Rappel plus strict quand le RAG est activé : seuil de similarité 0.45 -> 0.6.
- Réglages : libellé clarifié (« Mémoire entre sessions »).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVay7z3y7q2gEe54ByAE6N
This commit is contained in:
Claude committed 2026-07-20 11:47:58 +00:00
1 parent c36db0b862
commit de4ec1d919
4 files changed
+25 -9

No files matched your search

+16 -3
View File
@@ -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})
+4 -1
View File
@@ -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}
+3 -3
View File
@@ -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"),
+2 -2
View File
@@ -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) => (