Bagikan melalui


Pemadatan

Seiring bertambahnya percakapan, jumlah token riwayat obrolan dapat melebihi jendela konteks model atau meningkatkan biaya. Strategi pemadatan mengurangi ukuran riwayat percakapan sambil mempertahankan konteks penting, sehingga agen dapat terus berfungsi selama interaksi yang berjalan lama.

Penting

Kerangka kerja pemadatan saat ini bersifat eksperimental. Untuk menggunakannya, Anda harus menambahkan #pragma warning disable MAAI001.

Penting

Kerangka kerja pemadatan saat ini bersifat eksperimental di Python. Impor strategi dari agent_framework._compaction.

Mengapa pemadatan penting

Setiap panggilan ke LLM mencakup riwayat percakapan lengkap. Tanpa pemadatan:

  • Batas token — Percakapan akhirnya melebihi jendela konteks model, menyebabkan kesalahan.
  • Biaya — Permintaan yang lebih besar mengonsumsi lebih banyak token, meningkatkan biaya API.
  • Latensi — Lebih banyak token input berarti waktu respons yang lebih lambat.

Pemadatan memecahkan masalah ini dengan secara selektif menghapus, menggabungkan, atau meringkas bagian percakapan yang lebih lama.

Konsep inti

Penerapan: Hanya agen riwayat dalam memori

Pemadatan hanya berlaku untuk agen yang mengelola riwayat percakapan mereka sendiri dalam memori. Agen yang mengandalkan konteks yang dikelola layanan atau status percakapan tidak mendapat manfaat dari pemadatan karena layanan sudah menangani manajemen konteks. Contoh agen yang dikelola layanan meliputi:

  • Agen Foundry — konteks dikelola sisi server oleh layanan Azure AI Foundry.
  • RESPONS API dengan penyimpanan diaktifkan (default) — status percakapan disimpan dan dikelola oleh layanan OpenAI.
  • Agen Copilot Studio — konteks percakapan dikelola oleh layanan Copilot Studio.

Untuk jenis agen ini, mengonfigurasi strategi pemadatan tidak berpengaruh. Pemadatan hanya relevan ketika agen mempertahankan daftar pesan dalam memorinya sendiri dan meneruskan riwayat lengkap ke model pada setiap panggilan.

Pemadatan beroperasi pada MessageIndex — tampilan terstruktur dari daftar pesan datar yang mengorganisir pesan ke dalam unit atom yang disebut instance MessageGroup. Setiap grup melacak jumlah pesan, jumlah byte, dan perkiraan jumlah tokennya.

Grup pesan

Sebuah MessageGroup mewakili pesan-pesan terkait secara logis yang harus disimpan atau dihapus secara bersama-sama. Misalnya, pesan asisten yang berisi panggilan alat dan pesan hasil alat yang sesuai membentuk kelompok atomik — menghilangkan satu tanpa yang lain dapat menyebabkan kesalahan API LLM.

Setiap grup memiliki MessageGroupKind:

Kind Deskripsi
System Satu atau beberapa pesan sistem. Senantiasa dipertahankan selama pemadatan.
User Satu pesan pengguna yang memulai giliran baru.
AssistantText Respons teks asisten biasa (tidak ada panggilan alat).
ToolCall Pesan asisten dengan panggilan alat dan pesan hasil alat yang sesuai, diperlakukan sebagai kesatuan utuh.
Summary Pesan ringkas yang dihasilkan oleh pemadatan ikhtisar.

Pemicu

CompactionTrigger adalah delegat yang mengevaluasi apakah pemadatan harus dilanjutkan berdasarkan metrik saat ini MessageIndex:

public delegate bool CompactionTrigger(MessageIndex index);

Kelas ini CompactionTriggers menyediakan metode pabrikasi yang umum:

Pemicu Menembak ketika
CompactionTriggers.Always Setiap kali (tanpa syarat).
CompactionTriggers.Never Tidak pernah (mematikan fitur pemadatan).
CompactionTriggers.TokensExceed(maxTokens) Jumlah token yang disertakan melebihi ambang batas.
CompactionTriggers.MessagesExceed(maxMessages) Jumlah pesan yang disertakan melebihi ambang batas.
CompactionTriggers.TurnsExceed(maxTurns) Jumlah giliran pengguna yang termasuk melebihi ambang batas.
CompactionTriggers.GroupsExceed(maxGroups) Jumlah grup yang disertakan melebihi ambang batas.
CompactionTriggers.HasToolCalls() Setidaknya ada satu grup panggilan alat yang tidak termasuk dalam pengecualian.

