Сжатие контекста и кеширование
Hermes Agent использует двойную систему сжатия и кеширование подсказок (prompt caching) Anthropic для эффективного управления использованием окна контекста в длительных разговорах.
Исходные файлы: agent/context_engine.py (ABC), agent/context_compressor.py (движок по умолчанию),
agent/prompt_caching.py, gateway/run.py (гигиена сессий), run_agent.py (ищите _compress_context)
Подключаемый движок контекста
Управление контекстом построено на базе ABC ContextEngine (agent/context_engine.py). Встроенный ContextCompressor является реализацией по умолчанию, но плагины могут заменить его альтернативными движками (например, Lossless Context Management).
context:
engine: "compressor" # default — built-in lossy summarization
engine: "lcm" # example — plugin providing lossless context
Движок отвечает за:
-
Определение момента срабатывания уплотнения (
should_compress()) -
Выполнение уплотнения (
compress()) -
Опциональное предоставление инструментов, которые агент может вызывать (например,
lcm_grep) -
Отслеживание использования токенов из ответов API
Выбор осуществляется через конфигурацию context.engine в config.yaml. Порядок разрешения:
-
Проверка директории
plugins/context_engine/<name>/ -
Проверка общей системы плагинов (
register_context_engine()) -
Возврат к встроенному
ContextCompressor
Движки-плагины никогда не активируются автоматически — пользователь должен явно установить context.engine в имя плагина. Значение по умолчанию "compressor" всегда использует встроенный движок.
Настройка через hermes plugins → Provider Plugins → Context Engine, или редактирование config.yaml напрямую.
Для создания плагина движка контекста см. Context Engine Plugins.
Двойная система сжатия
Hermes имеет два отдельных слоя сжатия, которые работают независимо:
┌──────────────────────────┐
Incoming message │ Gateway Session Hygiene │ Fires at 85% of context
─────────────────► │ (pre-agent, rough est.) │ Safety net for large sessions
└─────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ Agent ContextCompressor │ Fires at 50% of context (default)
│ (in-loop, real tokens) │ Normal context management
└──────────────────────────┘
1. Гигиена сессий Gateway (порог 85%)
Находится в gateway/run.py (ищите Session hygiene: auto-compress). Это страховочная сеть, которая запускается перед обработкой сообщения агентом. Она предотвращает ошибки API, когда сессии становятся слишком большими между витками (например, при ночном накоплении в Telegram/Discord).
-
Порог: Фиксирован на уровне 85% длины контекста модели
-
Источник токенов: Предпочитает фактические токены из ответа API за последний виток; при отсутствии использует приблизительную оценку на основе символов (
estimate_messages_tokens_rough) -
Срабатывает: Только когда
len(history) >= 4и сжатие включено -
Назначение: Перехватить сессии, которые избежали собственного компрессора агента
Порог гигиены Gateway intentionally выше, чем у компрессора агента. Установка его на уровне 50% (как у агента) приводила к преждевременному сжатию на каждом витке в длительных сессиях Gateway.
2. ContextCompressor агента (порог 50%, настраивается)
Находится в agent/context_compressor.py. Это основная система сжатия, которая работает внутри цикла инструментов агента с доступом к точным данным о количестве токенов из API.
Конфигурация
Все настройки сжатия читаются из config.yaml в разделе compression:
compression:
enabled: true # Enable/disable compression (default: true)
threshold: 0.50 # Fraction of context window (default: 0.50 = 50%)
target_ratio: 0.20 # How much of threshold to keep as tail (default: 0.20)
protect_last_n: 20 # Minimum protected tail messages (default: 20)
# Summarization model/provider configured under auxiliary:
auxiliary:
compression:
model: null # Override model for summaries (default: auto-detect)
provider: auto # Provider: "auto", "openrouter", "nous", "main", etc.
base_url: null # Custom OpenAI-compatible endpoint
Детали параметров
| Параметр | По умолчанию | Диапазон | Описание |
|---|---|---|---|
threshold |
0.50 |
0.0-1.0 | Сжатие срабатывает, когда токены промпта ≥ threshold × context_length |
target_ratio |
0.20 |
0.10-0.80 | Управляет бюджетом токенов защиты хвоста: threshold_tokens × target_ratio |
protect_last_n |
20 |
≥1 | Минимальное количество последних сообщений, всегда сохраняемых |
protect_first_n |
3 |
(жёстко задано) | Системный промпт + первый обмен всегда сохраняются |
Вычисленные значения (для модели с контекстом 200K при настройках по умолчанию)
context_length = 200,000
threshold_tokens = 200,000 × 0.50 = 100,000
tail_token_budget = 100,000 × 0.20 = 20,000
max_summary_tokens = min(200,000 × 0.05, 12,000) = 10,000
Алгоритм сжатия
Метод ContextCompressor.compress() следует 4-фазному алгоритму:
Фаза 1: Обрезка старых результатов инструментов (дёшево, без вызова LLM)
Старые результаты инструментов (>200 символов) за пределами защищённого хвоста заменяются на:
[Old tool output cleared to save context space]
Это дёшевый предварительный проход, который экономит значительное количество токенов от многословных выводов инструментов (содержимое файлов, вывод терминала, результаты поиска).
Фаза 2: Определение границ
┌─────────────────────────────────────────────────────────────┐
│ Message list │
│ │
│ [0..2] ← protect_first_n (system + first exchange) │
│ [3..N] ← middle turns → SUMMARIZED │
│ [N..end] ← tail (by token budget OR protect_last_n) │
│ │
└─────────────────────────────────────────────────────────────┘
Защита хвоста основана на бюджете токенов: проходит с конца в обратном направлении, накапливая токены до исчерпания бюджета. Возвращается к фиксированному числу protect_last_n, если бюджет защитил бы меньше сообщений.
Границы выравниваются, чтобы избежать разделения групп tool_call/tool_result.
Метод _align_boundary_backward() проходит мимо последовательных результатов инструментов, чтобы найти родительское сообщение ассистента, сохраняя группы целыми.