स्मृति
AI एजेंटों के लिए दीर्घकालिक सिमेंटिक स्मृति adk-memory का उपयोग करके।
अवलोकन
स्मृति प्रणाली एजेंट वार्तालापों के लिए स्थायी, खोज योग्य भंडारण प्रदान करती है। सत्र स्थिति (जो क्षणभंगुर होती है) के विपरीत, स्मृति सत्रों में बनी रहती है और एजेंटों को पिछली बातचीत से प्रासंगिक संदर्भ याद रखने में सक्षम बनाती है।
स्थापना
[dependencies]
adk-memory = "2.0.0"
मुख्य अवधारणाएँ
MemoryEntry
सामग्री, लेखक और टाइमस्टैम्प के साथ एक एकल स्मृति रिकॉर्ड:
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
स्मृति बैकएंड के लिए मुख्य Trait:
#[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
स्मृति खोज के लिए क्वेरी पैरामीटर:
use adk_memory::SearchRequest;
let request = SearchRequest {
query: "user preferences".to_string(),
user_id: "user-123".to_string(),
app_name: "my_app".to_string(),
limit: None,
min_score: None,
project_id: None, // None = global only, Some("id") = global + project
};
InMemoryMemoryService
विकास और परीक्षण के लिए सरल इन-मेमोरी कार्यान्वयन:
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(),
limit: None,
min_score: None,
project_id: None,
};
let response = memory.search(request).await?;
println!("Found {} memories", response.memories.len());
Ok(())
}
स्मृति अलगाव
स्मृतियाँ इनके द्वारा अलग की जाती हैं:
- app_name: विभिन्न अनुप्रयोगों के लिए अलग-अलग स्मृति स्थान होते हैं
- user_id: प्रत्येक उपयोगकर्ता की स्मृतियाँ निजी होती हैं
- project_id (वैकल्पिक): प्रविष्टियों को एक उपयोगकर्ता के भीतर एक प्रोजेक्ट तक सीमित किया जा सकता है
// 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(),
limit: None,
min_score: None,
project_id: None, // None = global entries only
};
प्रोजेक्ट-स्कोप वाली स्मृति
स्मृतियों को एक उपयोगकर्ता के भीतर एक प्रोजेक्ट तक सीमित किया जा सकता है। अलगाव कुंजी (app_name, user_id, project_id?) बन जाती है:
- Global entries (
project_id = None): सभी प्रोजेक्ट संदर्भों में और केवल वैश्विक खोजों में दृश्यमान। - Project entries (
project_id = Some(id)): केवल तभी दृश्यमान जब उस विशिष्ट प्रोजेक्ट के भीतर खोज की जा रही हो। - Project search (
project_id = Some(id)): वैश्विक प्रविष्टियाँ + उस प्रोजेक्ट के लिए प्रविष्टियाँ लौटाता है। - Global search (
project_id = None): केवल वैश्विक प्रविष्टियाँ लौटाता है।
प्रोजेक्ट-स्कोप वाली प्रविष्टियों को संग्रहीत करना
use adk_memory::{InMemoryMemoryService, MemoryService, MemoryEntry};
use adk_core::Content;
use chrono::Utc;
let service = InMemoryMemoryService::new();
let entry = MemoryEntry {
content: Content::new("user").with_text("Project uses microservices"),
author: "user".to_string(),
timestamp: Utc::now(),
};
// Global entry (no project scope)
service.add_session("app", "user-1", "sess-1", vec![entry.clone()]).await?;
// Project-scoped entry
service.add_session_to_project("app", "user-1", "sess-2", "my-project", vec![entry.clone()]).await?;
// Single entry to a project
service.add_entry_to_project("app", "user-1", "my-project", entry).await?;
प्रोजेक्ट स्कोप के साथ खोजना
use adk_memory::SearchRequest;
// Global-only search — returns only global entries
let global = service.search(SearchRequest {
query: "microservices".into(),
user_id: "user-1".into(),
app_name: "app".into(),
limit: None,
min_score: None,
project_id: None,
}).await?;
// Project search — returns global + project entries
let project = service.search(SearchRequest {
query: "microservices".into(),
user_id: "user-1".into(),
app_name: "app".into(),
limit: None,
min_score: None,
project_id: Some("my-project".into()),
}).await?;
प्रोजेक्ट-स्कोप वाली प्रविष्टियों को हटाना
// Delete entries matching a query within a project only
service.delete_entries_in_project("app", "user-1", "my-project", "microservices").await?;
// Delete ALL entries for a project
service.delete_project("app", "user-1", "my-project").await?;
// Global delete — only removes global entries, project entries are unaffected
service.delete_entries("app", "user-1", "microservices").await?;
// GDPR delete_user — removes everything (global + all projects)
service.delete_user("app", "user-1").await?;
MemoryServiceAdapter with project scope
MemoryServiceAdapter, MemoryService को adk_core::Memory से जोड़ता है। सभी ऑपरेशनों को स्कोप करने के लिए with_project_id() का उपयोग करें:
use adk_memory::{InMemoryMemoryService, MemoryServiceAdapter};
use adk_core::Memory;
use std::sync::Arc;
let service = Arc::new(InMemoryMemoryService::new());
// Adapter without project — operates on global entries
let global_adapter = MemoryServiceAdapter::new(service.clone(), "app", "user-1");
// Adapter with project — all search/add/delete operations scoped to the project
let project_adapter = MemoryServiceAdapter::new(service.clone(), "app", "user-1")
.with_project_id("my-project");
// Core Memory trait also supports ad-hoc project access
global_adapter.search_in_project("query", "other-project").await?;
global_adapter.add_to_project(entry, "other-project").await?;
प्रोजेक्ट ID सत्यापन
सभी लेखन ऑपरेशनों पर प्रोजेक्ट पहचानकर्ताओं को मान्य किया जाता है:
- खाली नहीं होना चाहिए
- 256 वर्णों से अधिक नहीं होना चाहिए
use adk_memory::validate_project_id;
validate_project_id("my-project")?; // Ok
validate_project_id("")?; // Err: must not be empty
validate_project_id(&"x".repeat(257))?; // Err: exceeds 256 chars
खोज सिमेंटिक्स मैट्रिक्स
SearchRequest.project_id | वैश्विक प्रविष्टियाँ लौटाता है | प्रोजेक्ट प्रविष्टियाँ लौटाता है |
|---|---|---|
None | ✅ क्वेरी से मेल खाती है | ❌ कोई नहीं |
Some("A") | ✅ क्वेरी से मेल खाती है | ✅ केवल प्रोजेक्ट "A" की क्वेरी से मेल खाने वाली प्रविष्टियाँ |
विलोपन सिमेंटिक्स मैट्रिक्स
| ऑपरेशन | दायरा |
|---|---|
delete_entries (कोई प्रोजेक्ट नहीं) | केवल क्वेरी से मेल खाने वाली वैश्विक प्रविष्टियाँ |
delete_entries_in_project("A") | केवल क्वेरी से मेल खाने वाली प्रोजेक्ट "A" प्रविष्टियाँ |
delete_project("A") | प्रोजेक्ट "A" के लिए सभी प्रविष्टियाँ |
delete_user | सभी प्रविष्टियाँ (वैश्विक + सभी प्रोजेक्ट) |
खोज व्यवहार
InMemoryMemoryService शब्द-आधारित मिलान का उपयोग करता है:
- क्वेरी को शब्दों (छोटे अक्षरों) में टोकनाइज़ किया जाता है
- प्रत्येक मेमोरी की सामग्री को टोकनाइज़ किया जाता है
- किसी भी मिलान वाले शब्द वाली मेमोरीज वापस कर दी जाती हैं
// Query: "rust programming"
// Matches memories containing "rust" OR "programming"
कस्टम मेमोरी बैकएंड
कस्टम स्टोरेज (जैसे, vector database) के लिए MemoryService लागू करें:
use adk_memory::{MemoryService, MemoryEntry, SearchRequest, SearchResponse};
use adk_core::Result;
use async_trait::async_trait;
pub struct VectorMemoryService {
// Your vector 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. Generate embeddings for each entry
// 2. Store in vector database with metadata
Ok(())
}
async fn search(&self, req: SearchRequest) -> Result<SearchResponse> {
// 1. Generate embedding for query
// 2. Perform similarity search
// 3. Return top-k results
Ok(SearchResponse { memories: vec![] })
}
}
एजेंट्स के साथ एकीकरण
मेमोरी LlmAgentBuilder के साथ एकीकृत होती है:
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()?;
जब मेमोरी कॉन्फ़िगर की जाती है:
- प्रत्येक बारी से पहले, प्रासंगिक मेमोरीज खोजी जाती हैं
- मिलान वाली मेमोरीज को संदर्भ में इंजेक्ट किया जाता है
- प्रत्येक सेशन के बाद, बातचीत को मेमोरीज के रूप में संग्रहीत किया जाता है
आर्किटेक्चर
┌─────────────────────────────────────────────────────────────┐
│ Agent Request │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Memory Search │
│ │
│ SearchRequest { query, user_id, app_name, project_id } │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MemoryService │ │
│ │ ┌─────────┐ ┌──────────┐ ┌────────┐ ┌──────────┐ │ │
│ │ │InMemory │ │ SQLite │ │Postgres│ │ Redis │ │ │
│ │ │(dev) │ │ │ │pgvector│ │ │ │ │
│ │ └─────────┘ └──────────┘ └────────┘ └──────────┘ │ │
│ │ ┌─────────┐ ┌──────────┐ │ │
│ │ │MongoDB │ │ Neo4j │ │ │
│ │ └─────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ SearchResponse { memories: Vec<MemoryEntry> } │
│ (filtered by project scope) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Context Injection │
│ │
│ Relevant memories added to agent context │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Agent Execution │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Memory Storage │
│ │
│ Session conversation stored for future recall │
│ (global or project-scoped) │
└─────────────────────────────────────────────────────────────┘
सर्वोत्तम अभ्यास
| अभ्यास | विवरण |
|---|---|
| उत्पादन में वेक्टर DB का उपयोग करें | InMemory केवल देव/परीक्षण के लिए है |
| उपयोगकर्ता द्वारा स्कोप करें | गोपनीयता के लिए हमेशा user_id शामिल करें |
| परिणामों को सीमित करें | संदर्भ अतिप्रवाह से बचने के लिए लौटाई गई यादों को सीमित करें |
| पुरानी यादों को साफ करें | बासी डेटा के लिए TTL या संग्रह लागू करें |
| रणनीतिक रूप से एम्बेड करें | सारांश संग्रहीत करें, कच्चे वार्तालाप नहीं |
Sessions के साथ तुलना
| सुविधा | सत्र स्थिति | मेमोरी |
|---|---|---|
| दृढ़ता | सत्र का जीवनकाल | स्थायी |
| दायरा | एकल सत्र | क्रॉस-सत्र |
| खोज | कुंजी-मान लुकअप | सिमेंटिक खोज |
| उपयोग का मामला | वर्तमान संदर्भ | दीर्घकालिक स्मरण |
पिछला: ← Guardrails | अगला: Studio →