स्टेट मैनेजमेंट

ADK-Rust में सेशन स्टेट एजेंट्स को डेटा स्टोर और रिट्रीव करने की अनुमति देता है जो बातचीत के मोड़ों पर बना रहता है। स्टेट को की प्रीफिक्स का उपयोग करके व्यवस्थित किया जाता है जो डेटा के स्कोप और लाइफटाइम को निर्धारित करते हैं।

अवलोकन

स्टेट को की-वैल्यू पेयर के रूप में संग्रहीत किया जाता है जहाँ:

  • कीज़ वैकल्पिक प्रीफिक्स के साथ स्ट्रिंग्स होती हैं
  • वैल्यूज़ JSON वैल्यूज़ (serde_json::Value) होती हैं

प्रीफिक्स सिस्टम विभिन्न स्कोपिंग स्तरों को सक्षम बनाता है:

  • सेशन-स्कोप: डिफ़ॉल्ट, एक सिंगल सेशन से जुड़ा हुआ
  • यूज़र-स्कोप: एक यूज़र के लिए सभी सेशंस में साझा किया गया
  • ऐप-स्कोप: एक एप्लीकेशन के सभी यूज़र्स में साझा किया गया
  • टेम्पररी: प्रत्येक इनवोकेशन के बाद साफ़ किया गया

स्टेट ट्रेट

State ट्रेट स्टेट एक्सेस के लिए इंटरफ़ेस को परिभाषित करता है:

use serde_json::Value;
use std::collections::HashMap;

pub trait State: Send + Sync {
    /// Get a value by key
    fn get(&self, key: &str) -> Option<Value>;
    
    /// Set a value
    fn set(&mut self, key: String, value: Value);
    
    /// Get all state as a map
    fn all(&self) -> HashMap<String, Value>;
}

रीड-ओनली एक्सेस के लिए एक ReadonlyState ट्रेट भी है:

pub trait ReadonlyState: Send + Sync {
    fn get(&self, key: &str) -> Option<Value>;
    fn all(&self) -> HashMap<String, Value>;
}

स्टेट की प्रीफिक्स

ADK-Rust स्टेट स्कोपिंग को नियंत्रित करने के लिए तीन की प्रीफिक्स का उपयोग करता है:

उपसर्गस्थिरांकदायरा
app:KEY_PREFIX_APPसभी उपयोगकर्ताओं और सत्रों में साझा किया गया
user:KEY_PREFIX_USERएक उपयोगकर्ता के लिए सभी सत्रों में साझा किया गया
temp:KEY_PREFIX_TEMPप्रत्येक आह्वान के बाद साफ़ किया गया
(कोई नहीं)-सत्र-व्यापी (डिफ़ॉल्ट)

app: - एप्लिकेशन स्थिति

किसी एप्लिकेशन के सभी उपयोगकर्ताओं और Session में साझा की गई स्थिति।

use adk_session::KEY_PREFIX_APP;

// KEY_PREFIX_APP = "app:"
let key = format!("{}settings", KEY_PREFIX_APP);  // "app:settings"

उपयोग के मामले:

  • एप्लिकेशन कॉन्फ़िगरेशन
  • साझा संसाधन
  • वैश्विक काउंटर या आँकड़े

user: - उपयोगकर्ता स्थिति

किसी विशिष्ट उपयोगकर्ता के लिए सभी Session में साझा की गई स्थिति।

use adk_session::KEY_PREFIX_USER;

// KEY_PREFIX_USER = "user:"
let key = format!("{}preferences", KEY_PREFIX_USER);  // "user:preferences"

उपयोग के मामले:

  • उपयोगकर्ता प्राथमिकताएँ
  • उपयोगकर्ता प्रोफ़ाइल डेटा
  • क्रॉस-Session उपयोगकर्ता संदर्भ

temp: - अस्थायी स्थिति

