Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
À medida que as conversas crescem, a contagem de tokens do histórico de chat pode exceder as janelas de contexto do modelo ou aumentar os custos. As estratégias de compactação reduzem o tamanho do histórico de conversas, preservando o contexto importante, para que os agentes possam continuar funcionando em interações de longa execução.
Importante
A estrutura de compactação é atualmente experimental. Para usá-lo, você precisará adicionar #pragma warning disable MAAI001.
Importante
A estrutura de compactação atualmente é experimental no Python. Importar estratégias de agent_framework._compaction.
Por que a compactação importa
Cada chamada para uma LLM inclui o histórico completo da conversa. Sem compactação:
- Limites de token — as conversas eventualmente excedem a janela de contexto do modelo, causando erros.
- Custo – prompts maiores consomem mais tokens, aumentando os custos da API.
- Latência – mais tokens de entrada significa tempos de resposta mais lentos.
A compactação resolve esses problemas removendo, colapsando ou resumindo seletivamente partes mais antigas da conversa.
Conceitos principais
Aplicação: apenas para agentes de histórico em memória
A compactação se aplica somente a agentes que gerenciam seu próprio histórico de conversas na memória. Os agentes que dependem do contexto gerenciado pelo serviço ou do estado de conversa não se beneficiam da compactação porque o serviço já lida com o gerenciamento de contexto. Exemplos de agentes gerenciados pelo serviço incluem:
- Foundry Agents — o contexto é gerenciado do lado do servidor pelo serviço Azure AI Foundry.
- API de respostas com o repositório habilitado (o padrão) – o estado da conversa é armazenado e gerenciado pelo serviço OpenAI.
- Agentes do Copilot Studio – o contexto de conversa é mantido pelo serviço Copilot Studio.
Para esses tipos de agente, a configuração de uma estratégia de compactação não tem efeito. A compactação só é relevante quando o agente mantém sua própria lista de mensagens na memória e passa o histórico completo para o modelo em cada chamada.
A compactação opera em uma MessageIndex exibição estruturada da lista de mensagens simples que agrupa mensagens em unidades atômicas chamadas MessageGroup instâncias. Cada grupo controla sua contagem de mensagens, contagem de bytes e contagem de tokens estimada.
Grupos de mensagens
Um MessageGroup representa mensagens logicamente relacionadas que devem ser mantidas ou removidas juntas. Por exemplo, uma mensagem de assistente que contém chamadas de ferramenta e suas mensagens de resultado de ferramenta correspondentes formam um grupo atômico, e remover uma sem a outra causaria erros de API LLM.
Cada grupo tem um MessageGroupKind:
| Variante | Descrição |
|---|---|
System |
Uma ou mais mensagens do sistema. Sempre preservados durante a compactação. |
User |
Uma única mensagem de usuário que inicia um novo turno. |
AssistantText |
Uma resposta de texto de assistente sem formatação (nenhuma chamada de ferramenta). |
ToolCall |
Uma mensagem de assistente com chamadas de ferramenta e as mensagens de resultado da ferramenta correspondentes, tratadas como uma unidade atômica. |
Summary |
Uma mensagem condensada produzida pela compactação de resumo. |
Gatilhos
Um CompactionTrigger é um delegado que avalia se a compactação deve continuar com base nas métricas atuais MessageIndex :
public delegate bool CompactionTrigger(MessageIndex index);
A CompactionTriggers classe fornece métodos comuns de fábrica:
| Disparador | Acionado quando |
|---|---|
CompactionTriggers.Always |
Todas as vezes (incondicionalmente). |
CompactionTriggers.Never |
Nunca (desabilita a compactação). |
CompactionTriggers.TokensExceed(maxTokens) |
A contagem de tokens incluída excede o limite. |
CompactionTriggers.MessagesExceed(maxMessages) |
A contagem de mensagens incluídas excede o limite. |
CompactionTriggers.TurnsExceed(maxTurns) |
A contagem de turnos de usuário incluída excede o limite. |
CompactionTriggers.GroupsExceed(maxGroups) |
A contagem de grupos já incluídos excede o limite máximo. |
CompactionTriggers.HasToolCalls() |
Existe pelo menos um grupo de chamadas de ferramentas não excluído. |
Combinar gatilhos com CompactionTriggers.All(...) (AND lógico) ou CompactionTriggers.Any(...) (OR lógico):
// Compact only when there are tool calls AND tokens exceed 2000
CompactionTrigger trigger = CompactionTriggers.All(
CompactionTriggers.HasToolCalls(),
CompactionTriggers.TokensExceed(2000));
Gatilho versus alvo
Cada estratégia tem dois predicados:
-
Gatilho – Controla quando a compactação começa. Se o gatilho retornar
false, a estratégia será totalmente ignorada. -
Destino – Controla quando a compactação é interrompida. As estratégias excluem incrementalmente grupos e reavaliam o alvo após cada etapa, parando assim que o alvo retornar
true.
Quando nenhum destino é especificado, ele usa como padrão o inverso do gatilho – a compactação é interrompida assim que a condição de gatilho não é mais disparada.
A compactação opera em uma lista simples de Message objetos. As mensagens são anotadas com metadados de grupo leves e as estratégias modificam essas anotações em vigor para marcar grupos como excluídos antes que a lista de mensagens seja projetada para o modelo.
Grupos de mensagens
As mensagens são agrupadas em unidades atômicas. Cada grupo recebe um GroupKind:
| Variante | Descrição |
|---|---|
system |
Mensagens do sistema. Sempre preservado durante a compactação. |
user |
Uma única mensagem de usuário. |
assistant_text |
Uma resposta de texto simplificada de um assistente, sem chamadas de função. |
tool_call |
Uma mensagem de assistente com chamadas de função mais as mensagens de resultado da ferramenta correspondente, tratadas como uma unidade atômica. |
Estratégias de compactação
Um CompactionStrategy é um protocolo - qualquer async chamável que aceite um list[Message] e o altere no local, retornando True quando tenha mudado qualquer coisa:
class CompactionStrategy(Protocol):
async def __call__(self, messages: list[Message]) -> bool: ...
Gerador de token
Estratégias com reconhecimento de tokens aceitam uma TokenizerProtocol implementação. O interno CharacterEstimatorTokenizer usa uma heurística de 4 caracteres por token:
from agent_framework._compaction import CharacterEstimatorTokenizer
tokenizer = CharacterEstimatorTokenizer()
Passe um tokenizador personalizado quando for necessário obter contagens precisas de tokens para a codificação de um modelo específico.
Estratégias de compactação
Todas as estratégias herdam da classe base abstrata CompactionStrategy . Cada estratégia preserva as mensagens do sistema e mantém uma base MinimumPreserved que protege os grupos não-sistêmicos mais recentes contra remoção.
As estratégias de compressão são importadas de agent_framework._compaction.
TruncationCompactionStrategy
TruncationStrategy (EstratégiaDeTruncamento)
A abordagem mais simples: remove os grupos de mensagens mais antigos que não sejam do sistema até que a condição de destino seja atendida.
- Respeita os limites dos grupos atômicos (as mensagens de chamada e os resultados da ferramenta são removidos juntos).
- Melhor para backstops de orçamento de token rígido.
-
MinimumPreservedusa como padrão32.
// Drop oldest groups when tokens exceed 32K, keeping at least 10 recent groups
TruncationCompactionStrategy truncation = new(
trigger: CompactionTriggers.TokensExceed(0x8000),
minimumPreserved: 10);
- Quando uma
tokenizeré fornecida, a métrica é a contagem de tokens; caso contrário, ela está incluída na contagem de mensagens. -
preserve_systemusa como padrãoTrue.
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(),
)
Estratégia de Compactação Janela Deslizante
Estratégia de Janela Deslizante
Remove o conteúdo da conversa mais antigo para manter apenas a janela mais recente de trocas, respeitando unidades de conversa lógica em vez de contagens arbitrárias de mensagens. As mensagens do sistema são preservadas em todo o mundo.
- Melhor para controlar o comprimento da conversa de forma previsível.
Remove os turnos de usuário mais antigos e seus grupos de resposta associados, operando em limites lógicos de turnos em vez de em grupos individuais.
- Um turno começa com uma mensagem do usuário e inclui todos os grupos de assistente e chamadas de ferramenta subsequentes até a próxima mensagem do usuário.
-
MinimumPreservedé definido como1(preserva, pelo menos, o grupo não-sistema mais recente).
// Keep only the last 4 user turns
SlidingWindowCompactionStrategy slidingWindow = new(
trigger: CompactionTriggers.TurnsExceed(4));
Mantém apenas os grupos não-sistema mais recentes keep_last_groups , excluindo tudo o que é mais antigo.
-
preserve_systemusa como padrãoTrue.
from agent_framework._compaction import SlidingWindowStrategy
# Keep only the last 20 non-system groups
sliding_window = SlidingWindowStrategy(keep_last_groups=20)
Estratégia de Compactação de Resultados da Ferramenta
Recolhe grupos de chamadas de ferramentas mais antigos em mensagens de resumo compactas, preservando um rastreamento legível sem a sobrecarga completa da mensagem.
- Não toca em mensagens do usuário ou respostas diretas de assistente.
- Melhor como uma estratégia inicial para recuperar espaço dos resultados excessivamente detalhados da ferramenta.
- Substitui grupos de chamadas de ferramentas que envolvem várias mensagens (incluindo chamada de assistente e resultados da ferramenta) por um resumo conciso, como
[Tool calls: get_weather, search_docs]. - O padrão do
MinimumPreservedé2, garantindo que as interações de ferramenta do turno atual permaneçam visíveis.
// Collapse old tool results when tokens exceed 512
ToolResultCompactionStrategy toolCompaction = new(
trigger: CompactionTriggers.TokensExceed(0x200));
- Colapse em mensagens de resumo compactas, como
[Tool results: get_weather: sunny, 18°C]. - Os grupos de chamadas de ferramentas mais recentes
keep_last_tool_call_groupspermanecem inalterados.
from agent_framework._compaction import ToolResultCompactionStrategy
# Collapse all but the newest tool-call group
tool_result = ToolResultCompactionStrategy(keep_last_tool_call_groups=1)
SummarizationCompactionStrategy
Estratégia de Resumir
Usa uma LLM para resumir partes mais antigas da conversa, substituindo-as por uma única mensagem de resumo.
- Um prompt padrão preserva os principais fatos, decisões, preferências do usuário e resultados de chamadas de ferramenta.
- Requer um cliente LLM separado para resumo – é recomendável um modelo menor e mais rápido.
- Melhor para preservar o contexto de conversa e reduzir significativamente a contagem de tokens.
- Você pode fornecer um prompt de resumo personalizado.
- Protege as mensagens do sistema e os grupos não-sistema mais recentes
MinimumPreserved(padrão:4). - Envia as mensagens mais antigas para um local separado
IChatClientcom um prompt de resumo e, em seguida, insere o resumo comoMessageGroupKind.Summarygrupo.
// Summarize older messages when tokens exceed 1280, keeping the last 4 groups
SummarizationCompactionStrategy summarization = new(
chatClient: summarizerChatClient,
trigger: CompactionTriggers.TokensExceed(0x500),
minimumPreserved: 4);
Você pode fornecer um prompt de resumo personalizado:
SummarizationCompactionStrategy summarization = new(
chatClient: summarizerChatClient,
trigger: CompactionTriggers.TokensExceed(0x500),
summarizationPrompt: "Summarize the key decisions and user preferences only.");
- Dispara quando a contagem de mensagens não sistêmicas incluídas excede
target_count + threshold. - Retém as mensagens mais recentes
target_count; resume tudo que é mais antigo. - Requer um
SupportsChatGetResponsecliente.
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,
)
Forneça um prompt de resumo personalizado:
summarization = SummarizationStrategy(
client=summarizer_client,
target_count=4,
prompt="Summarize the key decisions and user preferences only.",
)
PipelineCompactionStrategy
Compõe várias estratégias em um pipeline sequencial. Cada estratégia opera com base no resultado da anterior, permitindo uma compactação em camadas que vai de leve a agressiva.
- O próprio gatilho do pipeline é
CompactionTriggers.Always, cada estratégia filha avalia seu próprio gatilho de forma independente. - As estratégias são executadas em ordem, portanto, coloque as estratégias mais suaves em primeiro lugar.
PipelineCompactionStrategy pipeline = new(
new ToolResultCompactionStrategy(CompactionTriggers.TokensExceed(0x200)),
new SummarizationCompactionStrategy(summarizerChatClient, CompactionTriggers.TokensExceed(0x500)),
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(4)),
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(0x8000)));
Este pipeline (fluxo de processo):
- Recolhe resultados antigos da ferramenta (com delicadeza).
- Resume intervalos de conversa mais antigos (moderado).
- Mantém apenas as últimas 4 voltas de usuário (agressivas).
- Descarta os grupos mais antigos se ainda estiver acima do orçamento (backstop de emergência).
SelectiveToolCallCompactionStrategy
Exclui totalmente grupos de chamadas de ferramentas mais antigos, mantendo apenas o último keep_last_tool_call_groups.
- Não toca mensagens de usuário ou mensagens de assistente simples.
- Melhor quando as conversas de ferramentas dominam o uso de token e o histórico completo de ferramentas não é necessário.
from agent_framework._compaction import SelectiveToolCallCompactionStrategy
# Keep only the most recent tool-call group
selective_tool = SelectiveToolCallCompactionStrategy(keep_last_tool_call_groups=1)
TokenBudgetComposedStrategy
Compõe várias estratégias em um pipeline sequencial impulsionado por um orçamento de tokens. Cada estratégia filial é executada em ordem, parando mais cedo quando o orçamento for atendido. Um recurso interno de reserva exclui os grupos mais antigos se as estratégias por si só não puderem atingir o destino.
- As estratégias devem ser executadas em ordem; coloque primeiro as estratégias menos agressivas.
-
early_stop=True(o padrão) para assim que o limite de tokens é atingido.
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),
],
)
Este processo:
- Recolhe resultados antigos da ferramenta de forma suave.
- Resume intervalos de conversa mais antigos (moderado).
- Mantém apenas os últimos 20 grupos (agressivos).
- Volta à exclusão mais antiga se ainda estiver acima do orçamento (backstop de emergência).
Usando compactação com um agente
Encapsular uma estratégia de compactação em uma CompactionProvider e registrá-la como um AIContextProvider. Passe uma única estratégia ou um PipelineCompactionStrategy ao construtor.
Registrando-se com a API do construtor
Registre o provedor no ChatClientBuilder usando UseAIContextProviders. O provedor é executado dentro do loop de chamada da ferramenta, compactando mensagens antes de cada chamada ao 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));
Dica
Use um modelo menor e mais barato (como gpt-4o-mini) para o cliente de chat de resumo para reduzir os custos, mantendo a qualidade resumida.
Se apenas uma estratégia for necessária, passe-a diretamente para CompactionProvider sem envolvê-la em um PipelineCompactionStrategy.
agentChatClient
.AsBuilder()
.UseAIContextProviders(new CompactionProvider(
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(20))))
.BuildAIAgent(...);
Registrando-se por meio ChatClientAgentOptions
O provedor também pode ser especificado diretamente em ChatClientAgentOptions.AIContextProviders:
AIAgent agent = agentChatClient
.AsBuilder()
.BuildAIAgent(new ChatClientAgentOptions
{
AIContextProviders = [new CompactionProvider(compactionPipeline)]
});
Observação
Quando registrado por meio de ChatClientAgentOptions, o CompactionProvidernão é ativado durante o loop de chamada de ferramentas. Os provedores de contexto no nível do agente são executados antes que o histórico de chat seja armazenado; portanto, quaisquer mensagens de resumo sintéticas produzidas por CompactionProvider podem se tornar parte do histórico persistente ao usar ChatHistoryProvider. Para compactar apenas o contexto de solicitação em andamento, preservando o histórico armazenado original, registre o provedor no ChatClientBuilder usando UseAIContextProviders(...).
Compactação ad hoc
CompactionProvider.CompactAsync aplica uma estratégia a uma lista de mensagens arbitrárias sem uma sessão de agente ativo:
IEnumerable<ChatMessage> compacted = await CompactionProvider.CompactAsync(
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(8000)),
existingMessages);
CompactionProvider é um provedor de contexto que aplica estratégias de compactação antes e depois da execução de cada agente. Adicione-o juntamente com um provedor de histórico na lista do agente context_providers.
-
before_strategy— é executado antes da chamada de modelo, compactando mensagens já carregadas no contexto. -
after_strategy— é executado após a chamada do modelo, compactando as mensagens armazenadas pelo provedor de histórico para que a próxima interação comece de forma mais compacta. -
history_source_id— osource_idprovedor de histórico cujas mensagensafter_strategyarmazenadas devem ser compactadas (o padrão é"in_memory").
Registrando-se com um 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))
Dica
Use um modelo menor e mais barato (como gpt-4o-mini) para o cliente de resumo para reduzir os custos, mantendo a qualidade resumida.
Se apenas uma estratégia for necessária, passe-a diretamente como before_strategy:
compaction = CompactionProvider(
before_strategy=SlidingWindowStrategy(keep_last_groups=20),
history_source_id=history.source_id,
)
Compactação do histórico persistente após cada execução
Use after_strategy para compactar as mensagens armazenadas pelo provedor de histórico para que as voltas futuras comecem com um contexto reduzido:
compaction = CompactionProvider(
before_strategy=SlidingWindowStrategy(keep_last_groups=20),
after_strategy=ToolResultCompactionStrategy(keep_last_tool_call_groups=1),
history_source_id=history.source_id,
)
Compactação ad hoc
apply_compaction aplica uma estratégia a uma lista de mensagens arbitrária fora de uma sessão de agente ativo:
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,
)
Escolhendo uma estratégia
| Estratégia | Agressividade | Preserva o contexto | Requer Modelo de Linguagem (LLM) | Mais adequado para |
|---|---|---|---|---|
ToolResultCompactionStrategy |
Baixo | Alta – recolhe apenas os resultados da ferramenta | No | Recuperando espaço da saída verbosa da ferramenta |
SummarizationCompactionStrategy |
Medium | Médio – substitui o histórico por um resumo | Sim | Conversas longas em que o contexto importa |
SlidingWindowCompactionStrategy |
Alto | Baixo – descarta turnos inteiros | No | Limites de contagem de turnos rígidos |
TruncationCompactionStrategy |
Alto | Baixo – descarta grupos mais antigos | No | Sustentação de orçamento de tokens de emergência |
PipelineCompactionStrategy |
Configurable | Depende de estratégias filho | Depende | Compactação em camadas com várias alternativas |
| Estratégia | Agressividade | Preserva o contexto | Requer LLM | Mais adequado para |
|---|---|---|---|---|
ToolResultCompactionStrategy |
Baixo | Nível alto — compacta os resultados da ferramenta em mensagens resumidas | No | Recuperação de espaço da saída detalhada da ferramenta |
SelectiveToolCallCompactionStrategy |
Baixo–Médio | Médio – exclui totalmente grupos de chamadas de ferramentas antigos | No | Removendo o histórico de ferramentas quando os resultados não são mais necessários |
SummarizationStrategy |
Medium | Médio – substitui o histórico por um resumo | Sim | Conversas longas em que o contexto importa |
SlidingWindowStrategy |
Alto | Baixo – descarta grupos mais antigos | No | Rígidos limites de contagem de grupos |
TruncationStrategy |
Alto | Baixo – descarta grupos mais antigos | No | Mecanismos de proteção de mensagens de emergência ou de limite de token |
TokenBudgetComposedStrategy |
Configurable | Depende de estratégias filho | Depende | Compactação em camadas com uma meta de orçamento de tokens e várias alternativas |
Próximas Etapas
Armazenamento