Gabungkan pemicu dengan CompactionTriggers.All(...) (LOGICAL AND) atau CompactionTriggers.Any(...) (logis OR):

// Compact only when there are tool calls AND tokens exceed 2000
CompactionTrigger trigger = CompactionTriggers.All(
    CompactionTriggers.HasToolCalls(),
    CompactionTriggers.TokensExceed(2000));

Pemicu vs. Sasaran

Setiap strategi memiliki dua predikat:

  • Pemicu — Kontrol saat pemadatan dimulai. Jika pemicu kembali false, strategi diabaikan sepenuhnya.
  • Target — Kontrol saat pemadatan berhenti. Strategi secara bertahap mengecualikan grup dan mengevaluasi ulang target setelah setiap langkah, berhenti segera setelah target tercapai true.

Ketika tidak ada target yang ditentukan, default diatur ke kebalikan dari pemicu — pemadatan berhenti segera setelah kondisi pemicu tidak lagi memenuhi syarat.

Pemadatan beroperasi pada daftar objek yang datar Message. Pesan dianotasikan dengan metadata grup ringan, dan strategi mengubah anotasi tersebut untuk menandai grup sebagai dikecualikan sebelum daftar pesan diproyeksikan ke model.

Grup pesan

Pesan dikelompokkan ke dalam unit atom. Setiap grup diberi GroupKind:

Kind Deskripsi
system Pesan sistem. Senantiasa dipertahankan selama pemadatan.
user Satu pesan pengguna.
assistant_text Respons teks asisten biasa (tidak ada panggilan fungsi).
tool_call Pesan asisten dengan panggilan fungsi ditambah pesan hasil alat yang sesuai, diperlakukan sebagai unit atomik.

Strategi pemadatan

CompactionStrategy adalah protokol — setiap async yang dapat dipanggil yang menerima list[Message] dan mengubahnya langsung di tempat, mengembalikan True ketika ada perubahan yang terjadi.

class CompactionStrategy(Protocol):
    async def __call__(self, messages: list[Message]) -> bool: ...

Pembuat token

Strategi yang memperhatikan token menerima implementasi TokenizerProtocol. Bawaan CharacterEstimatorTokenizer menggunakan heuristik 4 karakter per token:

from agent_framework._compaction import CharacterEstimatorTokenizer

tokenizer = CharacterEstimatorTokenizer()

Berikan tokenizer kustom saat Anda memerlukan jumlah token yang akurat untuk pengodean model tertentu.

Strategi pemadatan

Semua strategi diwariskan dari kelas dasar abstrak CompactionStrategy . Setiap strategi mempertahankan pesan sistem dan menghormati MinimumPreserved batas yang melindungi grup non-sistem terbaru dari penghapusan.

Strategi pemadatan diimpor dari agent_framework._compaction.

Strategi Pemotongan dan Pemadatan

Strategi Pemotongan

Pendekatan yang paling mudah: menghapus grup pesan non-sistem tertua hingga kondisi target terpenuhi.

  • Menghormati batas grup atomik (panggilan perangkat dan pesan hasil dihapus bersamaan).
  • Terbaik untuk backstop anggaran token keras.
  • MinimumPreserved defaultnya adalah 32.
// Drop oldest groups when tokens exceed 32K, keeping at least 10 recent groups
TruncationCompactionStrategy truncation = new(
    trigger: CompactionTriggers.TokensExceed(0x8000),
    minimumPreserved: 10);
  • Ketika tokenizer disediakan, metrik adalah jumlah token; jika tidak, metriknya adalah jumlah pesan.
  • preserve_system defaultnya adalah True.
from agent_framework._compaction import CharacterEstimatorTokenizer, TruncationStrategy

