Сжатие контекста и кэширование
Агент Hermes использует двойное сжатие системы и кэширование подсказок Anthropic для эффективного управления использованием контекста окна в длительных диалогах.
Исходные файлы: agent/context_engine.py (ABC), agent/context_compressor.py (стандартный движок), agent/prompt_caching.py, gateway/run.py (гигиена сессии), run_agent.py (поиск _compress_context)
Подключаемый контекст движка
Управление контекстом построено на абстрактном базовом классе ContextEngine (agent/context_engine.py). Встроенный ContextCompressor реализован по умолчанию, но плагины могут заменить его альтернативными движками (например, Управление контекстом без потерь).
context:
engine: "compressor" # по умолчанию — встроенное сжатие с потерями
engine: "lcm" # пример — плагин, обеспечивающий контекст без потерь
Мовок отвечает за:
- Определение момента, когда должно произойти уплотнение (should_compress())
- Выполнение уплотнения (compress())
- Опциональное предоставление инструментов, которые могут работать с агентом (например, lcm_grep)
- Отслеживание использования токенов из API ответов.
Выбор осуществляется через конфигурацию с помощью context.engine в config.yaml. Порядок разрешения:
1. Проверка каталога plugins/context_engine/<имя>/
2. Проверка всей системы плагинов (register_context_engine())
3. Возврат встроенного ContextCompressor
Движки плагинов никогда не активируются автоматически — пользователь должен явно установить context.engine по имени плагина. По умолчанию "компрессор" всегда используется встроенный.
Настройте через hermesplugins → Provider Plugins → Context Engine, или напрямую отредактируйте config.yaml.
Для создания плагина движка контекста см. Плагины движка контекста.
Двойная система сжатия
Hermes имеет два нижних уровня сжатия, производится независимо:
┌──────────────────────────┐
Входящее сообщение │ Гигиена сессии шлюза │ Срабатывает при 85% контекста
─────────────────► │ (до агента, грубая оценка)│ Предохранитель для больших сессий
└─────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ Agent ContextCompressor │ Срабатывает при 50% контекста (по умолч.)
│ (в цикле, реальные токены)│ Обычное управление контекстом
└──────────────────────────┘
1. Гигиена шлюза сессии (порог 85%)
Находится в gateway/run.py (поиск Гигиена сеанса: автосжатие). Это предохранитель, который запускается до того, как агент обработает сообщение. Вы допускаете ошибку API, когда сеансы становятся слишком высокими между большими оборотами (например, ночное накопление в Telegram/Discord).
- Порог: фиксирована на 85% длина контекста модели.
- Источник токенов: Предпочитает фактические токены, сообщенные API за последний оборот; при отсутствии использования грубая оценка на основе символов (
estimate_messages_tokens_rough) - Сдача: Только когда
len(history) >= 4и сжатие включено - Цель: Перехватить сессию, которая запускает собственного агента компрессора.
Порог гигиены шлюза намеренно выше, чем у агента компрессора. Установка его на 50% (как у агента) привела к преждевременному сжатию на каждом обороте в ходе сеансов шлюза.
2. Agent ContextCompressor (порог 50%, настраиваемый)
Находится в agent/context_compressor.py. Это основная система сжатия, которая работает внутри циклических инструментов агента с доступом к лучшим подсчетам токенов, сообщаемым API.
Конфигурация
Все настройки сжатия читаются из config.yaml в разделе compression:
compression:
enabled: true # Включить/отключить сжатие (по умолчанию: true)
threshold: 0.50 # Доля окна контекста (по умолчанию: 0.50 = 50%)
target_ratio: 0.20 # Сколько от порога сохранять как хвост (по умолчанию: 0.20)
protect_last_n: 20 # Минимальное количество защищенных хвостовых сообщений (по умолчанию: 20)
# Модель/провайдер суммаризации настраивается в auxiliary:
auxiliary:
compression:
model: null # Переопределить модель для суммаризации (по умолчанию: автоопределение)
provider: auto # Провайдер: "auto", "openrouter", "nous", "main" и т.д.
base_url: null # Пользовательская конечная точка, совместимая с OpenAI
Детальные параметры
| Параметр | По умолчанию | Диапазон | Описание |
|---|---|---|---|
порог |
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 |
(жестко запрограммировано) | Системная подсказка + первый обмен всегда выбирают |
Вычисленные значения (для моделей с контекстом 200К при задании по умолчанию)
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: Определение границ
┌─────────────────────────────────────────────────────────────┐
│ Список сообщений │
│ │
│ [0..2] ← protect_first_n (система + первый обмен) │
│ [3..N] ← средние обороты → СУММАРИЗИРОВАНЫ │
│ [N..end] ← хвост (по бюджету токенов ИЛИ protect_last_n) │
│ │
└─────────────────────────────────────────────────────────────┘
Защита хвоста опирается на бюджет токенов: идет назад от конца, накапливая токены, пока бюджет не исчерпан. Возвращается к фиксированному результату protect_last_n, если бюджет защитил меньше сообщений.
Границы спортивны, чтобы избежать разделения на группыtool_call/tool_result. Метод _align_boundary_backward() проходит через следующие инструменты результатов, чтобы найти родительское сообщение ассистента, сохраняющего группу нетронутыми.
Фаза 3: Генерация структурированной сводки:::предупреждение Длина контекста модели масштабирования
Модель более крупного размера должна иметь контекст окна не меньше, чем у основной модели агента. Весь средний раздел предполагает реализацию модели в одном вызове call_llm(task="compression"). Если контекстная модель уменьшена меньше, API возвращает ошибку длины контекста —_generate_summary()перехватывает ее, записывает предупреждение и возвращаетNone`. Затем компрессор выбрасывает средние обороты без сводки, молча теряя контекст разговора. Это наиболее распространенная причина ухудшения качества уплотнения.