Skip to content

Mémoire : un identifiant inventé par un modèle local devient un ajout - #46

Open
LucQuebec wants to merge 2 commits into
lfpoulain:betafrom
LucQuebec:correctif/memoire-identifiant-invente
Open

LucQuebec wants to merge 2 commits into
lfpoulain:betafrom
LucQuebec:correctif/memoire-identifiant-invente

Conversation

@LucQuebec

Copy link
Copy Markdown

Corrige #45.

But

Rendre la mémoire utilisable avec un modèle local, qui confond souvent ajout et correction,
sans affaiblir les vérifications.

Ce qui change

Dans MemoryRepository.apply, avant la vérification existante, chaque changement est normalisé :

  • un changement dont le memoryId n'existe nulle part (identifiant inventé) devient un ajout
    (operation: "add", memoryId: null) ;
  • un forget vers un souvenir inexistant est ignoré (rien à oublier).

Ce qui ne change pas :

  • un memoryId connu, de ce profil ou d'un autre, passe par la vérification stricte actuelle :
    le test « les preuves, propriétaire et opérations… » (Bob qui vise un souvenir d'Alice) reste rejeté ;
  • chaque fait doit toujours citer des evidenceTurnIds de la personne ;
  • la limite de 256 souvenirs et la déduplication s'appliquent comme avant.

Une ligne est ajoutée au CHANGELOG, sous « Non publié ».

Vérification

  • Nouveau test dans tests/memory.test.ts : un update et un add à identifiant inventé
    deviennent des ajouts, un forget inventé est ignoré, un identifiant d'un autre profil reste
    rejeté, une preuve inventée reste rejetée.
  • npm test sous Linux : 743 tests, les 4 échecs restants sont identiques avec le code d'origine
    (742 tests) et viennent de l'environnement d'essai (dossier data/ absent hors installation).
  • npm run check : sans erreur. prettier --check sur les fichiers modifiés : conforme.
  • Sur une installation réelle (Docker sur un NAS, Ollama qwen2.5:7b sur la puce Intel) : la
    conversation suivante a produit « 1 changement enregistré », extraction en 30 s.

@lfpoulain

Copy link
Copy Markdown
Owner

Merci Luc, et merci pour le banc qui reproduit l'appel de memory-extractor.ts : le diagnostic de #45 est juste, et rendre la mémoire utilisable avec un modèle local nous intéresse.

Les garde-fous essentiels tiennent : un identifiant connu, de ce profil ou d'un autre, garde la vérification stricte (Bob ne touche toujours pas aux souvenirs d'Alice), et chaque fait doit citer ses preuves. Trois points avant de fusionner.

À corriger

  1. Branche cible. La PR vise main. Le travail se fait sur beta : peux-tu la recibler et la rebaser ? Seul le CHANGELOG.md est en conflit.

  2. Une correction devient un doublon contradictoire. La déduplication actuelle ne retire que les ajouts strictement identiques (même sujet, même fait, même portée, même expiration ; server/memory-store.ts, juste avant l'INSERT). Scénario : le profil a « Préfère le thé. » (sujet boisson), la personne dit « en fait je préfère le café », le modèle envoie un update avec un identifiant inventé. Avec la PR, on garde « Préfère le thé. » et « Préfère le café. ». Le souvenir est faux, alors qu'avant le lot était rejeté.
    Piste : ne convertir en ajout que si aucun souvenir existant du profil ne porte le même topic. Sinon, garder le rejet. On pourrait aussi remplacer le souvenir de même sujet, mais ce serait accorder au modèle une correction qu'il n'a pas su viser : je préfère le rejet.

  3. Un oubli demandé disparaît sans trace. Un forget vers un identifiant inventé est retiré du lot, et le reste est enregistré : le journal dit « 1 changement enregistré » alors que la personne a demandé d'oublier quelque chose et que rien n'est oublié. Avant, le rejet se voyait au moins dans l'administration. Pour un oubli, il vaut mieux garder le rejet du lot (ou au minimum le signaler dans la raison du lot).

Tests

Le test actuel est bon. Il faudrait y ajouter les deux cas ci-dessus : update inventé alors qu'un souvenir du même sujet existe (rejeté, souvenir d'origine intact), et forget inventé (rejeté).

