الذاكرة في الجلسات الفورية

صوت ينساك بين المكالمات يبدو كأنه كشك خدمة. ADK-Rust يتيح لوكيل فوري أن يتذكر — يسترجع ما تعلّمه عن المستخدم قبل أن يتكلم، وينقّح حقائق جديدة أثناء المحادثة — وذلك عبر ربط MemoryService بـ IntegratedRealtimeRunner.

هناك آليتان تعملان معًا:

  1. حقن السياق تلقائيًا + تخزين كل دور — طبقة التكامل تتولى ذلك نيابةً عنك.
  2. ذاكرة يُديرها الوكيل عبر الأدوات — يقرر الوكيل ما يستحق الاحتفاظ به، باستخدام أدوات رسم بياني معرفي متصلة.

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 يخزن الذاكرة على أنها رسم بياني معرفي ثنائي الزمن: كيانات وعلاقات، يُتتبَّع كل منها عبر وقت الحدث (متى كان ذلك صحيحًا) ووقت الاستيعاب (متى تعلّم النظام ذلك). هذا يعني أن الوكيل يمكنه الإجابة عن "ما الخطة الحالية للمستخدم؟" دون أن يتعثر بسبب أنها كانت شيئًا آخر في السابق — فالحقائق المستبدلة تبقى في السجل بدلًا من أن تكتب فوق الحاضر.

use adk_memory::GraphMemoryService;
use std::sync::Arc;

let kg = Arc::new(GraphMemoryService::new(/* backing store */));

مرّر ذلك على أنه memory_service، وعندها سيعتمد الحقن التلقائي أعلاه على الرسم البياني.

3. تمكين الوكيل من تنقيح الذاكرة

النمط الأقوى: امنح الوكيل أدوات للكتابة إلى الرسم البياني نفسه، حتى يتذكر بشكل مقصود بدلًا من تفريغ كل النص. adk-tool (الميزة graph-memory-tools) تأتي مع أداتين تتصلان مباشرةً بجلسة فورية:

الأداةماذا يفعل الوكيل بها
RememberTool (remember)تخزين حقيقة بارزة ("يفضل البريد الإلكتروني على الهاتف").
RelateTool (relate)ربط كيانين ("الطلب A-10293 → ينتمي إلى → هذا المستخدم").

اربطها بـ .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()?;

ثم وجّه الوكيل لاستخدامها:

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.

الاستدعاء معتمد على الرموز: يعيد الرسم البياني الكيانات/العلاقات الأكثر صلة بالمحادثة، ضمن max_memory_injection، بحيث يظل السياق صغيرًا حتى مع نمو الرسم البياني.

اختيار العمق

  • عرض توضيحي بلا حالة → لا يوجد memory_service. تبدأ كل جلسة من جديد.
  • استمرارية عبر الجلسات → في الذاكرة أو GraphMemoryService مع إدراج/تخزين تلقائي. بلا أي جهد من الوكيل.
  • وكيل متعلمGraphMemoryService + أدوات remember/relate، بحيث ينظم الوكيل نموذجًا نظيفًا وقابلًا للاستعلام عن المستخدم بدلًا من كومة نصوص للمحادثة.

يستخدم مثال الإرشاد MIA الرسم البياني + الأدوات بحيث يتذكر المدرب أهداف المستخدم وتفضيلاته بين الجلسات؛ انظر Examples.

التالي: Building web apps →

ما الذي يُنقل إلى جلسة مستأنفة

IntegratedRealtimeRunner::connect يبني كتلة سياق واحدة ويضيفها في بداية تعليمات النظام قبل إنشاء جلسة المزوّد:

القسمالمصدرالحد
Earlier in this conversation:أحداث الجلسة السابقةIntegrationConfig::max_history_injection (افتراضيًا 20 دورة)
Relevant recalled context:MemoryService::searchIntegrationConfig::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 ثم إسقاطها، وسجّل فرع الذاكرة عبارة "injecting memory entries into session context" بجانب تعليق يذكر أن الإدراج كان تحسينًا مستقبليًا. بدأت جلسة مُستأنفة بدون أيٍّ منهما، بينما كانت السجلات تقول خلاف ذلك.

الذاكرة في الجلسات الفورية - وثائق ADK-Rust | ADK-Rust