# Exclude oldest groups when tokens exceed 32 000, trimming to 16 000
truncation = TruncationStrategy(
    max_n=32_000,
    compact_to=16_000,
    tokenizer=CharacterEstimatorTokenizer(),
)

SlidingWindowCompactionStrategy

SlidingWindowStrategy

Menghapus konten percakapan yang lebih lama untuk menyimpan hanya jendela pertukaran terbaru, menghormati unit percakapan logis daripada jumlah pesan sewenang-wenang. Pesan sistem dipertahankan secara keseluruhan.

  • Terbaik untuk membatasi panjang percakapan secara dapat diprediksi.

Menghapus giliran pengguna terlama dan grup respons terkait mereka, beroperasi pada batas belokan logis daripada grup individual.

  • Giliran dimulai dengan pesan pengguna dan menyertakan semua asisten dan grup panggilan alat berikutnya hingga pesan pengguna berikutnya.
  • MinimumPreserved default ke 1 (mempertahankan setidaknya grup non-sistem terbaru).
// Keep only the last 4 user turns
SlidingWindowCompactionStrategy slidingWindow = new(
    trigger: CompactionTriggers.TurnsExceed(4));

Hanya menjaga grup non-sistem terbaru keep_last_groups, tidak termasuk grup yang lebih lama.

  • preserve_system defaultnya adalah True.
from agent_framework._compaction import SlidingWindowStrategy

# Keep only the last 20 non-system groups
sliding_window = SlidingWindowStrategy(keep_last_groups=20)

Strategi Pemadatan Hasil Alat

Menggabungkan grup panggilan alat yang lebih lama ke dalam pesan ringkasan ringkas, mempertahankan jejak yang dapat dibaca tanpa overhead pesan yang lengkap.

  • Tidak menyentuh pesan pengguna atau respons asisten biasa.
  • Terbaik sebagai strategi first-pass untuk merebut kembali ruang dari hasil alat verbose.
  • Mengganti kelompok panggilan alat dengan banyak pesan (panggilan untuk asisten + hasil alat) menjadi ringkasan singkat seperti [Tool calls: get_weather, search_docs].
  • MinimumPreserved beralih ke 2, memastikan interaksi alat dalam sesi saat ini tetap terlihat.
// Collapse old tool results when tokens exceed 512
ToolResultCompactionStrategy toolCompaction = new(
    trigger: CompactionTriggers.TokensExceed(0x200));
  • Menguraikan ke dalam pesan ringkasan yang ringkas seperti [Tool results: get_weather: sunny, 18°C].
  • Grup panggilan alat yang paling terbaru keep_last_tool_call_groups dibiarkan tidak tersentuh.
from agent_framework._compaction import ToolResultCompactionStrategy

# Collapse all but the newest tool-call group
tool_result = ToolResultCompactionStrategy(keep_last_tool_call_groups=1)

SummarizationCompactionStrategy

Strategi Ringkasan

Menggunakan LLM untuk meringkas bagian percakapan yang lebih lama, menggantinya dengan satu pesan ringkasan.

  • Perintah default mempertahankan fakta utama, keputusan, preferensi pengguna, dan hasil panggilan alat.
  • Memerlukan klien LLM terpisah untuk ringkasan — model yang lebih kecil dan lebih cepat direkomendasikan.
  • Terbaik untuk mempertahankan konteks percakapan sambil mengurangi jumlah token secara signifikan.
  • Anda dapat memberikan perintah ringkasan kustom.
  • Melindungi pesan sistem dan grup non-sistem terbaru MinimumPreserved (default: 4).
  • Memindahkan pesan lama ke IChatClient terpisah dengan petunjuk ringkasan, lalu menyisipkan ringkasannya sebagai grup MessageGroupKind.Summary.
// Summarize older messages when tokens exceed 1280, keeping the last 4 groups
SummarizationCompactionStrategy summarization = new(
    chatClient: summarizerChatClient,
    trigger: CompactionTriggers.TokensExceed(0x500),
    minimumPreserved: 4);

Anda dapat memberikan perintah ringkasan kustom:

SummarizationCompactionStrategy summarization = new(
    chatClient: summarizerChatClient,
    trigger: CompactionTriggers.TokensExceed(0x500),
    summarizationPrompt: "Summarize the key decisions and user preferences only.");
  • Dipicu ketika jumlah pesan non-sistem yang disertakan melebihi target_count + threshold.
  • Mempertahankan pesan target_count terbaru; meringkas semua yang lebih lama.
  • Membutuhkan SupportsChatGetResponse klien.
from agent_framework._compaction import SummarizationStrategy

# Summarize when non-system message count exceeds 6, retaining the 4 newest
summarization = SummarizationStrategy(
    client=summarizer_client,
    target_count=4,
    threshold=2,
)

Berikan perintah ringkasan kustom:

summarization = SummarizationStrategy(
    client=summarizer_client,
    target_count=4,
    prompt="Summarize the key decisions and user preferences only.",
)

Strategi Pemadatan Pipa

Menyusun beberapa strategi ke dalam alur berurutan. Setiap strategi beroperasi pada hasil strategi sebelumnya, memungkinkan kompaksi berlapis dari lembut ke agresif.

  • Pemicu pipa aliran adalah CompactionTriggers.Always — setiap strategi anak mengevaluasi pemicunya dengan mandiri.
  • Strategi dijalankan secara berurutan, jadi letakkan strategi paling lembut terlebih dahulu.
PipelineCompactionStrategy pipeline = new(
    new ToolResultCompactionStrategy(CompactionTriggers.TokensExceed(0x200)),
    new SummarizationCompactionStrategy(summarizerChatClient, CompactionTriggers.TokensExceed(0x500)),
    new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(4)),
    new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(0x8000)));

Alur ini:

  1. Menciutkan hasil alat lama (lembut).
  2. Meringkas rentang percakapan yang lebih lama (sedang).
  3. Hanya menyimpan 4 percakapan pengguna terakhir (agresif).
  4. Menjatuhkan grup tertua jika masih melebihi anggaran (backstop darurat).

Strategi Kompak Panggilan Alat Selektif

Sepenuhnya mengecualikan grup panggilan alat yang lebih lama, hanya menyimpan yang terakhir keep_last_tool_call_groups.

  • Tidak menyentuh pesan pengguna atau asisten biasa.
  • Terbaik ketika obrolan alat mendominasi penggunaan token dan riwayat alat lengkap tidak diperlukan.
from agent_framework._compaction import SelectiveToolCallCompactionStrategy

# Keep only the most recent tool-call group
selective_tool = SelectiveToolCallCompactionStrategy(keep_last_tool_call_groups=1)

TokenBudgetComposedStrategy

Menyusun beberapa strategi ke dalam alur berurutan yang didorong oleh anggaran token. Setiap strategi anak berjalan secara berurutan, berhenti lebih awal setelah anggaran terpenuhi. Cadangan bawaan mengecualikan grup tertua jika strategi sendiri tidak dapat mencapai target.

  • Strategi dijalankan secara berurutan; menempatkan strategi paling lembut terlebih dahulu.
  • early_stop=True (default) berhenti segera setelah anggaran token terpenuhi.
from agent_framework._compaction import (
    CharacterEstimatorTokenizer,
    SelectiveToolCallCompactionStrategy,
    SlidingWindowStrategy,
    SummarizationStrategy,
    TokenBudgetComposedStrategy,
    ToolResultCompactionStrategy,
)

tokenizer = CharacterEstimatorTokenizer()

pipeline = TokenBudgetComposedStrategy(
    token_budget=16_000,
    tokenizer=tokenizer,
    strategies=[
        ToolResultCompactionStrategy(keep_last_tool_call_groups=1),
        SummarizationStrategy(client=summarizer_client, target_count=4, threshold=2),
        SlidingWindowStrategy(keep_last_groups=20),
    ],
)

Alur ini:

  1. Menciutkan hasil perangkat lama (dengan lembut).
  2. Meringkas rentang percakapan yang lebih lama (sedang).
  3. Hanya menyimpan 20 grup terakhir (agresif).
  4. Kembali ke pengecualian terlama-pertama jika masih melebihi anggaran (backstop darurat).

Menggunakan pemadatan dengan agen

Bungkus strategi pemadatan menggunakan CompactionProvider dan daftarkan sebagai AIContextProvider. Teruskan satu strategi atau PipelineCompactionStrategy ke konstruktor.