प्रत्येक आह्वान के बाद साफ़ की जाने वाली स्थिति। यह स्थायी नहीं होती।

use adk_session::KEY_PREFIX_TEMP;

// KEY_PREFIX_TEMP = "temp:"
let key = format!("{}current_step", KEY_PREFIX_TEMP);  // "temp:current_step"

उपयोग के मामले:

  • मध्यवर्ती गणना परिणाम
  • वर्तमान ऑपरेशन संदर्भ
  • वह डेटा जो स्थायी नहीं होना चाहिए

कोई उपसर्ग नहीं - Session स्थिति

बिना उपसर्ग वाली कुंजियाँ Session-स्कोप वाली होती हैं (डिफ़ॉल्ट व्यवहार)।

let key = "conversation_topic";  // Session-scoped

उपयोग के मामले:

  • वार्तालाप संदर्भ
  • Session-विशिष्ट डेटा
  • बारी-बारी की स्थिति

प्रारंभिक स्थिति सेट करना

Session बनाते समय स्थिति को इनिशियलाइज़ किया जा सकता है:

use adk_session::{InMemorySessionService, SessionService, CreateRequest, KEY_PREFIX_APP, KEY_PREFIX_USER};
use serde_json::json;
use std::collections::HashMap;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut initial_state = HashMap::new();

    // App-scoped state
    initial_state.insert(
        format!("{}version", KEY_PREFIX_APP),
        json!("1.0.0")
    );

    // User-scoped state
    initial_state.insert(
        format!("{}name", KEY_PREFIX_USER),
        json!("Alice")
    );

    // Session-scoped state
    initial_state.insert(
        "topic".to_string(),
        json!("Getting started")
    );

    let service = InMemorySessionService::new();
    let session = service.create(CreateRequest {
        app_name: "my_app".to_string(),
        user_id: "user_123".to_string(),
        session_id: None,
        state: initial_state,
    }).await?;
    
    Ok(())
}

स्थिति पढ़ना

Session के state() मेथड के माध्यम से स्थिति तक पहुँचें:

let state = session.state();

// Get a specific key
if let Some(value) = state.get("topic") {
    println!("Topic: {}", value);
}

// Get app-scoped state
if let Some(version) = state.get("app:version") {
    println!("App version: {}", version);
}

// Get all state
let all_state = state.all();
for (key, value) in all_state {
    println!("{}: {}", key, value);
}

Event के माध्यम से स्थिति अपडेट

स्थिति आमतौर पर Event क्रियाओं के माध्यम से अपडेट की जाती है। जब किसी Session में कोई Event जोड़ा जाता है, तो उसका state_delta लागू होता है:

use adk_session::{Event, EventActions};
use serde_json::json;
use std::collections::HashMap;

let mut state_delta = HashMap::new();
state_delta.insert("counter".to_string(), json!(42));
state_delta.insert("user:last_seen".to_string(), json!("2024-01-15"));

let mut event = Event::new("invocation_123");
event.actions = EventActions {
    state_delta,
    ..Default::default()
};

// When this event is appended, state is updated
service.append_event(session.id(), event).await?;

स्थिति स्कोपिंग व्यवहार

Session सेवा स्वचालित रूप से स्थिति स्कोपिंग को संभालती है:

Session निर्माण पर

  1. app: उपसर्ग वाली कुंजियाँ निकालें → एप्लिकेशन स्थिति में संग्रहीत करें
  2. user: उपसर्ग वाली कुंजियाँ निकालें → उपयोगकर्ता स्थिति में संग्रहीत करें
  3. शेष कुंजियाँ (temp: को छोड़कर) → Session स्थिति में संग्रहीत करें
  4. लौटाई गई Session के लिए सभी स्कोप मर्ज करें

Session पुनर्प्राप्ति पर

  1. एप्लिकेशन के लिए एप्लिकेशन स्थिति लोड करें
  2. उपयोगकर्ता के लिए उपयोगकर्ता स्थिति लोड करें
  3. Session स्थिति लोड करें
  4. सभी स्कोप मर्ज करें (एप्लिकेशन → उपयोगकर्ता → Session)

