Concepts de mémoire
La partie du magasin sémantique de la mémoire est construite à partir de quelques petits types. Apprenez ces quatre-là , et le reste de la section suit.
MemoryEntry
Un seul enregistrement de mémoire : un contenu, son auteur, et quand il a été créé.
use adk_memory::MemoryEntry;
use adk_core::Content;
use chrono::Utc;
let entry = MemoryEntry {
content: Content::new("user").with_text("I prefer dark mode"),
author: "user".to_string(),
timestamp: Utc::now(),
};
Les entrĂ©es sont lâunitĂ© de stockage et lâunitĂ© de rappel â search renvoie les
entrĂ©es les plus pertinentes pour une requĂȘte.
Le trait MemoryService
Chaque backend implĂ©mente un trait. Deux mĂ©thodes sont requises ; le reste a des implĂ©mentations par dĂ©faut quâun backend peut remplacer :
#[async_trait]
pub trait MemoryService: Send + Sync {
// Required
async fn add_session(&self, app: &str, user: &str, session: &str,
entries: Vec<MemoryEntry>) -> Result<()>;
async fn search(&self, req: SearchRequest) -> Result<SearchResponse>;
// Optional (default: "not implemented")
async fn delete_user(&self, app: &str, user: &str) -> Result<()>; // GDPR
async fn delete_session(&self, app: &str, user: &str, session: &str) -> Result<()>;
async fn add_entry(&self, app: &str, user: &str, entry: MemoryEntry) -> Result<()>;
async fn delete_entries(&self, app: &str, user: &str, query: &str) -> Result<u64>;
// âŠplus a health check
}
add_sessioningĂšre la totalitĂ© des entrĂ©es dâune conversation terminĂ©e. Un Runner lâappelle pour vous lorsque la mĂ©moire est attachĂ©e.searchest le rappel. Les backends interprĂštent la requĂȘte diffĂ©remment â mots-clĂ©s, similaritĂ© dâembedding, ou notation de jetons de graphe â mais le contrat est le mĂȘme.
SearchRequest / SearchResponse
use adk_memory::SearchRequest;
let req = SearchRequest {
app_name: "support".into(),
user_id: "alice".into(),
query: "contact preference".into(),
..Default::default() // top_k, project scoping, etc.
};
let resp = memory.search(req).await?; // resp.entries: Vec<MemoryEntry>
Ătat de session vs mĂ©moire
Ce sont des outils diffĂ©rents â ne les confondez pas :
| Ătat de session | MĂ©moire | |
|---|---|---|
| Durée de vie | Une conversation | à travers les conversations |
| API | adk-session (SessionService, carte dâĂ©tat) | adk-memory (MemoryService) |
| Contient | La transcription en direct + l'Ă©tat temporaire | Des faits durables dignes d'ĂȘtre rappelĂ©s plus tard |
| Lecture | Toujours dans le contexte | Ă la demande, via search_memory |
Un flux typique : la conversation vit dans lâĂ©tat de session ; lorsquâelle se termine (ou Ă chaque tour), les Ă©lĂ©ments saillants sont Ă©crits en mĂ©moire ; la session suivante recherche la mĂ©moire pour reconstituer le contexte. Voir Sessions & State.
Isolation : application, utilisateur et projet
La mémoire est toujours indexée par (app_name, user_id), donc les utilisateurs ne voient jamais les
mĂ©moires des autres. Vous pouvez dĂ©finir un troisiĂšme niveau â projet â au sein dâun utilisateur :
- Entrées globales (
project_id = None) â visibles dans tous les contextes. - EntrĂ©es de projet (
project_id = Some(id)) â visibles uniquement dans ce projet. - Recherche de projet renvoie les entrĂ©es globales + les entrĂ©es de projet correspondantes ; la recherche globale ne renvoie que les entrĂ©es globales.
use adk_memory::{MemoryServiceAdapter, InMemoryMemoryService};
use std::sync::Arc;
let service = Arc::new(InMemoryMemoryService::new());
// store within a project
service.add_session_to_project("app", "user", "sess", "acme-project", entries).await?;
// an adapter scoped to that project
let adapter = MemoryServiceAdapter::new(service, "app", "user")
.with_project_id("acme-project");
Utilisez les projets pour Ă©viter, par exemple, quâun assistant professionnel et un assistant personnel dâun utilisateur partagent la mĂ©moire, tout en partageant les faits rĂ©ellement globaux.
Tous les backends nâimplĂ©mentent pas la portĂ©e par projet
Lâisolation par projet est une à€à„à€·à€źà€€à€Ÿ du backend, pas quelque chose que le trait peut garantir. VĂ©rifiez avant de vous y fier :
if service.supports_project_scoping() {
service.add_entry_to_project("app", "user", "acme-project", entry).await?;
} else {
// Decide explicitly: refuse, or store globally on purpose.
}
| Backend | Délimitation du projet |
|---|---|
InMemoryMemoryService | Oui |
SqliteMemoryService | Oui |
PostgresMemoryService | Oui |
RedisMemoryService | Oui |
MongoMemoryService | Oui |
Neo4jMemoryService | Oui |
GraphMemoryService | Non â les mĂ©thodes du projet renvoient une erreur |
Un backend sans prise en charge des projets Ă©choue lâappel plutĂŽt que dâĂ©crire ou de supprimer silencieusement Ă lâĂ©chelle globale. Ătendre la portĂ©e dâune Ă©criture rendrait des donnĂ©es prĂ©vues pour un projet visibles par tout ce qui se trouve sous la mĂȘme application et le mĂȘme utilisateur, et Ă©tendre une suppression retirerait des entrĂ©es en dehors du projet nommĂ© â aucun de ces cas ne peut ĂȘtre dĂ©tectĂ© par lâappelant Ă partir de la valeur de retour. MemoryServiceAdapter::supports_project_scoping
indique ce que son backend prend en charge.
Effacement RGPD
delete_user(app, user) supprime tous les souvenirs dâun utilisateur (entrĂ©es et
embeddings) sur lâensemble des projets â le primitive du droit Ă lâeffacement. Les backends qui
stockent de maniĂšre persistante lâimplĂ©mentent ; appelez-le depuis votre chemin de suppression de compte.
memory.delete_user("support", "alice").await?;
Suivant : Backends â