الجلسات

توفر الجلسات في adk-rust إدارة سياق المحادثة، مما يسمح للوكلاء بالحفاظ على الحالة عبر تفاعلات متعددة. تخزن الجلسات سجل المحادثة (events) وبيانات الحالة العشوائية التي تستمر طوال المحادثة.

نظرة عامة

تمثل الجلسة محادثة واحدة بين مستخدم ووكيل. كل جلسة:

  • لها معرف فريد
  • تنتمي إلى تطبيق (app_name) ومستخدم (user_id)
  • تحتوي على قائمة من الأحداث (سجل المحادثة)
  • تحافظ على بيانات الحالة (أزواج المفتاح والقيمة)
  • تتتبع وقت آخر تحديث

سمة Session

تحدد سمة Session الواجهة لكائنات الجلسة:

use adk_session::{Events, State};
use chrono::{DateTime, Utc};

pub trait Session: Send + Sync {
    /// معرف الجلسة الفريد
    fn id(&self) -> &str;
    
    /// اسم التطبيق الذي تنتمي إليه هذه الجلسة
    fn app_name(&self) -> &str;
    
    /// معرف المستخدم
    fn user_id(&self) -> &str;
    
    /// الوصول إلى حالة الجلسة
    fn state(&self) -> &dyn State;
    
    /// الوصول إلى أحداث المحادثة
    fn events(&self) -> &dyn Events;
    
    /// آخر مرة تم فيها تحديث الجلسة
    fn last_update_time(&self) -> DateTime<Utc>;
}

سمة SessionService

تحدد سمة SessionService العمليات لإدارة الجلسات:

use adk_session::{CreateRequest, GetRequest, ListRequest, DeleteRequest, Event, Session};
use adk_core::Result;
use async_trait::async_trait;

#[async_trait]
pub trait SessionService: Send + Sync {
    /// إنشاء جلسة جديدة
    async fn create(&self, req: CreateRequest) -> Result<Box<dyn Session>>;
    
    /// استرداد جلسة موجودة
    async fn get(&self, req: GetRequest) -> Result<Box<dyn Session>>;
    
    /// سرد جميع الجلسات لتطبيق/مستخدم
    async fn list(&self, req: ListRequest) -> Result<Vec<Box<dyn Session>>>;
    
    /// حذف جلسة
    async fn delete(&self, req: DeleteRequest) -> Result<()>;
    
    /// إلحاق حدث بجلسة
    async fn append_event(&self, session_id: &str, event: Event) -> Result<()>;
}

أنواع الطلبات

CreateRequest

use adk_session::CreateRequest;
use std::collections::HashMap;

let request = CreateRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
    session_id: None,  // إنشاء UUID تلقائيًا إذا كان None
    state: HashMap::new(),  // الحالة الأولية
};

GetRequest

use adk_session::GetRequest;

let request = GetRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
    session_id: "session_abc".to_string(),
    num_recent_events: Some(10),  // تحديد عدد الأحداث المرجعة
    after: None,  // تصفية الأحداث بعد الطابع الزمني
};

ListRequest

use adk_session::ListRequest;

let request = ListRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
};

DeleteRequest

use adk_session::DeleteRequest;

let request = DeleteRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
    session_id: "session_abc".to_string(),
};

تطبيقات SessionService

يوفر ADK-Rust تطبيقين لخدمة Session:

InMemorySessionService

تخزن الجلسات في الذاكرة. مثالية للتطوير والاختبار والنشر على مثيل واحد.

use adk_session::{InMemorySessionService, SessionService, CreateRequest};
use std::collections::HashMap;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Create the service
    let session_service = InMemorySessionService::new();
    
    // Create a session
    let session = session_service.create(CreateRequest {
        app_name: "my_app".to_string(),
        user_id: "user_123".to_string(),
        session_id: None,
        state: HashMap::new(),
    }).await?;
    
    println!("Session ID: {}", session.id());
    println!("App: {}", session.app_name());
    println!("User: {}", session.user_id());
    
    Ok(())
}

DatabaseSessionService

تخزن الجلسات في قاعدة بيانات SQLite. مناسبة لعمليات النشر في الإنتاج التي تتطلب استمرارية.

use adk_session::{DatabaseSessionService, SessionService, CreateRequest};
use std::collections::HashMap;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Connect to database
    let session_service = DatabaseSessionService::new("sqlite:sessions.db").await?;
    
    // Run migrations to create tables
    session_service.migrate().await?;
    
    // Create a session
    let session = session_service.create(CreateRequest {
        app_name: "my_app".to_string(),
        user_id: "user_123".to_string(),
        session_id: None,
        state: HashMap::new(),
    }).await?;
    
    println!("Session persisted: {}", session.id());
    
    Ok(())
}

ملاحظة: يتطلب DatabaseSessionService علامة الميزة database:

adk-session = { version = "0.2", features = ["database"] }

دورة حياة Session

1. الإنشاء

يتم إنشاء الجلسات باستخدام CreateRequest. إذا لم يتم توفير session_id، يتم إنشاء UUID تلقائيًا.

use adk_session::{InMemorySessionService, SessionService, CreateRequest};
use std::collections::HashMap;

let service = InMemorySessionService::new();