Event जोड़ने पर

  1. Event से स्थिति डेल्टा निकालें
  2. temp: कुंजियों को फ़िल्टर करें (स्थायी नहीं)
  3. app: डेल्टा को एप्लिकेशन स्थिति पर लागू करें
  4. user: डेल्टा को उपयोगकर्ता स्थिति पर लागू करें
  5. शेष डेल्टा को Session स्थिति पर लागू करें

पूर्ण उदाहरण

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

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let service = InMemorySessionService::new();
    
    // Create first session with initial state
    let mut state1 = HashMap::new();
    state1.insert(format!("{}theme", KEY_PREFIX_APP), json!("dark"));
    state1.insert(format!("{}language", KEY_PREFIX_USER), json!("en"));
    state1.insert("context".to_string(), json!("session1"));
    
    let session1 = service.create(CreateRequest {
        app_name: "my_app".to_string(),
        user_id: "alice".to_string(),
        session_id: Some("s1".to_string()),
        state: state1,
    }).await?;
    
    // Create second session for same user
    let mut state2 = HashMap::new();
    state2.insert("context".to_string(), json!("session2"));
    
    let session2 = service.create(CreateRequest {
        app_name: "my_app".to_string(),
        user_id: "alice".to_string(),
        session_id: Some("s2".to_string()),
        state: state2,
    }).await?;
    
    // Session 2 inherits app and user state
    let s2_state = session2.state();
    
    // App state is shared
    assert_eq!(s2_state.get("app:theme"), Some(json!("dark")));
    
    // User state is shared
    assert_eq!(s2_state.get("user:language"), Some(json!("en")));
    
    // Session state is separate
    assert_eq!(s2_state.get("context"), Some(json!("session2")));
    
    println!("State scoping works correctly!");
    Ok(())
}

स्थिति के साथ इंस्ट्रक्शन टेम्प्लेटिंग

Session स्थिति से मानों का उपयोग करके Agent निर्देशों में {key} सिंटैक्स का उपयोग करके स्थिति मानों को इंजेक्ट किया जा सकता है:

use adk_rust::prelude::*;
use std::sync::Arc;

let agent = LlmAgentBuilder::new("personalized_assistant")
    .instruction("You are helping {user:name} with {topic}. Their preferred language is {user:language}.")
    .model(Arc::new(model))
    .build()?;

जब Agent चलता है, तो {user:name}, {topic}, और {user:language} को Session स्थिति से मानों से बदल दिया जाता है।

सर्वोत्तम अभ्यास

1. उचित स्कोप का उपयोग करें

// ✅ Good: User preferences in user scope
"user:theme"
"user:timezone"

// ✅ Good: Session-specific context without prefix
"current_task"
"conversation_summary"

// ✅ Good: App-wide settings in app scope
"app:model_version"
"app:feature_flags"

// ❌ Bad: User data in session scope (lost between sessions)
"user_preferences"  // Should be "user:preferences"

2. मध्यवर्ती डेटा के लिए अस्थायी स्थिति का उपयोग करें

// ✅ Good: Intermediate results in temp scope
"temp:search_results"
"temp:current_step"

// ❌ Bad: Intermediate data persisted unnecessarily
"search_results"  // Will be saved to database

3. स्थिति कुंजियों को सुसंगत रखें

// ✅ Good: Consistent naming convention
"user:preferences.theme"
"user:preferences.language"

// ❌ Bad: Inconsistent naming
"user:theme"
"userLanguage"
"user-timezone"
  • Sessions - Session प्रबंधन अवलोकन
  • Events - Event संरचना और state_delta
  • LlmAgent - इंस्ट्रक्शन टेम्प्लेटिंग

पिछला: ← Sessions | अगला: Callbacks →