Une question en plus : as-tu essayé de donner les identifiants existants plus visiblement dans la consigne d'extraction ? Si qwen2.5:7b invente un identifiant même quand la liste est vide, la normalisation reste utile, mais je voudrais savoir si la consigne seule améliore les choses.

LucQuebec added 2 commits November 12, 2026 08:10
Avec un fournisseur personnalisé (Ollama, qwen2.5:7b), l'extraction propose
des faits justes mais étiquetés « update » vers un souvenir inexistant, ou
un « add » qui porte un identifiant. La vérification rejetait tout le lot
(« Souvenir absent ou propriétaire incompatible. ») : aucun souvenir n'était
jamais retenu.

Avant la vérification, un changement qui ne vise aucun souvenir existant
devient un ajout (memoryId null) ; un « forget » sans souvenir est ignoré.
Un identifiant connu, de ce profil ou d'un autre, garde la vérification
stricte, et les preuves restent exigées pour chaque fait.
Suite de la relecture de lfpoulain#46. Une correction (update) vers un identifiant
inconnu ne devient un ajout que si le profil n'a aucun souvenir du même
sujet : sinon le lot reste rejeté, au lieu de garder deux faits
contradictoires (« Préfère le thé. » et « Préfère le café. »). Un oubli
vers un identifiant inconnu reste rejeté, au lieu de disparaître sans
trace. Un ajout qui porte un identifiant reste un ajout.

Tests : correction inventée sur un sujet existant (rejetée, souvenir
d'origine intact), oubli inventé (rejeté, rien n'est oublié ni ajouté),
et un témoin : la même correction sur un autre sujet devient un ajout.
@LucQuebec
LucQuebec force-pushed the correctif/memoire-identifiant-invente branch from 648cd5c to b631544 Compare November 12, 2026 13:29
@LucQuebec
LucQuebec changed the base branch from main to beta November 12, 2026 13:29
@LucQuebec

Copy link
Copy Markdown
Author

Merci pour la relecture, les trois points sont corrigés.

  • Branche : la PR vise maintenant beta, rebasée (conflit du CHANGELOG résolu, notre entrée en tête de « Non publié »).
  • Correction de même sujet : un update vers un identifiant inconnu ne devient un ajout que si le profil n'a aucun souvenir du même topic (comparé sans tenir compte des espaces ni de la casse). Sinon, le lot reste rejeté, comme vous le préférez.
  • Oubli inventé : un forget vers un identifiant inconnu garde le rejet du lot.
  • Tests : vos deux cas (correction inventée sur un sujet existant : rejetée, souvenir d'origine intact ; oubli inventé : rejeté, rien n'est oublié ni ajouté), plus un témoin : la même correction sur un autre sujet devient un ajout. npm test : 806 sur 806 sur beta.

Votre question sur la consigne : je viens de l'essayer, sur le même banc (qwen2.5:7b, Ollama, même appel que memory-extractor.ts), 5 essais par cas. A = consigne actuelle ; B = la même, suivie d'une ligne qui liste les identifiants existants (« les seuls valables pour update et forget : … », ou « aucun : utilise seulement add, avec memoryId: null »).

Cas A B
Aucun souvenir 0/5 lots valables (5 fois update, dont 2 avec un identifiant inventé et 3 avec memoryId: null) 5/5 (add, memoryId: null)
Correction (« thé » existe, « en fait je préfère le café ») 2/5 update justes (2 fois un forget seul, 1 fois forget puis add) 5/5 update de l'identifiant existant

La consigne seule améliore donc nettement les choses, sur ce petit échantillon. Je propose de l'ajouter : la liste des identifiants construite à chaque appel dans memory-extractor.ts. La normalisation resterait un filet de sécurité. Préférez-vous que je l'ajoute à cette PR, ou dans une PR séparée ?

Luc, Jokobee™

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants