रियलटाइम सेशन्स में मेमोरी
एक ऐसी आवाज़ जो कॉल्स के बीच आपको भूल जाती है, कियोस्क जैसी लगती है। ADK-Rust एक रियलटाइम एजेंट को याद रखने देता है — बोलने से पहले उपयोगकर्ता के बारे में जो उसने सीखा है उसे याद करना, और बातचीत के बीच नए तथ्यों को व्यवस्थित करना — यह सब MemoryService को IntegratedRealtimeRunner में वायर करके।
दो सहयोगी तंत्र हैं:
- स्वचालित कॉन्टेक्स्ट इंजेक्शन + टर्न स्टोरेज — इंटीग्रेशन लेयर यह आपके लिए करती है।
- टूल्स के माध्यम से एजेंट-नियंत्रित मेमोरी — ब्रिज किए गए नॉलेज-ग्राफ टूल्स का उपयोग करके एजेंट तय करता है कि क्या रखना है।
1. स्वचालित इंजेक्शन और स्टोरेज
एक MemoryService जोड़ें और रनर राउंड-ट्रिप संभाल लेता है:
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()?;
- कनेक्ट होने पर, उस उपयोगकर्ता के लिए मेमोरी क्वेरी की जाती है और परिणाम सेशन कॉन्टेक्स्ट में मिला दिए जाते हैं, ताकि एजेंट पहले से प्रासंगिक इतिहास जानकर अभिवादन करे।
- हर टर्न पर, पूरे हुए एक्सचेंज वापस लिखे जाते हैं (जब
store_to_memory), ताकि अगला सेशन इसी पर आधारित हो।
कोई भी MemoryService काम करता है — डेवलपमेंट के लिए इन-मेमोरी वाला, या नीचे दिया गया नॉलेज-ग्राफ बैकएंड।
2. नॉलेज-ग्राफ बैकएंड
adk-memory का GraphMemoryService मेमोरी को एक bi-temporal
knowledge graph के रूप में संग्रहीत करता है: entities और relationships, जिनमें से प्रत्येक को event time
(जब वह सत्य था) और ingestion time (जब सिस्टम ने उसे जाना) के साथ ट्रैक किया जाता है। इसका मतलब है
कि एजेंट "उपयोगकर्ता की current plan क्या है?" का उत्तर दे सकता है, बिना इस बात से उलझे
कि वह पहले कुछ और थी — पीछे छोड़ दिए गए तथ्यों को वर्तमान को ओवरराइट करने के बजाय
इतिहास में बने रहने दिया जाता है।
use adk_memory::GraphMemoryService;
use std::sync::Arc;
let kg = Arc::new(GraphMemoryService::new(/* backing store */));
उसे memory_service के रूप में पास करें और ऊपर दिया गया स्वचालित इंजेक्शन अब
ग्राफ का उपयोग करेगा।
3. एजेंट को मेमोरी क्यूरेट करने देना
सबसे शक्तिशाली पैटर्न: एजेंट को ग्राफ में खुद लिखने के लिए टूल्स दें,
ताकि वह हर ट्रांसक्रिप्ट को डंप करने के बजाय जानबूझकर याद रखे। adk-tool
(feature graph-memory-tools) दो टूल्स के साथ आता है जो सीधे एक रियलटाइम
सेशन में ब्रिज होते हैं:
| उपकरण | एजेंट इसके साथ क्या करता है |
|---|---|
RememberTool (remember) | एक महत्वपूर्ण तथ्य संग्रहीत करें ("फोन की तुलना में ईमेल को प्राथमिकता देता है")। |
RelateTool (relate) | दो इकाइयों को जोड़ें ("Order A-10293 → belongs-to → this user")। |
उन्हें .adk_tool(...) के साथ जोड़ें (देखें 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()?;
फिर agent को उन्हें उपयोग करने के लिए निर्देश दें:
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 token-based है: graph conversation से सबसे अधिक प्रासंगिक entities/relationships लौटाता है, जो max_memory_injection द्वारा सीमित होते हैं, इसलिए graph बढ़ने पर भी context छोटा रहता है।
एक depth चुनना
- Stateless demo → कोई
memory_serviceनहीं। हर session fresh शुरू होता है। - Sessions के बीच continuity → in-memory या
GraphMemoryServiceके साथ automatic injection/storage। agent का कोई effort नहीं। - एक learning agent →
GraphMemoryService+remember/relatetools, ताकि agent transcript pile के बजाय user का एक साफ़, queryable model curate करे।
MIA coaching example graph + tools का उपयोग करता है ताकि coach sessions के बीच user के goals और preferences याद रखे; Examples देखें।
अगला: Building web apps →
resumed session में क्या carry किया जाता है
IntegratedRealtimeRunner::connect एक context block बनाता है और provider session बनाए जाने से पहले उसे system
instruction के सामने जोड़ता है:
| अनुभाग | स्रोत | सीमा |
|---|---|---|
Earlier in this conversation: | पिछले सत्र की घटनाएँ | IntegrationConfig::max_history_injection (डिफ़ॉल्ट 20 टर्न) |
Relevant recalled context: | MemoryService::search | IntegrationConfig::max_memory_injection (डिफ़ॉल्ट 10 प्रविष्टियाँ) |
दोनों सीमित हैं क्योंकि निर्देश सत्र निर्माण के समय एक बार भेजा जाता है और मॉडल के संदर्भ के विरुद्ध गिना जाता है। प्रत्येक टर्न को role: text के रूप में रेंडर किया जाता है, 400 वर्णों पर ट्रंकेट किया जाता है, और बिना पाठ वाले टर्न हटा दिए जाते हैं। सीमा को शून्य पर सेट करने से वह अनुभाग निष्क्रिय हो जाता है।
IntegratedRealtimeRunner::instruction() यह लौटाता है कि सत्र किसके साथ बनाया गया था, इसलिए साथ लाया गया संदर्भ अनुमानित करने के बजाय सत्यापित किया जा सकता है:
runner.connect().await?;
let instruction = runner.instruction().await.unwrap_or_default();
assert!(instruction.contains("Relevant recalled context"));
महत्वपूर्ण: यह संदर्भ पहले लोड किया गया था और त्याग दिया गया था — पिछला सत्र
_sessionमें लाया गया और छोड़ दिया गया था, और memory शाखा ने एक टिप्पणी के साथ "injecting memory entries into session context" लॉग किया था, जिसमें कहा गया था कि injection एक भविष्य का enhancement था। एक resumed session दोनों के बिना शुरू हुआ, जबकि logs कुछ और कह रहे थे।