// Create with auto-generated ID
let session = service.create(CreateRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
    session_id: None,
    state: HashMap::new(),
}).await?;

// Create with specific ID
let session = service.create(CreateRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
    session_id: Some("my-custom-id".to_string()),
    state: HashMap::new(),
}).await?;

2. الاسترداد

استرداد الجلسة بواسطة معرفاتها:

use adk_session::GetRequest;

let session = service.get(GetRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
    session_id: "session_abc".to_string(),
    num_recent_events: None,
    after: None,
}).await?;

println!("Retrieved session: {}", session.id());
println!("Events: {}", session.events().len());

3. إلحاق الأحداث

يتم إلحاق الأحداث بالجلسات مع تقدم المحادثة. يتم التعامل مع هذا عادةً بواسطة Runner، ولكن يمكن القيام به يدويًا:

use adk_session::Event;

let event = Event::new("invocation_123");
service.append_event(session.id(), event).await?;

4. الإدراج

سرد جميع الجلسات لمستخدم:

use adk_session::ListRequest;

let sessions = service.list(ListRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
}).await?;

for session in sessions {
    println!("Session: {} (updated: {})", 
        session.id(), 
        session.last_update_time()
    );
}

5. الحذف

حذف جلسة عندما لا تكون هناك حاجة إليها:

use adk_session::DeleteRequest;

service.delete(DeleteRequest {
    app_name: "my_app".to_string(),
    user_id: "user_123".to_string(),
    session_id: "session_abc".to_string(),
}).await?;

استخدام الجلسات (Sessions) مع Runner

عادةً ما تتم إدارة Sessions بواسطة Runner عند تنفيذ Agents. يقوم Runner بما يلي:

  1. ينشئ أو يسترجع session
  2. يمرر سياق الـsession إلى الـAgent
  3. يضيف Events مع تقدم المحادثة
  4. يحدث حالة الـsession بناءً على إجراءات الـAgent
use adk_rust::prelude::*;
use adk_runner::{Runner, RunnerConfig};
use adk_session::InMemorySessionService;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = Arc::new(GeminiModel::new(&api_key, "gemini-2.0-flash")?);

    let agent = LlmAgentBuilder::new("assistant")
        .model(model)
        .instruction("You are a helpful assistant.")
        .build()?;

    let session_service = Arc::new(InMemorySessionService::new());

    // Create runner with session service
    let runner = Runner::new(RunnerConfig {
        app_name: "my_app".to_string(),
        agent: Arc::new(agent),
        session_service,
        artifact_service: None,
        memory_service: None,
        run_config: None,
    })?;

    // Run with user and session IDs
    let user_content = Content::new("user").with_text("Hello!");
    let stream = runner.run(
        "user_123".to_string(),
        "session_abc".to_string(),
        user_content,
    ).await?;

    Ok(())
}

الأحداث (Events)

يوفر الـtrait Events إمكانية الوصول إلى سجل المحادثة:

pub trait Events: Send + Sync {
    /// Get all events
    fn all(&self) -> Vec<Event>;
    
    /// Get number of events
    fn len(&self) -> usize;
    
    /// Get event at index
    fn at(&self, index: usize) -> Option<&Event>;
    
    /// Check if empty
    fn is_empty(&self) -> bool;
}

الوصول إلى Events من session:

let events = session.events();
println!("Total events: {}", events.len());

for event in events.all() {
    println!("Event {} by {} at {}", 
        event.id, 
        event.author, 
        event.timestamp
    );
}

مثال كامل

use adk_session::{
    InMemorySessionService, SessionService, 
    CreateRequest, GetRequest, ListRequest, DeleteRequest,
    Event, KEY_PREFIX_USER,
};
use serde_json::json;
use std::collections::HashMap;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let service = InMemorySessionService::new();
    
    // Create session with initial state
    let mut initial_state = HashMap::new();
    initial_state.insert(format!("{}name", KEY_PREFIX_USER), json!("Alice"));
    initial_state.insert("topic".to_string(), json!("Getting started"));
    
    let session = service.create(CreateRequest {
        app_name: "demo".to_string(),
        user_id: "alice".to_string(),
        session_id: None,
        state: initial_state,
    }).await?;
    
    println!("Created session: {}", session.id());
    
    // Check state
    let state = session.state();
    println!("User name: {:?}", state.get("user:name"));
    println!("Topic: {:?}", state.get("topic"));
    
    // Append an event
    let event = Event::new("inv_001");
    service.append_event(session.id(), event).await?;
    
    // Retrieve session with events
    let session = service.get(GetRequest {
        app_name: "demo".to_string(),
        user_id: "alice".to_string(),
        session_id: session.id().to_string(),
        num_recent_events: None,
        after: None,
    }).await?;
    
    println!("Events: {}", session.events().len());
    
    // List all sessions
    let sessions = service.list(ListRequest {
        app_name: "demo".to_string(),
        user_id: "alice".to_string(),
    }).await?;
    
    println!("Total sessions: {}", sessions.len());
    
    // Delete session
    service.delete(DeleteRequest {
        app_name: "demo".to_string(),
        user_id: "alice".to_string(),
        session_id: session.id().to_string(),
    }).await?;
    
    println!("Session deleted");
    
    Ok(())
}

ذات صلة


السابق: ← MCP Tools | التالي: إدارة الحالة →