الذاكرة

ذاكرة دلالية طويلة المدى لوكلاء الذكاء الاصطناعي باستخدام adk-memory.

نظرة عامة

يوفر نظام الذاكرة تخزينًا ثابتًا وقابلاً للبحث لمحادثات الوكيل. على عكس حالة الجلسة (التي تكون سريعة الزوال)، تستمر الذاكرة عبر الجلسات وتمكن الوكلاء من استدعاء السياق ذي الصلة من التفاعلات السابقة.

التثبيت

[dependencies]
adk-memory = "0.2.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) للخلفيات التخزينية (memory 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

معلمات الاستعلام لبحث الذاكرة:

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

تنفيذ بسيط في الذاكرة للتطوير والاختبار:

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(())
}

عزل الذاكرة

يتم عزل الذكريات بواسطة:

  • app_name: التطبيقات المختلفة لها مساحات ذاكرة منفصلة.
  • user_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(),
};

سلوك البحث

يستخدم InMemoryMemoryService المطابقة القائمة على الكلمات:

  1. يتم تقسيم الاستعلام إلى كلمات (أحرف صغيرة).
  2. يتم تقسيم محتوى كل ذاكرة إلى كلمات.
  3. يتم إرجاع الذكريات التي تحتوي على أي كلمات متطابقة.
// Query: "rust programming"
// Matches memories containing "rust" OR "programming"

واجهة خلفية ذاكرة مخصصة

نفّذ MemoryService للتخزين المخصص (مثل: vector database):

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![] })
    }
}

التكامل مع Agents

Memory يتكامل مع 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()?;

عندما يتم تكوين memory:

  1. قبل كل دور، يتم البحث عن memories ذات الصلة
  2. يتم حقن memories المطابقة في السياق
  3. بعد كل session، يتم تخزين المحادثة كـ memories

البنية

┌─────────────────────────────────────────────────────────────┐
│                      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            │
└─────────────────────────────────────────────────────────────┘

أفضل الممارسات

الممارسةالوصف
استخدم قاعدة بيانات متجهة في الإنتاجInMemory مخصصة للتطوير/الاختبار فقط
تحديد النطاق حسب المستخدمقم دائمًا بتضمين user_id للخصوصية
تقييد النتائجحدد الذكريات المعادة لتجنب تجاوز السياق
تنظيف الذكريات القديمةطبق TTL أو الأرشفة للبيانات القديمة
التضمين بشكل استراتيجيقم بتخزين الملخصات، وليس المحادثات الخام

مقارنة مع الجلسات

الميزةحالة الجلسةالذاكرة
الاستمراريةمدة صلاحية الجلسةدائمة
النطاقجلسة واحدةعبر الجلسات
البحثالبحث عن طريق المفتاح والقيمةالبحث الدلالي
حالة الاستخدامالسياق الحاليالاستدعاء طويل الأمد

السابق: ← الضوابط | التالي: Studio →