Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Man mano che le conversazioni aumentano, il numero di token della cronologia delle chat può superare le finestre del contesto del modello o aumentare i costi. Le strategie di compattazione riducono le dimensioni della cronologia delle conversazioni mantenendo al tempo stesso un contesto importante, in modo che gli agenti possano continuare a funzionare con interazioni a esecuzione prolungata.
Importante
Il framework di compattazione è al momento in fase sperimentale. Per usarlo, è necessario aggiungere #pragma warning disable MAAI001.
Importante
Il framework di compattazione è attualmente sperimentale in Python. Importare strategie da agent_framework._compaction.
Perché la compattazione è importante
Ogni chiamata a un LLM include la cronologia completa della conversazione. Senza compattazione:
- Limiti dei token : le conversazioni superano infine la finestra di contesto del modello, causando errori.
- Costo : richieste più grandi usano più token, aumentando i costi dell'API.
- Latenza : più token di input indicano tempi di risposta più lenti.
La compattazione risolve questi problemi rimuovendo, comprimendo o riepilogando parti precedenti della conversazione in modo selettivo.
Concetti di base
Applicabilità: solo agenti di cronologia in memoria
La compattazione si applica solo agli agenti che gestiscono la propria cronologia delle conversazioni in memoria. Gli agenti che si basano sul contesto gestito dal servizio o sullo stato della conversazione non traggono vantaggio dalla compattazione perché il servizio gestisce già la gestione del contesto. Esempi di agenti gestiti dal servizio includono:
- Agenti Foundry — il contesto viene gestito sul lato server dal servizio Azure AI Foundry.
- API delle risposte con l'archivio abilitato (impostazione predefinita): lo stato della conversazione viene archiviato e gestito dal servizio OpenAI.
- Agenti di Copilot Studio : il contesto di conversazione viene gestito dal servizio Copilot Studio.
Per questi tipi di agente, la configurazione di una strategia di compattazione non ha alcun effetto. La compattazione è rilevante solo quando l'agente mantiene un proprio elenco di messaggi in memoria e passa la cronologia completa al modello in ogni chiamata.
La compattazione opera su un oggetto MessageIndex, ovvero una visualizzazione strutturata dell'elenco di messaggi flat che raggruppa i messaggi in unità atomiche chiamate MessageGroup istanze. Ogni gruppo tiene traccia del numero di messaggi, del numero di byte e del numero di token stimato.
Gruppi di messaggi
Un MessageGroup oggetto rappresenta messaggi correlati logicamente che devono essere mantenuti o rimossi insieme. Ad esempio, un messaggio di assistente contenente le chiamate agli strumenti e i messaggi di risultato dello strumento corrispondenti formano un gruppo atomico, rimuovendone uno senza l'altro causerebbe errori dell'API LLM.
Ogni gruppo ha un MessageGroupKind:
| Kind | Descrizione |
|---|---|
System |
Uno o più messaggi di sistema. Viene sempre mantenuta durante la compattazione. |
User |
Messaggio utente singolo che avvia un nuovo turno. |
AssistantText |
Risposta di testo di assistente normale (nessuna chiamata di strumento). |
ToolCall |
Messaggio di assistente con chiamate degli strumenti e messaggi di risultato dello strumento corrispondenti, considerati come unità atomiche. |
Summary |
Messaggio condensato prodotto dalla compattazione di sintesi. |
Attivatori
Un CompactionTrigger è un delegato che valuta se la compattazione deve continuare in base alle metriche correnti MessageIndex :
public delegate bool CompactionTrigger(MessageIndex index);
La CompactionTriggers classe fornisce metodi factory comuni:
| Attivatore | Si attiva quando |
|---|---|
CompactionTriggers.Always |
Ogni volta (incondizionatamente) |
CompactionTriggers.Never |
Mai (disabilita la compattazione). |
CompactionTriggers.TokensExceed(maxTokens) |
Il numero di token inclusi supera la soglia. |
CompactionTriggers.MessagesExceed(maxMessages) |
Il numero di messaggi inclusi supera la soglia. |
CompactionTriggers.TurnsExceed(maxTurns) |
Il conteggio incluso dei turni utente supera la soglia. |
CompactionTriggers.GroupsExceed(maxGroups) |
Il numero di gruppi inclusi supera la soglia. |
CompactionTriggers.HasToolCalls() |
Esiste almeno un gruppo di chiamate dello strumento non escluso. |
Combinare i trigger con l'operatore logico CompactionTriggers.All(...) (AND) o l'operatore logico CompactionTriggers.Any(...) (OR):
// Compact only when there are tool calls AND tokens exceed 2000
CompactionTrigger trigger = CompactionTriggers.All(
CompactionTriggers.HasToolCalls(),
CompactionTriggers.TokensExceed(2000));
Trigger e obiettivo
Ogni strategia ha due predicati:
-
Trigger : controlla l'avvio della compattazione. Se il trigger restituisce
false, la strategia viene ignorata completamente. -
Target : controlla quando si arresta la compattazione. Le strategie escludono in modo incrementale i gruppi e rivalutano l'obiettivo dopo ogni passaggio, interrompere non appena l'obiettivo ritorna
true.
Quando non viene specificata alcuna destinazione, l'impostazione predefinita è l'inversa del trigger. La compattazione si arresta non appena la condizione del trigger non viene più attivata.
La compattazione opera su un elenco semplice di Message oggetti. I messaggi vengono annotati con metadati di gruppo leggeri e le strategie modificano tali annotazioni sul posto per contrassegnare i gruppi come esclusi prima che l'elenco dei messaggi venga proiettato nel modello.
Gruppi di messaggi
I messaggi vengono raggruppati in unità atomiche. A ogni gruppo viene assegnato un oggetto GroupKind:
| Kind | Descrizione |
|---|---|
system |
Messaggi di sistema. Viene sempre mantenuta durante la compattazione. |
user |
Un singolo messaggio utente. |
assistant_text |
Risposta di testo di assistente normale (nessuna chiamata di funzione). |
tool_call |
Messaggio di assistente con chiamate di funzione più i messaggi di risultato dello strumento corrispondenti, considerati come un'unità atomica. |
Strategie di compattazione
Un CompactionStrategy è un protocollo: qualsiasi async chiamabile che accetta un oggetto list[Message] e lo modifica sul posto, restituendo True quando è cambiato qualcosa:
class CompactionStrategy(Protocol):
async def __call__(self, messages: list[Message]) -> bool: ...
Tokenizzatore
Le strategie con riconoscimento dei token accettano un'implementazione TokenizerProtocol . L'interfaccia predefinita CharacterEstimatorTokenizer usa un'euristica a 4 caratteri per token:
from agent_framework._compaction import CharacterEstimatorTokenizer
tokenizer = CharacterEstimatorTokenizer()
Utilizza un tokenizzatore personalizzato quando hai bisogno di conteggi di token accurati per la codifica di un modello specifico.
Strategie di compattazione
Tutte le strategie ereditano dalla classe base astratta CompactionStrategy . Ogni strategia mantiene i messaggi di sistema e rispetta una MinimumPreserved base che protegge i gruppi non di sistema più recenti dalla rimozione.
Le strategie di compattazione vengono importate da agent_framework._compaction.
TruncationCompactionStrategy
StrategiaTroncamento
L'approccio più semplice: rimuove i gruppi di messaggi non di sistema meno recenti fino a quando non viene soddisfatta la condizione di destinazione.
- Rispetta i confini dei gruppi atomici (i messaggi di chiamata dello strumento e quelli dei risultati vengono rimossi insieme).
- Ideale per i meccanismi di protezione del budget dei token rigidi.
- Il valore predefinito di
MinimumPreservedè32.
// Drop oldest groups when tokens exceed 32K, keeping at least 10 recent groups
TruncationCompactionStrategy truncation = new(
trigger: CompactionTriggers.TokensExceed(0x8000),
minimumPreserved: 10);
- Quando viene fornito un
tokenizer, la metrica è il numero di token; in caso contrario, viene incluso il conteggio dei messaggi. - Il valore predefinito di
preserve_systemè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
Rimuove il contenuto della conversazione meno recente per mantenere solo la finestra di scambio più recente, rispettando le unità di conversazione logiche anziché i conteggi arbitrari dei messaggi. I messaggi di sistema vengono mantenuti in tutto.
- Ideale per delimitare la lunghezza della conversazione in modo prevedibile.
Rimuove i turni dell'utente meno recenti e i relativi gruppi di risposta associati, operando sui limiti dei turni logici anziché sui singoli gruppi.
- Un turno inizia con un messaggio utente e include tutti i gruppi di assistente e chiamata agli strumenti successivi fino al messaggio utente successivo.
-
MinimumPreservedpredefinito a1(mantiene almeno il gruppo non di sistema più recente).
// Keep only the last 4 user turns
SlidingWindowCompactionStrategy slidingWindow = new(
trigger: CompactionTriggers.TurnsExceed(4));
Mantiene solo i gruppi non di sistema più recenti keep_last_groups , esclusi tutti gli elementi precedenti.
- Il valore predefinito di
preserve_systemèTrue.
from agent_framework._compaction import SlidingWindowStrategy
# Keep only the last 20 non-system groups
sliding_window = SlidingWindowStrategy(keep_last_groups=20)
ToolResultCompactionStrategy
Comprime i gruppi di chiamate a strumenti più datati in messaggi riassuntivi compatti, mantenendo una traccia leggibile senza l'overhead completo del messaggio.
- Non tocca i messaggi utente o le risposte di assistente normale.
- Ideale come strategia iniziale per recuperare spazio dai risultati dettagliati degli strumenti.
- Sostituisce i gruppi di chiamate dello strumento multi-messaggio (chiamata assistente + risultati dello strumento) con un breve riepilogo, ad esempio
[Tool calls: get_weather, search_docs]. -
MinimumPreservedè impostato su2, assicurando che le interazioni dello strumento del turno corrente rimangano visibili.
// Collapse old tool results when tokens exceed 512
ToolResultCompactionStrategy toolCompaction = new(
trigger: CompactionTriggers.TokensExceed(0x200));
- Comprime in messaggi di riepilogo compatti, ad esempio
[Tool results: get_weather: sunny, 18°C]. - I gruppi di chiamate agli strumenti più recenti
keep_last_tool_call_groupsvengono lasciati invariati.
from agent_framework._compaction import ToolResultCompactionStrategy
# Collapse all but the newest tool-call group
tool_result = ToolResultCompactionStrategy(keep_last_tool_call_groups=1)
RiepilogoCompactionStrategy
Strategia di Riepilogo
Usa un LLM per riepilogare le parti precedenti della conversazione, sostituendole con un singolo messaggio di riepilogo.
- Una richiesta predefinita mantiene i fatti chiave, le decisioni, le preferenze degli utenti e i risultati delle chiamate degli strumenti.
- Richiede un client LLM separato per il riepilogo. È consigliabile un modello più piccolo e veloce.
- Ideale per mantenere il contesto di conversazione riducendo significativamente il numero di token.
- È possibile fornire un prompt di riepilogo personalizzato.
- Protegge i messaggi di sistema e i gruppi non di sistema più recenti
MinimumPreserved(impostazione predefinita:4). - Invia i messaggi meno recenti a una destinazione separata
IChatClientcon un prompt di riepilogo, successivamente inserisce il riepilogo come gruppoMessageGroupKind.Summary.
// Summarize older messages when tokens exceed 1280, keeping the last 4 groups
SummarizationCompactionStrategy summarization = new(
chatClient: summarizerChatClient,
trigger: CompactionTriggers.TokensExceed(0x500),
minimumPreserved: 4);
È possibile fornire un prompt di riepilogo personalizzato:
SummarizationCompactionStrategy summarization = new(
chatClient: summarizerChatClient,
trigger: CompactionTriggers.TokensExceed(0x500),
summarizationPrompt: "Summarize the key decisions and user preferences only.");
- Si attiva quando il conteggio dei messaggi non di sistema incluso supera
target_count + threshold. - Mantiene i messaggi più recenti
target_count. Riepiloga tutti gli elementi precedenti. - Richiede un
SupportsChatGetResponseclient.
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,
)
Fornire un prompt di riepilogo personalizzato:
summarization = SummarizationStrategy(
client=summarizer_client,
target_count=4,
prompt="Summarize the key decisions and user preferences only.",
)
PipelineCompactionStrategy
Compone più strategie in una pipeline sequenziale. Ogni strategia opera sul risultato della precedente, consentendo la compattazione stratificata dal delicato all'aggressivo.
- Il trigger della pipeline è
CompactionTriggers.Always: ogni strategia figlia valuta il proprio trigger in modo indipendente. - Le strategie si eseguono in ordine, quindi mettere prima le strategie più delicate.
PipelineCompactionStrategy pipeline = new(
new ToolResultCompactionStrategy(CompactionTriggers.TokensExceed(0x200)),
new SummarizationCompactionStrategy(summarizerChatClient, CompactionTriggers.TokensExceed(0x500)),
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(4)),
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(0x8000)));
Questa pipeline:
- Comprime i risultati dei vecchi strumenti (delicato).
- Riepiloga gli intervalli di conversazione meno recenti (moderata).
- Mantiene solo gli ultimi 4 turni utente (aggressivi).
- Elimina i gruppi meno recenti se ancora oltre il budget (backstop di emergenza).
Strategia di Compattazione delle Chiamate di Strumenti Selettivi
Esclude i gruppi di chiamate agli strumenti meno recenti completamente, conservando solo l'ultimo oggetto keep_last_tool_call_groups.
- Non tocca i messaggi utente o assistente normale.
- Meglio quando lo strumento chatter domina l'utilizzo dei token e la cronologia completa degli strumenti non è necessaria.
from agent_framework._compaction import SelectiveToolCallCompactionStrategy
# Keep only the most recent tool-call group
selective_tool = SelectiveToolCallCompactionStrategy(keep_last_tool_call_groups=1)
TokenBudgetComposedStrategy
Compone più strategie in una pipeline sequenziale basata su un budget di token. Ogni strategia figlia viene eseguita in ordine, interrompendosi anticipatamente una volta soddisfatto il budget. Un meccanismo di fallback incorporato esclude i gruppi meno recenti se le strategie da sole non riescono a raggiungere l'obiettivo.
- Eseguire le strategie in ordine; posizionare prima le strategie più lievi.
-
early_stop=True(impostazione predefinita) si arresta non appena viene soddisfatto il budget dei token.
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),
],
)
Questa pipeline:
- Comprime i risultati dei vecchi strumenti (in modo graduale).
- Riepiloga gli intervalli di conversazione meno recenti (moderata).
- Mantiene solo gli ultimi 20 gruppi (aggressivi).
- Torna all'esclusione meno recente se ancora oltre il budget (backstop di emergenza).
Uso della compattazione con un agente
Incapsulare una strategia di compattazione in un CompactionProvider e registrarla come AIContextProvider. Passa una singola strategia o un PipelineCompactionStrategy al costruttore.
Registrazione con l'API del generatore
Registrare il fornitore nell'oggetto ChatClientBuilder utilizzando UseAIContextProviders. Il provider viene eseguito all'interno del ciclo di chiamata degli strumenti, compattando i messaggi prima di ogni chiamata 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));
Suggerimento
Usare un modello più piccolo e più economico (ad esempio gpt-4o-mini) per il client di chat di riepilogo per ridurre i costi mantenendo al tempo stesso la qualità di riepilogo.
Se è necessaria una sola strategia, passarla direttamente a CompactionProvider senza inserirla in un oggetto PipelineCompactionStrategy.
agentChatClient
.AsBuilder()
.UseAIContextProviders(new CompactionProvider(
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(20))))
.BuildAIAgent(...);
Registrazione tramite ChatClientAgentOptions
Il provider può anche essere specificato direttamente in ChatClientAgentOptions.AIContextProviders:
AIAgent agent = agentChatClient
.AsBuilder()
.BuildAIAgent(new ChatClientAgentOptions
{
AIContextProviders = [new CompactionProvider(compactionPipeline)]
});
Annotazioni
Se registrato tramite ChatClientAgentOptions, CompactionProvider non viene attivato durante il ciclo di chiamata degli strumenti. I provider di contesto a livello di agente vengono eseguiti prima dell'archiviazione della cronologia delle chat, quindi qualsiasi messaggio di riepilogo sintetico prodotto da CompactionProvider può diventare parte della cronologia persistente quando si usa ChatHistoryProvider. Per compattare solo il contesto della richiesta in transito preservando la cronologia originale archiviata, registrare invece il provider su ChatClientBuilder tramite UseAIContextProviders(...).
Compattazione ad hoc
CompactionProvider.CompactAsync applica una strategia a un elenco di messaggi arbitrari senza una sessione agente attiva:
IEnumerable<ChatMessage> compacted = await CompactionProvider.CompactAsync(
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(8000)),
existingMessages);
CompactionProvider è un provider di contesto che applica strategie di compattazione prima e dopo l'esecuzione di ogni agente. Aggiungerlo insieme a un provider di cronologia nell'elenco dell'agente context_providers .
-
before_strategy: viene eseguito prima della chiamata del modello, compattando i messaggi già caricati nel contesto. -
after_strategy: viene eseguito dopo la chiamata al modello, compattando i messaggi archiviati dal fornitore di cronologia in modo che il turno successivo risulti più piccolo. -
history_source_id— il fornitore della cronologia i cui messaggi archiviatiafter_strategydevono essere compattati (valore predefinito"in_memory").
Registrazione con un agente
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))
Suggerimento
Usare un modello più piccolo e più economico (ad esempio gpt-4o-mini) per il client di riepilogo per ridurre i costi mantenendo al tempo stesso la qualità di riepilogo.
Se è necessaria una sola strategia, passarla direttamente come before_strategy:
compaction = CompactionProvider(
before_strategy=SlidingWindowStrategy(keep_last_groups=20),
history_source_id=history.source_id,
)
Compattazione della cronologia persistente dopo ogni esecuzione
Usare after_strategy per compattare i messaggi archiviati dal provider di cronologia in modo che i turni futuri inizino con un contesto ridotto:
compaction = CompactionProvider(
before_strategy=SlidingWindowStrategy(keep_last_groups=20),
after_strategy=ToolResultCompactionStrategy(keep_last_tool_call_groups=1),
history_source_id=history.source_id,
)
Compattazione ad hoc
apply_compaction applica una strategia a un elenco di messaggi arbitrari all'esterno di una sessione dell'agente attivo:
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,
)
Scelta di una strategia
| Strategia | Aggressività | Mantiene il contesto | Richiede LLM | Ideale per |
|---|---|---|---|---|
ToolResultCompactionStrategy |
Low | Alto: comprime solo i risultati degli strumenti | No | Riappropriazione di spazio dall'output eccessivo dello strumento |
SummarizationCompactionStrategy |
Medium | Medium : sostituisce la cronologia con un riepilogo | Sì | Conversazioni lunghe in cui il contesto è importante |
SlidingWindowCompactionStrategy |
Alto | Basso : elimina interi turni | No | Limiti di conteggio dei turni rigidi |
TruncationCompactionStrategy |
Alto | Basso: elimina i gruppi meno recenti | No | Dispositivo di sicurezza per la riserva di token d'emergenza |
PipelineCompactionStrategy |
Configurable | Dipende dalle strategie dei figli | Dipende da | Compattazione stratificata con più opzioni di fallback |
| Strategia | Aggressività | Mantiene il contesto | Richiede LLM | Ideale per |
|---|---|---|---|---|
ToolResultCompactionStrategy |
Low | Alto: comprime i risultati degli strumenti in messaggi di riepilogo | No | Recupero di spazio dall'output prolisso dello strumento |
SelectiveToolCallCompactionStrategy |
Basso-Medio | Medio: esclude completamente i gruppi di chiamata degli strumenti precedenti | No | Rimozione della cronologia degli strumenti quando i risultati non sono più necessari |
SummarizationStrategy |
Medium | Medium : sostituisce la cronologia con un riepilogo | Sì | Conversazioni lunghe in cui il contesto è importante |
SlidingWindowStrategy |
Alto | Basso - elimina i gruppi più vecchi | No | Limiti di conteggio dei gruppi rigidi |
TruncationStrategy |
Alto | Basso - elimina i gruppi più vecchi | No | Backstop del budget di token o messaggi di emergenza |
TokenBudgetComposedStrategy |
Configurable | Dipende dalle strategie figlie | Dipende da | Compattazione a più livelli con un obiettivo di budget di token e diversi fallback |