Speicher
Semantischer Langzeitspeicher fÃŒr AI-Agenten mit adk-memory.
Ãberblick
Das Speichersystem bietet persistenten, durchsuchbaren Speicher fÌr Agenten-Konversationen. Im Gegensatz zum Session-Status (der temporÀr ist) bleiben Erinnerungen Ìber Sessions hinweg bestehen und ermöglichen es Agenten, relevante Kontexte aus vergangenen Interaktionen abzurufen.
Installation
[dependencies]
adk-memory = "0.2.0"
Kernkonzepte
MemoryEntry
Ein einzelner Speicherdatensatz mit content, author und timestamp:
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(),
};
MemoryService Trait
Das Kern-Trait fÃŒr Speicher-Backends:
#[async_trait]
pub trait MemoryService: Send + Sync {
/// Store session memories for a user
async fn add_session(
&self,
app_name: &str,
user_id: &str,
session_id: &str,
entries: Vec<MemoryEntry>,
) -> Result<()>;
/// Search memories by query
async fn search(&self, req: SearchRequest) -> Result<SearchResponse>;
}
SearchRequest
Query-Parameter fÃŒr die Speichersuche:
use adk_memory::SearchRequest;
let request = SearchRequest {
query: "user preferences".to_string(),
user_id: "user-123".to_string(),
app_name: "my_app".to_string(),
};
InMemoryMemoryService
Einfache In-Memory-Implementierung fÃŒr Entwicklung und Tests:
use adk_memory::{InMemoryMemoryService, MemoryService, MemoryEntry, SearchRequest};
use adk_core::Content;
use chrono::Utc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let memory = InMemoryMemoryService::new();
// Store memories from a session
let entries = vec![
MemoryEntry {
content: Content::new("user").with_text("I like Rust programming"),
author: "user".to_string(),
timestamp: Utc::now(),
},
MemoryEntry {
content: Content::new("assistant").with_text("Rust is great for systems programming"),
author: "assistant".to_string(),
timestamp: Utc::now(),
},
];
memory.add_session("my_app", "user-123", "session-1", entries).await?;
// Search memories
let request = SearchRequest {
query: "Rust".to_string(),
user_id: "user-123".to_string(),
app_name: "my_app".to_string(),
};
let response = memory.search(request).await?;
println!("Found {} memories", response.memories.len());
Ok(())
}
Speicherisolation
Erinnerungen werden isoliert durch:
- app_name: Verschiedene Anwendungen haben separate Speicherbereiche
- user_id: Die Erinnerungen jedes Benutzers sind privat
// User A's memories
memory.add_session("app", "user-a", "sess-1", entries_a).await?;
// User B's memories (separate)
memory.add_session("app", "user-b", "sess-1", entries_b).await?;
// Search only returns user-a's memories
let request = SearchRequest {
query: "topic".to_string(),
user_id: "user-a".to_string(),
app_name: "app".to_string(),
};
Suchverhalten
Der InMemoryMemoryService verwendet wortbasierte Ãbereinstimmungen:
- Query wird in Wörter (Kleinbuchstaben) tokenisiert
- Der content jeder Erinnerung wird tokenisiert
- Erinnerungen mit Ìbereinstimmenden Wörtern werden zurÌckgegeben
// Query: "rust programming"
// Entspricht Erinnerungen, die "rust" ODER "programming" enthalten
Benutzerdefiniertes Memory Backend
Implementieren Sie MemoryService fÃŒr benutzerdefinierten Speicher (z.B. Vektordatenbank):
use adk_memory::{MemoryService, MemoryEntry, SearchRequest, SearchResponse};
use adk_core::Result;
use async_trait::async_trait;
pub struct VectorMemoryService {
// Ihr Vektor-DB-Client
}
#[async_trait]
impl MemoryService for VectorMemoryService {
async fn add_session(
&self,
app_name: &str,
user_id: &str,
session_id: &str,
entries: Vec<MemoryEntry>,
) -> Result<()> {
// 1. Embeddings fÃŒr jeden Eintrag generieren
// 2. In Vektordatenbank mit Metadaten speichern
Ok(())
}
async fn search(&self, req: SearchRequest) -> Result<SearchResponse> {
// 1. Embedding fÃŒr Abfrage generieren
// 2. Ãhnlichkeitssuche durchfÃŒhren
// 3. Top-k-Ergebnisse zurÃŒckgeben
Ok(SearchResponse { memories: vec![] })
}
}
Integration mit Agents
Memory wird mit LlmAgentBuilder integriert:
use adk_agent::LlmAgentBuilder;
use adk_memory::InMemoryMemoryService;
use std::sync::Arc;
let memory = Arc::new(InMemoryMemoryService::new());
let agent = LlmAgentBuilder::new("assistant")
.model(model)
.instruction("You are a helpful assistant with memory.")
.memory(memory)
.build()?;
Wenn Memory konfiguriert ist:
- Vor jeder Runde werden relevante Memories gesucht
- Passende Memories werden in den Kontext injiziert
- Nach jeder Session wird die Konversation als Memories gespeichert
Architektur
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Agent Request â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Memory Search â
â â
â SearchRequest { query, user_id, app_name } â
â â â
â ⌠â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â MemoryService â â
â â âââââââââââââââ âââââââââââââââ ââââââââââââââ â â
â â â InMemory â â Vector DB â â Custom â â â
â â â (dev/test) â â (Qdrant) â â Backend â â â
â â âââââââââââââââ âââââââââââââââ ââââââââââââââ â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â
â ⌠â
â SearchResponse { memories: Vec<MemoryEntry> } â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Context Injection â
â â
â Relevant memories added to agent context â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Agent Execution â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Memory Storage â
â â
â Session conversation stored for future recall â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Best Practices
| Vorgehensweise | Beschreibung |
|---|---|
| Nutzen Sie eine Vektordatenbank in der Produktion | In-Memory ist nur fÃŒr Entwicklung/Tests gedacht |
| Umfang nach Benutzer festlegen | FÃŒgen Sie immer die user_id fÃŒr den Datenschutz hinzu |
| Ergebnisse begrenzen | Begrenzen Sie die zurÃŒckgegebenen Erinnerungen, um einen KontextÃŒberlauf zu vermeiden |
| Alte Erinnerungen bereinigen | Implementieren Sie TTL oder Archivierung fÃŒr veraltete Daten |
| Strategisch einbetten | Speichern Sie Zusammenfassungen, nicht rohe Konversationen |
Vergleich mit Sessions
| Feature | Session-Status | Speicher |
|---|---|---|
| Persistenz | Lebensdauer der Session | Permanent |
| Umfang | Einzelne Session | Session-ÃŒbergreifend |
| Suche | SchlÃŒssel-Wert-Suche | Semantische Suche |
| Anwendungsfall | Aktueller Kontext | LangzeitgedÀchtnis |
ZurÃŒck: â Guardrails | Weiter: Studio â