Files
workspace/docs/memory-evolution-strategy.md
2026-04-15 11:26:46 +02:00

121 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Evoluzione della gestione memoria/personalizzazione di adiuvAI
> **Versione:** 1.0 — 2026-04-14
> **Scope:** analisi architetturale e raccomandazioni per l'evoluzione del sottosistema di memoria di adiuvAI (Electron + FastAPI), con focus sul posizionamento "segretaria personale" (cfr. `docs/marketing-strategy.md`).
> **Premessa:** lo stato attuale di `api/app/core/memory_middleware.py` implementa già un modello 4-tier ispirato a MemGPT (core / associative / episodic / proactive) con crittografia Fernet per-utente. Le raccomandazioni partono da qui, non da zero.
---
## 1. Stato attuale (sintesi)
| Tier | Storage | Uso | Gap principale |
|---|---|---|---|
| `core` | Postgres (k/v) crittografato | Preferenze stabili (lingua, ruolo, tono, ecc.) — già usato dall'onboarding | Crescita non controllata, nessuna gerarchia, nessun limite per tier |
| `associative` | `MemoryAssociative` + pgvector (campo `embedding` presente ma **inutilizzato**) | Recupero top-k | Fallback keyword: sta funzionando come "lista recenti", non come semantica |
| `episodic` | Summaries conversazione | Iniettato nel contesto | Summary naïf (`message[:200]`), nessuna compressione LLM, nessun decay |
| `proactive` | Pattern con `confidence` | Suggerimenti | Nessun ciclo che alimenta la tabella — resta vuota in produzione |
**Zero-trust:** la crittografia per-utente è un vincolo architetturale forte. Qualunque tecnica che richieda di "leggere" la memoria lato server deve passare dal Fernet dell'utente → esclude servizi gestiti esterni (Mem0 SaaS, Pinecone con payload in chiaro) per il contenuto, ma lascia liberi i **vettori** (già trattati come deterministici da SHA-256 in `vectors.py`).
---
## 2. Allineamento con il posizionamento "segretaria"
Una segretaria umana eccelle in tre dimensioni mnestiche che gli agenti generici trascurano:
1. **Memoria di ruolo** — sa *chi è* il capo, *cosa gli interessa*, *quali persone* sono VIP, *quali progetti* sono caldi.
2. **Memoria di routine** — conosce gli orari, gli stili comunicativi, le abitudini ("di lunedì il capo vuole il brief entro le 8:00").
3. **Memoria relazionale** — conosce *le persone intorno al capo*: clienti, colleghi, fornitori, con contesto (ultimo contatto, tono appropriato, argomenti in sospeso).
Il sistema attuale copre bene (1) tramite `core`, parzialmente (2) via onboarding, **non copre** (3). Questo è il gap più grande rispetto al marketing promise.
---
## 3. Raccomandazione architetturale: ibrido mirato
Nessuno degli approcci citati va adottato in purezza. La proposta è una **combinazione selettiva** guidata dal dominio:
### 3.1 Base (tutti i tier): MemGPT consolidato + Mem0-style extraction
Mantenere la struttura 4-tier già presente, ma **sostituire le scritture naïf con una pipeline Mem0**:
- **Fase Extraction** (post-conversazione, async):
- Trigger: dopo `store_episode`, una task in background fa girare `gpt-4o-mini` (economico) su `(last_turn, recency_window, core_memory)`.
- Output strutturato: `{candidates: [{type: "fact|preference|relation|routine", content, target_tier}]}`.
- **Fase Update** (decisione ADD/UPDATE/DELETE/NOOP):
- Per ogni candidato: similarity search nel tier target → l'LLM decide l'azione via tool call.
- **Perché Mem0 e non MemGPT puro**: su un'app "segretaria" le informazioni importanti sono *fatti stabili* (il CFO si chiama Giulia, il cliente X paga sempre in ritardo), non conversazioni da rimettere in RAM. Il ciclo Extract/Update è più adatto di una coda FIFO di messaggi.
### 3.2 Estensione dominio-specifica: Knowledge Graph leggero (Mem0g)
Aggiungere un **quinto tier** orientato al dominio segretaria:
- **`relational` tier**: grafo *Entità → Relazione → Entità* memorizzato in Postgres (non serve Neo4j).
- Nodi: Person, Company, Project, Topic (già presenti come entità in `agents` dell'Electron — riutilizzabili).
- Archi: `works_at`, `reports_to`, `stakeholder_of`, `last_contacted_on`, `owes_followup`.
- **Perché un grafo e non solo vettori**: la segretaria deve rispondere a domande tipo *"chi è Marco?"* → embedding testuale confonde "Marco Rossi (cliente)" con "Marco Bianchi (collega)". Il grafo disambigua, i vettori no.
- **Implementazione minima**: nuova tabella `memory_relations(user_id, subject_id, predicate, object_id, confidence, source_episode_id, encrypted_notes)`. Popolata dalla stessa pipeline Extraction.
### 3.3 Dove **non** andare
- **A-Mem / memory evolution retroattiva**: affascinante ma costoso (ri-analizza il passato a ogni nuova nota). Per una segretaria è *anti-pattern* — introduce non-determinismo dove l'utente si aspetta stabilità ("ma ieri mi dicevi un'altra cosa"). Skippare.
- **AutoGPT loop riflessivo**: il dominio è reattivo (brief, follow-up), non goal-seeking autonomo. Over-engineering.
- **LangChain `ConversationBufferMemory`** e parenti: già superati dalla struttura attuale. No regressioni.
---
## 4. Differenziazione per tier di prodotto
La memoria è un asset di differenziazione commerciale **naturale**: più memoria = segretaria più "al corrente". Proposta:
| Capability | Free | Pro | Power | Team |
|---|:-:|:-:|:-:|:-:|
| `core` blocks (max k/v) | 20 | 100 | illimitato | illimitato |
| `episodic` retention | 7 gg | 90 gg | illimitato | illimitato |
| `associative` con pgvector reale (OpenAI embeddings) | ❌ (keyword only) | ✅ | ✅ | ✅ |
| `relational` graph (Mem0g) | ❌ | ✅ base (Person/Project) | ✅ completo + custom predicates | ✅ + condivisione team |
| Mem0 Extraction pipeline LLM | batch giornaliero | realtime post-turn | realtime + proactive mining | realtime + team-wide |
| `proactive` pattern mining | ❌ | ❌ | ✅ (pattern "ogni lunedì…") | ✅ |
| Memory export/import cifrato | ✅ | ✅ | ✅ | ✅ |
| Forget/consent UI (GDPR Art. 17) | ✅ | ✅ | ✅ | ✅ |
**Rationale commerciale:**
- Il Free tier ha una segretaria che "ricorda i fatti base" — sufficiente per la wow-moment del daily brief, non sufficiente per sentirla *tua*.
- Il salto Free → Pro si giustifica con "la segretaria inizia a conoscere davvero le persone che tratti" (embeddings reali + grafo base).
- Il salto Pro → Power si vende come "la segretaria nota i tuoi pattern e te li anticipa" (proactive tier attivo).
- Il Team tier abilita memoria condivisa su entità aziendali comuni (clienti, progetti), mantenendo memoria personale cifrata per-utente.
**Vincolo zero-trust**: il tier-gating si applica a *quanto* si memorizza e *quali pipeline* girano, **mai** a chi può leggere. Il backend continua a non decifrare nulla che non sia strettamente necessario al turn corrente.
---
## 5. Piano di implementazione suggerito (ordine)
1. **Quick win (12 gg)**: attivare davvero `pgvector` sull'`associative` tier (oggi c'è il campo `embedding` ma si usa il fallback keyword). Gate dietro tier ≥ Pro.
2. **Extraction pipeline Mem0-style (1 sett)**: task async post-`store_episode``gpt-4o-mini` → update strutturato dei tier. Log trace per debug. Gate per tier (batch Free vs realtime Pro+).
3. **Relational tier (Mem0g leggero) (12 sett)**: schema nuova tabella, alimentazione dalla pipeline, uso nel prompt agent come contesto "persone e relazioni rilevanti".
4. **Settings > Memory UI**: pagina dedicata per vedere/modificare `core` + `relational` (la segretaria deve essere *correggibile* — è una feature, non un bug, che l'utente possa dire "no, Giulia è la CFO non la CEO"). GDPR-compliant by design.
5. **Proactive mining (opzionale, Power)**: job schedulato che cerca pattern temporali nelle `episodic` e promuove a `proactive` con confidence score.
---
## 6. Rischi e mitigazioni
| Rischio | Mitigazione |
|---|---|
| Costo LLM dell'Extraction pipeline esplode sul Free | Batch notturno per Free (1 run/24h con rate cap), realtime solo Pro+ |
| Memoria "sporca" (fatti estratti errati) erode fiducia nella segretaria | UI di review/edit obbligatoria (punto 4); mai scrivere `core` senza conferma implicita (es. utente non corregge entro N turni) |
| Zero-trust vs embeddings: OpenAI vede il testo dell'embedding | Già accettato dall'architettura attuale per altri flussi (cfr. note su vector search in CLAUDE.md). Documentare esplicitamente nella privacy policy. Opzione BYOK-embedding per tier Power come mitigante marketing. |
| Grafo relazionale cresce indefinitamente | TTL per archi con `last_contacted_on` > 18 mesi + decay sulla `confidence` |
| Drift tra memoria locale (Electron SQLite) e backend | Già gestito come "backend = source of truth" per `core`. Estendere la stessa regola al nuovo `relational`. |
---
## 7. TL;DR
- **Base architetturale:** manteniamo MemGPT 4-tier (già in casa), sostituiamo le scritture naïf con pipeline **Mem0 Extract/Update**.
- **Differenziazione dominio:** aggiungiamo un tier **`relational` (Mem0g leggero)** per modellare persone/progetti — è il vero gap rispetto alla promessa "segretaria".
- **Monetizzazione:** la memoria diventa scala di differenziazione tier (retention, embeddings reali, proactive mining, team sharing) senza violare zero-trust.
- **Da evitare:** A-Mem (troppo non-deterministico), AutoGPT loop (fuori scope), wrapper LangChain legacy (regressione).
- **Primo passo concreto:** accendere pgvector reale sull'`associative` tier — è già pre-cablato e sbloccato da un singolo gate.