Mendaftar dengan builder API

Daftarkan penyedia pada ChatClientBuilder menggunakan UseAIContextProviders. Penyedia layanan berjalan di dalam loop pemanggilan alat, memadatkan pesan sebelum setiap panggilan LLM.

IChatClient agentChatClient = openAIClient.GetChatClient(deploymentName).AsIChatClient();
IChatClient summarizerChatClient = openAIClient.GetChatClient(deploymentName).AsIChatClient();

PipelineCompactionStrategy compactionPipeline =
    new(
        new ToolResultCompactionStrategy(CompactionTriggers.TokensExceed(0x200)),
        new SummarizationCompactionStrategy(summarizerChatClient, CompactionTriggers.TokensExceed(0x500)),
        new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(4)),
        new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(0x8000)));

AIAgent agent =
    agentChatClient
        .AsBuilder()
        .UseAIContextProviders(new CompactionProvider(compactionPipeline))
        .BuildAIAgent(
            new ChatClientAgentOptions
            {
                Name = "ShoppingAssistant",
                ChatOptions = new()
                {
                    Instructions = "You are a helpful shopping assistant.",
                    Tools = [AIFunctionFactory.Create(LookupPrice)],
                },
            });

AgentSession session = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("What's the price of a laptop?", session));

Petunjuk / Saran

Gunakan model yang lebih kecil dan lebih murah (seperti gpt-4o-mini) untuk ringkasan klien obrolan untuk mengurangi biaya sambil mempertahankan kualitas ringkasan.

Jika hanya satu strategi yang diperlukan, teruskan langsung ke CompactionProvider tanpa membungkusnya dalam :PipelineCompactionStrategy

agentChatClient
    .AsBuilder()
    .UseAIContextProviders(new CompactionProvider(
        new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(20))))
    .BuildAIAgent(...);

Mendaftar melalui ChatClientAgentOptions

Penyedia juga dapat ditentukan langsung pada ChatClientAgentOptions.AIContextProviders:

AIAgent agent = agentChatClient
    .AsBuilder()
    .BuildAIAgent(new ChatClientAgentOptions
    {
        AIContextProviders = [new CompactionProvider(compactionPipeline)]
    });

Nota

Ketika didaftarkan melalui ChatClientAgentOptions, CompactionProvidertidak terlibat selama loop pemanggilan alat. Penyedia konteks pada tingkat agen berjalan sebelum riwayat obrolan disimpan, sehingga setiap pesan ringkasan sintetis yang dihasilkan oleh CompactionProvider dapat menjadi bagian dari riwayat yang disimpan saat menggunakan ChatHistoryProvider. Untuk memadamkan hanya konteks permintaan dalam penerbangan sambil mempertahankan riwayat asli yang disimpan, daftarkan penyedia melalui ChatClientBuilderUseAIContextProviders(...) sebagai gantinya.

Pemadatan Sementara

CompactionProvider.CompactAsync menerapkan strategi ke daftar pesan arbitrer tanpa sesi agen aktif:

IEnumerable<ChatMessage> compacted = await CompactionProvider.CompactAsync(
    new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(8000)),
    existingMessages);

CompactionProvider adalah penyedia konteks yang menerapkan strategi pemadatan sebelum dan sesudah setiap agen dijalankan. Tambahkan sebagai bagian dari penyedia riwayat dalam daftar agen context_providers.

  • before_strategy — dijalankan sebelum panggilan model, mengompres pesan yang sudah dimuat ke dalam konteks.
  • after_strategy — berjalan setelah panggilan model, memadatkan pesan yang disimpan oleh penyedia riwayat sehingga giliran berikutnya dimulai dengan ukuran yang lebih kecil.
  • history_source_id source_id— penyedia riwayat yang pesan after_strategy tersimpannya harus ringkas (default ke "in_memory").

Mendaftar dengan agen

from agent_framework import Agent, CompactionProvider, InMemoryHistoryProvider
from agent_framework._compaction import (
    CharacterEstimatorTokenizer,
    SlidingWindowStrategy,
    SummarizationStrategy,
    TokenBudgetComposedStrategy,
    ToolResultCompactionStrategy,
)

