Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
По мере роста бесед количество токенов в истории чата может превышать контекстные окна модели или увеличивать затраты. Стратегии сжатия снижают размер журнала бесед при сохранении важного контекста, поэтому агенты могут продолжать функционировать в течение длительных взаимодействий.
Это важно
Платформа сжатия в настоящее время экспериментальна. Чтобы использовать его, необходимо добавить #pragma warning disable MAAI001.
Это важно
Платформа сжатия в настоящее время экспериментальна в Python. Импорт стратегий из agent_framework._compaction.
Почему уплотнение имеет значение
Каждый запрос к LLM включает полный журнал бесед. Без сжатия:
- Ограничения токенов — беседы со временем превышают окно контекста модели, вызывая ошибки.
- Затраты — более крупные подсказки потребляют больше токенов, увеличивая затраты на API.
- Задержка — больше маркеров ввода означает более медленное время отклика.
Сжатие решает эти проблемы, выборочно удаляя, сворачивая или суммируя старые части беседы.
Основные понятия
Применимость: только агенты журнала в памяти
Сжатие применяется только к агентам, которые управляют собственной историей общения в памяти. Агенты, использующие управляемый службой контекст или состояние беседы, не получают преимущества от сжатия, так как служба уже обрабатывает управление контекстом. Примеры агентов, управляемых службой, включают:
- Агенты Foundry — контекст управляется на стороне сервера службой Azure AI Foundry.
- API ответов с включенным хранилищем (по умолчанию) — состояние беседы хранится и управляется службой OpenAI.
- Агенты Copilot Studio — контекст беседы поддерживается службой Copilot Studio.
Для этих типов агентов настройка стратегии сжатия не влияет. Сжатие имеет значение только в том случае, если агент сохраняет свой собственный список сообщений в оперативной памяти и передает модели полную историю сообщений для каждого вызова.
Сжатие работает с MessageIndex — структурированным представлением плоского списка сообщений, который группирует сообщения в атомарные единицы, называемые MessageGroup экземплярами. Каждая группа отслеживает количество сообщений, число байтов и предполагаемое число маркеров.
Группы сообщений
A MessageGroup представляет логически связанные сообщения, которые должны храниться или удаляться вместе. Например, сообщение помощника, содержащее вызовы инструментов и соответствующие сообщения результатов средства, образуют атомарную группу— удаление одного без другого приведет к ошибкам API LLM.
Каждая группа имеет :MessageGroupKind
| Kind | Описание |
|---|---|
System |
Одно или несколько системных сообщений. Всегда сохраняется во время сжатия. |
User |
Одно пользовательское сообщение, начинающее новую очередь. |
AssistantText |
Обычный текстовый ответ помощника (без вызовов инструментов). |
ToolCall |
Сообщение помощника с вызовами инструментов и соответствующими результатами использования инструментов, рассматриваемое как единое неделимое целое. |
Summary |
Сжатое сообщение, созданное сжатием сводных данных. |
Triggers
Это CompactionTrigger делегат, который оценивает, следует ли продолжить сжатие на основе текущих MessageIndex метрик:
public delegate bool CompactionTrigger(MessageIndex index);
Класс CompactionTriggers предоставляет стандартные методы фабрики.
| Триггер | Срабатывает, когда |
|---|---|
CompactionTriggers.Always |
Каждый раз (безоговорочно). |
CompactionTriggers.Never |
Никогда (отключает сжатие). |
CompactionTriggers.TokensExceed(maxTokens) |
Количество включенных токенов превышает пороговое значение. |
CompactionTriggers.MessagesExceed(maxMessages) |
Включенное число сообщений превышает пороговое значение. |
CompactionTriggers.TurnsExceed(maxTurns) |
Включенное число поворотов пользователя превышает пороговое значение. |
CompactionTriggers.GroupsExceed(maxGroups) |
Включенное число групп превышает пороговое значение. |
CompactionTriggers.HasToolCalls() |
Существует по крайней мере одна группа вызовов инструментов, не подлежащая исключению. |
Объедините триггеры с CompactionTriggers.All(...) (логическим И) или CompactionTriggers.Any(...) (логическим ИЛИ):
// Compact only when there are tool calls AND tokens exceed 2000
CompactionTrigger trigger = CompactionTriggers.All(
CompactionTriggers.HasToolCalls(),
CompactionTriggers.TokensExceed(2000));
Триггер и целевой объект
Каждая стратегия имеет два предиката:
-
Триггер — определяет когда начинается сжатие. Если триггер возвращается
false, стратегия полностью пропускается. -
Целевой объект — элементы управления при остановке сжатия. Стратегии постепенно исключают группы и повторно оценивают целевой объект после каждого шага, остановившись сразу после возврата
trueцелевого объекта.
Если целевой объект не указан, он по умолчанию возвращает обратное значение триггера — сжатие останавливается, как только условие триггера больше не будет срабатывать.
Сжатие работает на плоском списке Message объектов. Сообщения аннотируются с использованием упрощенных групповых метаданных, и стратегии изменяют эти аннотации на месте, чтобы пометить группы как исключенные до того, как список сообщений отображается в модели.
Группы сообщений
Сообщения группируются в атомарные единицы. Каждой группе назначается GroupKind:
| Kind | Описание |
|---|---|
system |
Системные сообщения. Всегда сохраняется во время сжатия. |
user |
Одно пользовательское сообщение. |
assistant_text |
Обычный текстовый ответ помощника (без вызовов функций). |
tool_call |
Уведомление ассистента с вызовами функций и соответствующими сообщениями обрезультатах инструмента, рассматриваемое как атомарная единица. |
Стратегии сжатия
Это CompactionStrategy протокол — любой async вызываемый объект, который принимает list[Message] и изменяет его на месте, возвращая True, если что-то изменилось.
class CompactionStrategy(Protocol):
async def __call__(self, messages: list[Message]) -> bool: ...
Токенизатор
Стратегии, учитывающие маркеры, принимают реализацию TokenizerProtocol. Встроенный CharacterEstimatorTokenizer использует эвристику 4 символа на токен.
from agent_framework._compaction import CharacterEstimatorTokenizer
tokenizer = CharacterEstimatorTokenizer()
Передайте пользовательский токенизатор, если требуется точное количество токенов для энкодинга конкретной модели.
Стратегии сжатия
Все стратегии наследуются от абстрактного CompactionStrategy базового класса. Каждая стратегия сохраняет системные сообщения и учитывает MinimumPreserved порог, который защищает самые последние несистемные группы от удаления.
Стратегии сжатия импортируются из agent_framework._compaction.
СтратегияУсеченияКомпакции
Стратегия усечения
Самый простой подход: удаляет самые старые группы сообщений, не относящихся к системе, до тех пор, пока целевое условие не будет выполнено.
- Учитывает границы атомарных групп (вызовы инструментов и сообщения результатов удаляются вместе).
- Лучше всего подходит для ограничителей бюджета токенов.
-
MinimumPreservedпо умолчанию использует32.
// Drop oldest groups when tokens exceed 32K, keeping at least 10 recent groups
TruncationCompactionStrategy truncation = new(
trigger: CompactionTriggers.TokensExceed(0x8000),
minimumPreserved: 10);
- Если задан
tokenizer, то метрикой является количество маркеров; в противном случае — количество сообщений. -
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(),
)
Стратегия компакции скользящего окна
СкользящаяОкноСтратегия
Удаляет старое содержимое беседы, чтобы сохранить только последнее окно обмена, уважая логические единицы беседы, а не произвольные подсчеты сообщений. Системные сообщения сохраняются во всех случаях.
- Лучше всего для предсказуемого ограничения длины беседы.
Удаляет старейших пользователей повороты и связанные с ними группы ответов, работающие на границах логического поворота, а не отдельные группы.
- Поворот начинается с сообщения пользователя и включает все последующие группы помощников и групп вызовов инструментов до следующего сообщения пользователя.
-
MinimumPreservedпо умолчанию устанавливается на1(сохраняя как минимум наиболее недавнюю несистемную группу).
// Keep only the last 4 user turns
SlidingWindowCompactionStrategy slidingWindow = new(
trigger: CompactionTriggers.TurnsExceed(4));
Сохраняет только самые последние keep_last_groups несистемные группы, за исключением всех старых.
-
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
Свертывает устаревшие группы вызовов инструментов в компактные сводные сообщения, сохраняя читаемую трассировку без излишней детализации сообщений.
- Не касается сообщений пользователей или ответов обычного помощника.
- Оптимальная стратегия первого этапа восстановления пространства, занятого подробными результатами инструментов.
- Заменяет группы вызовов с несколькими сообщениями (помощник и результаты инструментов) краткой сводкой, такой как
[Tool calls: get_weather, search_docs]. -
MinimumPreservedустанавливает значение2по умолчанию, гарантируя, что взаимодействие с текущим инструментом остаётся видимым.
// Collapse old tool results when tokens exceed 512
ToolResultCompactionStrategy toolCompaction = new(
trigger: CompactionTriggers.TokensExceed(0x200));
- Сворачивается в компактные сводные сообщения, такие как
[Tool results: get_weather: sunny, 18°C]. - Последние
keep_last_tool_call_groupsгруппы вызовов инструментов остаются нетронутыми.
from agent_framework._compaction import ToolResultCompactionStrategy
# Collapse all but the newest tool-call group
tool_result = ToolResultCompactionStrategy(keep_last_tool_call_groups=1)
СуммированиеCompactionStrategy
СтратегияСводки
Использует LLM для суммирования старых частей беседы, заменив их одним сводным сообщением.
- Запрос по умолчанию сохраняет ключевые факты, решения, предпочтения пользователя и результаты вызова средства.
- Требуется отдельный клиент LLM для суммирования — рекомендуется использовать меньшую, более быструю модель.
- Лучше всего для сохранения контекста беседы при значительном снижении количества токенов.
- Можно указать настраиваемый запрос на сводку.
- Защищает системные сообщения и последние
MinimumPreservedнесистемные группы (по умолчанию:4). - Отправляет старые сообщения в отдельный
IChatClientзапрос на создание сводки, а затем вставляет саму сводку как группу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);
Можно указать настраиваемый запрос на сводку:
SummarizationCompactionStrategy summarization = new(
chatClient: summarizerChatClient,
trigger: CompactionTriggers.TokensExceed(0x500),
summarizationPrompt: "Summarize the key decisions and user preferences only.");
- Триггер срабатывает при превышении количества включенных сообщений, не относящихся к системе,
target_count + threshold. - Сохраняет самые
target_countновые сообщения; суммирует все старые. - Требуется
SupportsChatGetResponseклиент.
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,
)
Укажите пользовательский запрос на суммирование.
summarization = SummarizationStrategy(
client=summarizer_client,
target_count=4,
prompt="Summarize the key decisions and user preferences only.",
)
Стратегия Компактирования Конвейера
Комбинирует несколько стратегий в единую последовательность. Каждая стратегия работает на основе результата предыдущей, что позволяет выполнять многослойное уплотнение от мягкого к агрессивному.
- Триггер конвейера —
CompactionTriggers.Always. Каждая дочерняя стратегия независимо оценивает свой собственный триггер. - Стратегии выполняются по порядку, поэтому сначала разместите наименее агрессивные стратегии.
PipelineCompactionStrategy pipeline = new(
new ToolResultCompactionStrategy(CompactionTriggers.TokensExceed(0x200)),
new SummarizationCompactionStrategy(summarizerChatClient, CompactionTriggers.TokensExceed(0x500)),
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(4)),
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(0x8000)));
Этот конвейер:
- Свернуть старые результаты инструмента (плавно).
- Суммирует старые фрагменты бесед на среднем уровне.
- Сохраняет только последние 4 хода пользователя (агрессивный).
- Удаляет старые группы, если бюджет все еще превышен (экстренный резервный механизм).
ВыборочнаяToolCallCompactionStrategy
Полностью исключает старые группы вызовов инструментов, сохраняя только последний keep_last_tool_call_groups.
- Не касается сообщений пользователя или обычного помощника.
- Лучше всего, если чат инструментов доминирует в использовании маркеров, а полный журнал инструментов не нужен.
from agent_framework._compaction import SelectiveToolCallCompactionStrategy
# Keep only the most recent tool-call group
selective_tool = SelectiveToolCallCompactionStrategy(keep_last_tool_call_groups=1)
СтратегияСоставленияБюджетаТокенов
Создает несколько стратегий в последовательный конвейер, управляемый бюджетом токенов. Каждая дочерняя стратегия выполняется в указанном порядке, останавливаясь, как только бюджет будет удовлетворен. Встроенный резервный механизм исключает самые старые группы, если одних стратегий недостаточно для достижения цели.
- Стратегии выполняются по порядку; поместите в самую первую очередь самые мягкие стратегии.
-
early_stop=True(значение по умолчанию) останавливается, как только бюджет токенов будет исчерпан.
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),
],
)
Этот конвейер:
- Свернуть предыдущие результаты инструмента (мягко).
- Сводит воедино старые фрагменты бесед (умеренно).
- Сохраняет только последние 20 групп (агрессивных).
- Возвращается к исключению по принципу старшинства, если бюджет по-прежнему превышен (чрезвычайная мера).
Использование сжатия с агентом
Оборачивайте стратегию сжатия в CompactionProvider и зарегистрируйте ее в качестве AIContextProvider. Передайте одну стратегию или PipelineCompactionStrategy в конструктор.
Регистрация в API построителя
Зарегистрируйте поставщика в ChatClientBuilder с использованием UseAIContextProviders. Поставщик выполняется внутри цикла вызова средства, сжимая сообщения перед каждым вызовом 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));
Подсказка
Используйте меньшую, более дешевую модель (например gpt-4o-mini) для клиента чата для суммирования, чтобы сократить затраты, при этом сохраняя качество сводки.
Если требуется только одна стратегия, передайте её непосредственно в CompactionProvider, не упаковывая её в PipelineCompactionStrategy.
agentChatClient
.AsBuilder()
.UseAIContextProviders(new CompactionProvider(
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(20))))
.BuildAIAgent(...);
Регистрация через ChatClientAgentOptions
Поставщик также можно указать непосредственно в ChatClientAgentOptions.AIContextProviders:
AIAgent agent = agentChatClient
.AsBuilder()
.BuildAIAgent(new ChatClientAgentOptions
{
AIContextProviders = [new CompactionProvider(compactionPipeline)]
});
Замечание
При регистрации через ChatClientAgentOptions, CompactionProviderне активируется во время цикла вызова инструментов. Поставщики контекста уровня агента запускаются перед сохранением журнала чата, поэтому все искусственные сводные сообщения, созданные с помощью CompactionProvider, могут стать частью сохраняемой истории при использовании ChatHistoryProvider. Чтобы сжать только текущий контекст запроса при сохранении исходной сохраненной истории, зарегистрируйте поставщика на ChatClientBuilder через UseAIContextProviders(...).
Незапланированное сжатие
CompactionProvider.CompactAsync Применяет стратегию к произвольному списку сообщений без активного сеанса агента:
IEnumerable<ChatMessage> compacted = await CompactionProvider.CompactAsync(
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(8000)),
existingMessages);
CompactionProvider — это поставщик контекста, который применяет стратегии сжатия до и после каждого запуска агента. Добавьте его вместе с поставщиком данных истории в списке агента context_providers.
-
before_strategy— выполняется перед вызовом модели, сжимая сообщения, уже загруженные в контекст. -
after_strategy— выполняется после вызова модели, сжимая сообщения, хранящиеся поставщиком истории, так что следующий ход начинается с меньшего объема. -
history_source_id— поставщик истории, сообщенияsource_idкоторого должны быть сжаты (по умолчанию"in_memory").
Регистрация в агенте
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))
Подсказка
Используйте меньшую и более дешевую модель (например, gpt-4o-mini) для клиента суммирования, чтобы сократить затраты при сохранении качества суммирования.
Если требуется только одна стратегия, передайте ее напрямую следующим образом before_strategy:
compaction = CompactionProvider(
before_strategy=SlidingWindowStrategy(keep_last_groups=20),
history_source_id=history.source_id,
)
Сжатие сохраняемого журнала после каждого запуска
Используйте after_strategy для сжатия сообщений, хранящихся поставщиком журнала, чтобы будущие повороты начинались с сокращенного контекста:
compaction = CompactionProvider(
before_strategy=SlidingWindowStrategy(keep_last_groups=20),
after_strategy=ToolResultCompactionStrategy(keep_last_tool_call_groups=1),
history_source_id=history.source_id,
)
Незапланированное сжатие
apply_compaction Применяет стратегию к произвольному списку сообщений за пределами активного сеанса агента:
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,
)
Выбор стратегии
| Стратегия | Агрессивность | Сохраняет контекст | Требуется LLM | лучше всего подходит для |
|---|---|---|---|---|
ToolResultCompactionStrategy |
Low | Высокий — свертываются только результаты инструмента | Нет | Восстановление пространства из подробных выходных данных средства |
SummarizationCompactionStrategy |
Средний | Средний — заменяет историю сводкой | Да | Длинные беседы, где важен контекст |
SlidingWindowCompactionStrategy |
High | Низкий — пропуск целых оборотов | Нет | Ограничения на количество строгих поворотов |
TruncationCompactionStrategy |
High | Низкий — удаление старых групп | Нет | Резервные меры для чрезвычайного бюджетирования токенов |
PipelineCompactionStrategy |
Configurable | Зависит от дочерних стратегий | Зависит | Многоуровневое сжатие с несколькими резервными копиями |
| Стратегия | Агрессивность | Сохраняет контекст | Требуется LLM | лучше всего подходит для |
|---|---|---|---|---|
ToolResultCompactionStrategy |
Low | Высокий — сводит результаты инструмента в сводные сообщения. | Нет | Высвобождение пространства из избыточных выводов инструмента |
SelectiveToolCallCompactionStrategy |
Низкий–средний | Средний — полностью исключает старые группы вызовов инструментов | Нет | Удаление журнала инструментов, когда результаты больше не нужны |
SummarizationStrategy |
Средний | Средний — заменяет журнал сводкой | Да | Длинные беседы, где важен контекст |
SlidingWindowStrategy |
High | Низкий уровень — удаляет старейшие группы | Нет | Жёсткие ограничения на количество групп |
TruncationStrategy |
High | Низкий — падение старейших групп | Нет | Запасные варианты для аварийных сообщений или бюджетирования токенов |
TokenBudgetComposedStrategy |
Configurable | Зависит от дочерних стратегий | Зависит | Многоуровневая компакция с целью экономии токенов и несколькими альтернативными вариантами |