Gedächtnis in Realtime-Sitzungen
Eine Stimme, die sich zwischen Anrufen nicht an dich erinnert, wirkt wie ein Kiosk. ADK-Rust lässt einen
Realtime-Agenten sich erinnern — das, was er vor dem Sprechen über einen Benutzer gelernt hat, abrufen und neue Fakten mitten im Gespräch kuratieren — indem eine MemoryService in die
IntegratedRealtimeRunner eingebunden wird.
Es gibt zwei zusammenarbeitende Mechanismen:
- Automatische Kontextinjektion + Turn-Speicherung — die Integrationsschicht erledigt das für dich.
- Vom Agenten kuratierter Speicher über Tools — der Agent entscheidet, was es wert ist, behalten zu werden, mithilfe angebundener Knowledge-Graph-Tools.
1. Automatische Injektion und Speicherung
Hänge eine MemoryService an, und der Runner übernimmt den Hin- und Rückweg:
let runner = IntegratedRealtimeRunner::builder()
.model(model)
.config(config)
.identity("support", &user_id, &session_id)
.session_service(sessions)
.memory_service(memory.clone())
.integration_config(IntegrationConfig {
inject_memory_context: true, // query memory at connect
max_memory_injection: 10, // cap injected items
store_to_memory: true, // write each completed turn back
persist_transcripts: true,
})
.build()?;
- Beim Verbinden wird der Speicher für den Benutzer abgefragt, und die Ergebnisse werden in den Sitzungskontext eingearbeitet, sodass der Agent ihn begrüßt und die relevante Historie bereits kennt.
- Pro Turn werden abgeschlossene Austausche zurückgeschrieben (wenn
store_to_memory), sodass die nächste Sitzung auf dieser aufbaut.
Jedes MemoryService funktioniert — das In-Memory-Backend für die Entwicklung oder das
Knowledge-Graph-Backend unten.
2. Das Knowledge-Graph-Backend
adk-memorys GraphMemoryService speichert Speicher als bi-temporalen
Knowledge Graph: Entitäten und Beziehungen, jeweils nach Ereigniszeit
(wann es wahr war) und Ingestionszeit (wann das System es gelernt hat) erfasst. Das bedeutet,
dass der Agent die Frage „was ist der aktuelle Plan des Benutzers?“ beantworten kann, ohne
an der Tatsache zu scheitern, dass es früher etwas anderes war — überholte Fakten bleiben in der Historie
statt die Gegenwart zu überschreiben.
use adk_memory::GraphMemoryService;
use std::sync::Arc;
let kg = Arc::new(GraphMemoryService::new(/* backing store */));
Übergib das als die memory_service, und die automatische Injektion oben greift nun auf
den Graphen zu.
3. Den Agenten den Speicher kuratieren lassen
Das mächtigste Muster: Gib dem Agenten Tools, um direkt in den Graphen zu schreiben,
damit er sich bewusst erinnert, statt einfach jedes Transkript abzulegen. adk-tool
(Funktion graph-memory-tools) liefert zwei davon, die direkt in eine Realtime
Sitzung eingebunden werden:
| Werkzeug | Was der Agent damit macht |
|---|---|
RememberTool (remember) | Eine wichtige Tatsache speichern („bevorzugt E-Mail statt Telefon“). |
RelateTool (relate) | Zwei Entitäten verbinden („Bestellung A-10293 → gehört-zu → dieser Benutzer“). |
Verbinden Sie sie mit .adk_tool(...) (siehe Tools):
use adk_tool::{RememberTool, RelateTool};
let runner = IntegratedRealtimeRunner::builder()
.model(model).config(config)
.identity("support", &user_id, &session_id)
.memory_service(kg.clone())
.adk_tool(Arc::new(RememberTool::new(kg.clone())))
.adk_tool(Arc::new(RelateTool::new(kg)))
.build()?;
Weisen Sie dann den Agenten an, sie zu verwenden:
When you learn a durable fact about the customer (a preference, an account
detail, a decision), call `remember` to store it. Use `relate` to link orders
or items to the customer. Recall naturally — don't announce that you're saving.
Recall ist tokenbasiert: Der Graph gibt die Entitäten/Beziehungen zurück, die für die Unterhaltung am relevantesten sind, begrenzt durch max_memory_injection, sodass der Kontext klein bleibt, auch wenn der Graph wächst.
Eine Tiefe wählen
- Stateless-Demo → kein
memory_service. Jede Sitzung beginnt neu. - Kontinuität über Sitzungen hinweg → in-memory oder
GraphMemoryServicemit automatischer Einfügung/Speicherung. Kein Aufwand für den Agenten. - Ein Lernagent →
GraphMemoryService+remember/relate-Tools, damit der Agent ein sauberes, abfragbares Modell des Benutzers kuratiert statt eines Protokollhaufens.
Das MIA-Coaching-Beispiel verwendet den Graphen + Tools, damit sich der Coach an die Ziele und Präferenzen des Benutzers zwischen den Sitzungen erinnert; siehe Examples.
Weiter: Web-Apps erstellen →
Was in eine wiederaufgenommene Sitzung übernommen wird
IntegratedRealtimeRunner::connect baut einen Kontextblock und stellt ihn dem System
Instruction voran, bevor die Provider-Sitzung erstellt wird:
| Abschnitt | Quelle | Grenze |
|---|---|---|
Earlier in this conversation: | Die Ereignisse der vorherigen Sitzung | IntegrationConfig::max_history_injection (standardmäßig 20 Züge) |
Relevant recalled context: | MemoryService::search | IntegrationConfig::max_memory_injection (standardmäßig 10 Einträge) |
Beide sind begrenzt, weil die Anweisung einmal bei der Sitzungserstellung gesendet wird und gegen den Kontext des Modells zählt. Jede Runde wird als role: text dargestellt, auf 400 Zeichen gekürzt, und Runden ohne Text werden verworfen. Wenn eine Begrenzung auf null gesetzt wird, wird dieser Abschnitt deaktiviert.
IntegratedRealtimeRunner::instruction() gibt zurück, womit die Sitzung erstellt wurde, sodass der übernommene Kontext bestätigt statt nur abgeleitet werden kann:
runner.connect().await?;
let instruction = runner.instruction().await.unwrap_or_default();
assert!(instruction.contains("Relevant recalled context"));
Wichtig: Dieser Kontext wurde zuvor geladen und verworfen — die vorherige Sitzung wurde in
_sessionabgerufen und verworfen, und der Memory-Zweig protokollierte „injecting memory entries into session context“ neben einem Kommentar, der besagte, dass die Injektion eine zukünftige Verbesserung sei. Eine wiederaufgenommene Sitzung begann ohne beides, während die Protokolle etwas anderes behaupteten.