Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
À medida que as conversas crescem, o número de tokens no histórico de conversas 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 enquanto preservam contexto importante, para que os agentes possam continuar a funcionar em interações de longa duração.
Importante
O quadro de compactação é atualmente experimental. Para usá-lo, você precisará adicionar #pragma warning disable MAAI001.
Importante
O framework de compactação está atualmente experimental em Python. Importar estratégias de agent_framework._compaction.
Por que a compactação é importante
Cada chamada para um LLM inclui o histórico completo de conversas. Sem compactação:
- Limites de tokens — As conversas acabam por ultrapassar 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 significam tempos de resposta mais lentos.
A compactação resolve estes problemas ao remover, comprimir ou resumir partes antigas da conversa de forma seletiva.
Conceitos-chave
Aplicabilidade: Apenas agentes de histórico em memória
A compactação aplica-se apenas a agentes que gerem o seu próprio histórico de conversas em memória. Agentes que dependem do contexto gerido pelo serviço ou do estado da conversação não beneficiam da compactação porque o serviço já faz a gestão do contexto. Exemplos de agentes de gestão de serviços incluem:
- Foundry Agents — o contexto é gerido do lado do servidor pelo serviço Azure AI Foundry.
- API de Respostas com a memória ativada (o padrão) — o estado da conversa é armazenado e gerido pelo serviço OpenAI.
- Agentes do Copilot Studio — o contexto da conversa é mantido pelo serviço Copilot Studio.
Para estes tipos de agentes, configurar uma estratégia de compactação não tem efeito. A compactação só é relevante quando o agente mantém a sua própria lista de mensagens em memória e passa o histórico completo ao modelo em cada chamada.
A compactação opera com base numa MessageIndex — uma visão estruturada da lista plana de mensagens que agrupa as mensagens em unidades atómicas chamadas MessageGroup instâncias. Cada grupo regista a sua contagem de mensagens, número de bytes e estimativa de tokens.
Grupos de mensagens
A MessageGroup representa mensagens logicamente relacionadas que devem ser mantidas ou removidas juntas. Por exemplo, uma mensagem de assistente contendo chamadas de ferramenta e as correspondentes mensagens de resultado de ferramenta formam um grupo atómico — remover uma sem a outra causaria erros na API do LLM.
Cada grupo tem um MessageGroupKind:
| Variante | Descrição |
|---|---|
System |
Uma ou mais mensagens do sistema. Sempre preservado durante a compactação. |
User |
Uma mensagem de um único utilizador que inicia um novo turno. |
AssistantText |
Uma resposta simples de texto do assistente (sem chamadas de ferramentas). |
ToolCall |
Uma mensagem assistente com chamadas de ferramenta e as correspondentes mensagens de resultado de ferramenta, tratadas como uma unidade atómica. |
Summary |
Uma mensagem condensada produzida por compactação de resumo. |
Acionadores
A CompactionTrigger é um delegado que avalia se a compactação deve prosseguir com base nas métricas atuais MessageIndex:
public delegate bool CompactionTrigger(MessageIndex index);
A CompactionTriggers classe fornece métodos comuns de fábrica:
| Trigger | Incêndios quando |
|---|---|
CompactionTriggers.Always |
Sempre (incondicionalmente). |
CompactionTriggers.Never |
Nunca (desativa a compactação). |
CompactionTriggers.TokensExceed(maxTokens) |
O número de tokens incluídos excede o limiar. |
CompactionTriggers.MessagesExceed(maxMessages) |
O número de mensagens incluídas excede o limiar. |
CompactionTriggers.TurnsExceed(maxTurns) |
O contador de turnos do usuário incluído excede o limiar. |
CompactionTriggers.GroupsExceed(maxGroups) |
A contagem dos grupos incluídos excede o limite. |
CompactionTriggers.HasToolCalls() |
Existe pelo menos um grupo de chamada de ferramenta 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 vs. alvo
Cada estratégia tem dois predicados:
-
Trigger — Controla quando a compactação começa. Se o gatilho devolver
false, a estratégia é completamente ignorada. -
Alvo — Controla quando a compactação para. As estratégias excluem de forma incremental grupos e reavaliam o alvo após cada etapa, parando assim que o alvo retorna
true.
Quando nenhum destino é especificado, por padrão passa para o oposto do gatilho — a compactação para assim que a condição do gatilho já não se aplica.
A compactação opera numa lista plana de Message objetos. As mensagens são anotadas com metadados leves de grupo, e as estratégias alteram essas anotações para marcar grupos como excluídos antes de a lista de mensagens ser projetada para o modelo.
Grupos de mensagens
As mensagens são agrupadas em unidades atómicas. Cada grupo é atribuído a um GroupKind:
| Variante | Descrição |
|---|---|
system |
Mensagens do sistema. É sempre preservado durante a compactação. |
user |
Uma única mensagem de utilizador. |
assistant_text |
Uma resposta de texto simples do assistente (sem chamadas de função). |
tool_call |
Uma mensagem assistente com chamadas de função mais as correspondentes mensagens de resultado da ferramenta, tratada como uma unidade atómica. |
Estratégias de compactação
A CompactionStrategy é um protocolo — qualquer async chamável que aceite a list[Message] e o mute no lugar, regressando True quando alterou algo:
class CompactionStrategy(Protocol):
async def __call__(self, messages: list[Message]) -> bool: ...
Tokenizador
Estratégias sensíveis a tokens aceitam uma implementação TokenizerProtocol. O integrado CharacterEstimatorTokenizer utiliza uma heurística de 4 caracteres por token:
from agent_framework._compaction import CharacterEstimatorTokenizer
tokenizer = CharacterEstimatorTokenizer()
Passe um tokenizador personalizado quando precisar de 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 respeita um MinimumPreserved piso que protege da remoção os grupos mais recentes não-sistémicos.
As estratégias de compactação são importadas de agent_framework._compaction.
Estratégia de Truncamento e Compactação
Estratégia de Truncação
A abordagem mais direta: remove os grupos de mensagens não do sistema mais antigos até que a condição alvo seja cumprida.
- Respeita os limites dos grupos atómicos (as mensagens de chamada e resultado da ferramenta são removidas em conjunto).
- Ideal para backstops com orçamento de tokens rígido.
-
MinimumPreservedassume 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 um
tokenizeré fornecido, a métrica é a contagem de tokens; caso contrário, a métrica é a contagem de mensagens. -
preserve_systemassume 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 conteúdos de conversa mais antigos para manter apenas a janela mais recente de trocas, respeitando unidades lógicas de conversa em vez de contagens arbitrárias de mensagens. As mensagens do sistema são preservadas ao longo de todo o processo.
- Ideal para limitar a duração das conversas de forma previsível.
Remove os turnos de utilizador mais antigos e os seus grupos de resposta associados, operando sobre limites lógicos de turnos em vez de grupos individuais.
- Um turno começa com uma mensagem de utilizador e inclui todos os grupos subsequentes de assistentes e chamadas de ferramenta até à próxima mensagem do utilizador.
-
MinimumPreservedpor defeito, (1preserva 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-se apenas os grupos mais recentes keep_last_groups que não são do sistema, excluindo tudo o que é mais antigo.
-
preserve_systemassume como padrãoTrue.
from agent_framework._compaction import SlidingWindowStrategy
# Keep only the last 20 non-system groups
sliding_window = SlidingWindowStrategy(keep_last_groups=20)
ToolResultCompactaçãoEstratégia
Colapsa grupos de chamadas de ferramentas mais antigos em mensagens resumidas compactas, preservando um rastreio legível sem a sobrecarga total da mensagem.
- Não mexe nas mensagens dos utilizadores nem nas respostas simples do assistente.
- Melhor como estratégia inicial para recuperar espaço dos resultados verbosos das ferramentas.
- Substitui grupos de chamadas de ferramentas com múltiplas mensagens (chamada assistente + resultados da ferramenta) por um resumo curto como
[Tool calls: get_weather, search_docs]. -
MinimumPreservedconfigura-se por padrão para2, garantindo que as interações da ferramenta no turno atual permaneçam visíveis.
// Collapse old tool results when tokens exceed 512
ToolResultCompactionStrategy toolCompaction = new(
trigger: CompactionTriggers.TokensExceed(0x200));
- Colapsa em mensagens resumidas compactas como
[Tool results: get_weather: sunny, 18°C]. - Os grupos de chamadas de ferramentas mais recentes
keep_last_tool_call_groupspermanecem intocados.
from agent_framework._compaction import ToolResultCompactionStrategy
# Collapse all but the newest tool-call group
tool_result = ToolResultCompactionStrategy(keep_last_tool_call_groups=1)
Estratégia de Compactação por Resumo
Estratégia de Sumarização
Utiliza um LLM para resumir partes antigas da conversa, substituindo-as por uma única mensagem de resumo.
- Um prompt padrão preserva factos-chave, decisões, preferências do utilizador e resultados das chamadas de ferramenta.
- Requer um cliente LLM separado para sumarização — recomenda-se um modelo mais pequeno e rápido.
- Ideal para preservar o contexto conversacional enquanto reduz significativamente o número de tokens.
- Pode fornecer um prompt de resumo personalizado.
- Protege as mensagens do sistema e os grupos mais recentes que não são de sistema
MinimumPreserved(por defeito:4). - Envia as mensagens mais antigas para uma localização separada
IChatClientcom um prompt de resumo, depois insere o resumo como um grupoMessageGroupKind.Summary.
// Summarize older messages when tokens exceed 1280, keeping the last 4 groups
SummarizationCompactionStrategy summarization = new(
chatClient: summarizerChatClient,
trigger: CompactionTriggers.TokensExceed(0x500),
minimumPreserved: 4);
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.");
- Os disparadores ativam-se quando a contagem de mensagens não do sistema incluídas excede
target_count + threshold. - Mantém as mensagens mais
target_countrecentes; resume tudo o que é 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.",
)
Estratégia de Compactação de Pipeline
Compõe múltiplas estratégias num pipeline sequencial. Cada estratégia funciona com base no resultado da anterior, permitindo uma compactação em camadas de suave a agressiva.
- O próprio gatilho do pipeline é
CompactionTriggers.Always— cada estratégia filho avalia o seu próprio gatilho de forma independente. - As estratégias executam-se por ordem, por isso 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 fluxo de trabalho
- Colapsa resultados de ferramentas antigas (suavemente).
- Resume os períodos de conversa mais antigos (moderado).
- Mantém apenas as últimas 4 interações do utilizador (agressivo).
- Remove grupos antigos se ainda estiver acima do orçamento (salvaguarda de emergência).
Estratégia de Compactação de Chamadas de Ferramenta Seletiva
Exclui totalmente os grupos de chamadas de ferramentas mais antigos, mantendo apenas o último keep_last_tool_call_groups.
- Não toca nas mensagens do utilizador nem nas mensagens simples do assistente.
- O melhor é quando a conversa das ferramentas domina o uso dos tokens e o histórico completo da ferramenta 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 múltiplas estratégias num pipeline sequencial impulsionado por um orçamento de tokens. Cada estratégia de criança corre por ordem, parando mais cedo assim que o orçamento está satisfeito. Um plano B incorporado exclui os grupos mais antigos se as estratégias sozinhas não conseguirem atingir o alvo.
- As estratégias são executadas por ordem; Coloque as estratégias mais suaves em primeiro lugar.
-
early_stop=True(o padrão) para assim que o orçamento dos tokens seja satisfeito.
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 fluxo de trabalho:
- Colapsa resultados de ferramentas antigas (suavemente).
- Resume os períodos de conversa mais antigos (moderado).
- Mantém apenas os últimos 20 grupos (agressivo).
- Retoma a exclusão pelo critério do mais antigo primeiro, caso ainda ultrapasse o orçamento (salvaguarda de emergência).
Utilização da compactação com um agente
Envie uma estratégia de compactação em CompactionProvider e registe-a como um AIContextProvider. Passe uma única estratégia ou um PipelineCompactionStrategy ao construtor.
Registo na API do construtor
Registe o fornecedor no ChatClientBuilder usando UseAIContextProviders. O fornecedor opera dentro do ciclo de chamada de ferramentas, compactando mensagens antes de cada chamada de 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));
Sugestão
Use um modelo mais pequeno e barato (como gpt-4o-mini) para o cliente de chat de resumo, para reduzir custos mantendo a qualidade do resumo.
Se for necessária apenas uma estratégia, passá-la diretamente para CompactionProvider sem a envolver num PipelineCompactionStrategy:
agentChatClient
.AsBuilder()
.UseAIContextProviders(new CompactionProvider(
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(20))))
.BuildAIAgent(...);
Registar-se através ChatClientAgentOptions
O prestador também pode ser especificado diretamente em ChatClientAgentOptions.AIContextProviders:
AIAgent agent = agentChatClient
.AsBuilder()
.BuildAIAgent(new ChatClientAgentOptions
{
AIContextProviders = [new CompactionProvider(compactionPipeline)]
});
Observação
Quando registado através de ChatClientAgentOptions, CompactionProvider é ativado durante o ciclo de chamada de ferramentas. Os fornecedores de contexto ao nível de agente executam-se antes de o histórico de chat ser armazenado, pelo que quaisquer mensagens sintéticas de resumo produzidas por CompactionProvider podem tornar-se parte do histórico persistente ao usar ChatHistoryProvider. Para, em vez disso, compactar apenas o contexto do pedido em voo enquanto preserva o histórico original armazenado, registe o fornecedor na ChatClientBuilder via UseAIContextProviders(...).
Compactação ad hoc
CompactionProvider.CompactAsync Aplica uma estratégia a uma lista de mensagens arbitrária sem uma sessão ativa de agente:
IEnumerable<ChatMessage> compacted = await CompactionProvider.CompactAsync(
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(8000)),
existingMessages);
CompactionProvider é um fornecedor de contexto que aplica estratégias de compactação antes e depois de cada execução do agente. Adicione-o junto a um fornecedor de histórico na lista do agente context_providers.
-
before_strategy— executa-se antes da chamada ao modelo, comprimindo mensagens já carregadas no contexto. -
after_strategy— executa após a chamada de modelo, compactando as mensagens armazenadas pelo fornecedor de histórico para que o próximo turno comece mais pequeno. -
history_source_id— osource_iddo fornecedor de histórico cujas mensagensafter_strategyarmazenadas devem compactar (por defeito para"in_memory").
Registo 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))
Sugestão
Use um modelo mais pequeno e barato (como gpt-4o-mini) para o cliente de sumarização para reduzir custos mantendo a qualidade do resumo.
Se for necessária apenas uma estratégia, passá-la diretamente como before_strategy:
compaction = CompactionProvider(
before_strategy=SlidingWindowStrategy(keep_last_groups=20),
history_source_id=history.source_id,
)
Após cada execução, compactar o histórico persistente
Use after_strategy para compactar as mensagens armazenadas pelo fornecedor de histórico, de modo a que os turnos futuros 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 ativa de agente:
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,
)
Escolher uma estratégia
| Estratégia | Agressividade | Preserva o contexto | Exige LLM | Melhor para |
|---|---|---|---|---|
ToolResultCompactionStrategy |
Baixo | Alto — só colapsa os resultados da ferramenta | No | Recuperar espaço da saída da ferramenta verbosa |
SummarizationCompactionStrategy |
Medium | Meio — substitui a história por um resumo | Sim | Conversas longas onde o contexto importa |
SlidingWindowCompactionStrategy |
Alto | Baixo — perde turnos inteiros | No | Limites rigorosos de contagem de turnos |
TruncationCompactionStrategy |
Alto | Baixo — elimina grupos mais antigos | No | Salvaguardas de emergência para o orçamento de tokens |
PipelineCompactionStrategy |
Configurable | Depende das estratégias da criança | Depends | Compactação em camadas com múltiplas alternativas de reserva |
| Estratégia | Agressividade | Preserva o contexto | Exige LLM | Melhor para |
|---|---|---|---|---|
ToolResultCompactionStrategy |
Baixo | Alto — colapsa os resultados da ferramenta em mensagens-resumo | No | Recuperar espaço da saída da ferramenta verbosa |
SelectiveToolCallCompactionStrategy |
Baixo–Médio | Médio — exclui totalmente os antigos grupos de chamada de ferramentas | No | Remoção do histórico de ferramentas quando os resultados deixam de ser necessários |
SummarizationStrategy |
Medium | Meio — substitui a história por um resumo | Sim | Conversas longas onde o contexto importa |
SlidingWindowStrategy |
Alto | Baixo — elimina grupos mais antigos | No | Limites rígidos de contagem de grupos |
TruncationStrategy |
Alto | Baixo — elimina grupos mais antigos | No | Salvaguardas de emergência para mensagens ou tokens de orçamento |
TokenBudgetComposedStrategy |
Configurable | Depende das estratégias da criança | Depends | Compactação em camadas com um objetivo de otimização do uso de tokens e múltiplas soluções de recurso. |
Passos seguintes
Armazenamento