tokenizer = CharacterEstimatorTokenizer()

pipeline = TokenBudgetComposedStrategy(
    token_budget=16_000,
    tokenizer=tokenizer,
    strategies=[
        ToolResultCompactionStrategy(keep_last_tool_call_groups=1),
        SummarizationStrategy(client=summarizer_client, target_count=4, threshold=2),
        SlidingWindowStrategy(keep_last_groups=20),
    ],
)

history = InMemoryHistoryProvider()
compaction = CompactionProvider(
    before_strategy=pipeline,
    history_source_id=history.source_id,
)

agent = Agent(
    client=client,
    name="ShoppingAssistant",
    instructions="You are a helpful shopping assistant.",
    context_providers=[history, compaction],
)

session = agent.create_session()
print(await agent.run("What's the price of a laptop?", session=session))

Petunjuk / Saran

Gunakan model yang lebih kecil dan lebih murah (seperti gpt-4o-mini) untuk klien ringkasan guna mengurangi biaya sambil mempertahankan kualitas ringkasan.

Jika hanya satu strategi yang diperlukan, berikan langsung sebagai before_strategy:

compaction = CompactionProvider(
    before_strategy=SlidingWindowStrategy(keep_last_groups=20),
    history_source_id=history.source_id,
)

Memampatkan riwayat persisten setelah setiap eksekusi

Gunakan after_strategy untuk memadamkan pesan yang disimpan oleh penyedia riwayat sehingga giliran di masa mendatang dimulai dengan konteks yang dikurangi:

compaction = CompactionProvider(
    before_strategy=SlidingWindowStrategy(keep_last_groups=20),
    after_strategy=ToolResultCompactionStrategy(keep_last_tool_call_groups=1),
    history_source_id=history.source_id,
)

Pemadatan Sementara

apply_compaction menerapkan strategi ke daftar pesan arbitrer di luar sesi agen aktif:

from agent_framework._compaction import apply_compaction, TruncationStrategy, CharacterEstimatorTokenizer

tokenizer = CharacterEstimatorTokenizer()

compacted = await apply_compaction(
    messages,
    strategy=TruncationStrategy(
        max_n=8_000,
        compact_to=4_000,
        tokenizer=tokenizer,
    ),
    tokenizer=tokenizer,
)

Memilih strategi

Strategi Agresivitas Mempertahankan konteks Memerlukan LLM Paling cocok untuk
ToolResultCompactionStrategy Low Tinggi — hanya menciutkan hasil alat No Merebut kembali ruang dari output alat verbose
SummarizationCompactionStrategy Medium Sedang — mengganti riwayat dengan ringkasan Yes Percakapan panjang di mana konteks penting
SlidingWindowCompactionStrategy High Rendah — melewatkan seluruh giliran No Batas jumlah giliran ketat
TruncationCompactionStrategy High Rendah — menghapus kelompok tertua No Penyangga anggaran darurat token
PipelineCompactionStrategy Dapat dikonfigurasi Tergantung pada strategi anak Depends Pemadatan berlapis dengan beberapa opsi cadangan
Strategi Agresivitas Mempertahankan konteks Memerlukan LLM Paling cocok untuk
ToolResultCompactionStrategy Low Tinggi — meringkas hasil alat ke dalam pesan ringkasan No Merebut kembali ruang dari output alat yang berlebihan
SelectiveToolCallCompactionStrategy Rendah–Sedang Sedang — sepenuhnya mengecualikan kelompok panggilan alat lama No Menghapus riwayat alat saat hasil tidak lagi diperlukan
SummarizationStrategy Medium Sedang — mengganti riwayat dengan ringkasan Yes Percakapan panjang di mana konteks penting
SlidingWindowStrategy High Rendah — menghapus grup paling lama No Batas jumlah grup yang ketat
TruncationStrategy High Rendah — menghapus grup terlama No Pesan darurat- atau backstop anggaran token
TokenBudgetComposedStrategy Dapat dikonfigurasi Tergantung pada strategi anak Depends Pemadatan berlapis dengan tujuan pengelolaan anggaran token dan beberapa alternatif

Langkah berikutnya