ضغط السياق

أثناء تشغيل وكيل ADK، يتراكم السياق — رسائل المستخدم، واستجابات الأدوات، والمحتوى المُنشأ. ومع نمو هذا السياق، تزداد أوقات معالجة LLM لأن المزيد من البيانات يُرسَل مع كل طلب. يعالج ضغط السياق هذه المشكلة من خلال تلخيص الأحداث الأقدم باستخدام نهج النافذة المنزلقة.

كيفية عمله

يستخدم ضغط السياق نافذة منزلقة لتلخيص أحداث المحادثة الأقدم دوريًا ضمن جلسة. عندما يصل عدد الاستدعاءات المكتملة إلى الفاصل الزمني المُهيأ، يضغط الملخِّص الأحداث الأقدم في حدث ملخّص واحد.

Invocations 1-3: [event1, event2, event3] → Summarized into "Summary A"
Invocations 4-6: [Summary A, event3, event4, event5, event6] → Summarized into "Summary B"

تتحكم المعلمة overlap_size في عدد الأحداث من النافذة السابقة التي تنتقل إلى الملخّص التالي، مما يحافظ على الاستمرارية.

الإعداد

أضف الضغط إلى إعدادات المشغّل:

use adk_agent::LlmEventSummarizer;
use adk_runner::{Runner, RunnerConfig, EventsCompactionConfig};
use std::sync::Arc;

// Use any LLM for summarization (a fast, cheap model works well)
let summarizer_llm = Arc::new(my_model);
let summarizer = Arc::new(LlmEventSummarizer::new(summarizer_llm));

let runner = Runner::new(RunnerConfig {
    app_name: "my_app".to_string(),
    agent: root_agent,
    session_service: sessions,
    artifact_service: None,
    memory_service: None,
    plugin_manager: None,
    run_config: None,
    compaction_config: Some(EventsCompactionConfig {
        compaction_interval: 3,  // Compact every 3 invocations
        overlap_size: 1,         // Keep 1 prior invocation for context
        summarizer,
    }),
})?;

معلمات الإعداد

المَعلمةالنوعالوصف
compaction_intervalu32عدد الاستدعاءات المكتملة الذي يؤدي إلى التكثيف
overlap_sizeu32الأحداث من النافذة السابقة المضمّنة في الملخص التالي
summarizerArc<dyn BaseEventsSummarizer>استراتيجية التلخيص

الملخِّص المخصَّص

يمكنك تخصيص مطالبة التلخيص:

let summarizer = LlmEventSummarizer::new(llm)
    .with_prompt_template(
        "Summarize this conversation focusing on action items \
         and decisions:\n\n{conversation_history}"
    );

أو تنفيذ BaseEventsSummarizer للتحكم الكامل:

use adk_core::{BaseEventsSummarizer, Event, Result};
use async_trait::async_trait;

struct MySummarizer;

#[async_trait]
impl BaseEventsSummarizer for MySummarizer {
    async fn summarize_events(&self, events: &[Event]) -> Result<Option<Event>> {
        // Custom summarization logic
        // Return None to skip compaction for this window
        todo!()
    }
}

كيف يؤثر الضغط في السجل

عند استدعاء conversation_history() في جلسة تحتوي على أحداث ضغط:

  1. يتم العثور على أحدث حدث ضغط
  2. يحل ملخصه محل جميع الأحداث حتى حدّ الضغط
  3. لا تُدرج بشكل فردي إلا الأحداث التي تلي الحدّ

هذا شفاف بالنسبة إلى الوكلاء — إذ يتلقون سجل محادثة متماسكًا يتضمن الملخص متبوعًا بالأحداث الأخيرة.

مثال على الخط الزمني

باستخدام compaction_interval: 3 وoverlap_size: 1:

الاستدعاءالأحداثالإجراء
1المستخدم→الوكيل
2المستخدم→الوكيل
3المستخدم→الوكيلضغط الأحداث 1-3 في الملخص A
4المستخدم→الوكيل
5المستخدم→الوكيل
6المستخدم→الوكيلضغط الأحداث 3-6 (التداخل=1) في الملخص B

بعد الاستدعاء السادس، يرى الوكيل: [Summary B, event 6 overlap events, event 7+]

ملاحظات

  • فشل الاختصار غير قاتل — يسجّل المشغّل تحذيرًا ويتابع التنفيذ
  • يُنفَّذ الاختصار بعد اكتمال تدفق الاستدعاءات، وليس أثناءه
  • يُحفَظ حدث الاختصار في خدمة الجلسة لضمان المتانة
  • استخدم نموذجًا سريعًا ومنخفض التكلفة للتلخيص (مثل gemini-3.5-flash-lite)