Сжатие контекста агента: 169 строк с квитанцией

Сжатие контекста агента: 169 строк с квитанцией

Сессия агента умирает не на первом большом файле, а на десятом повторе одного и того же падающего теста. Ни одна отдельная порция данных не была огромной: вывод инструмента, лог сборки, ещё один прогон тестов, та же ошибка в чуть другом формате. К моменту, когда модель начинает путаться, в контексте лежат десятки килобайт почти идентичного текста, и каждый новый токен только ухудшает картину.

Именно эту проблему разбирает Context Diet, небольшой MCP-сервер и CLI от разработчика techdevfun. Идея простая до неудобства: сжимать надо не файлы, а накопленное содержимое сессии, и делать это так, чтобы каждое сокращение можно было проверить.

Что такое Context Diet. Это детерминированный компрессор контекста для AI-агентов: он убирает дубликаты, извлекает релевантные фрагменты и укладывает текст в заданный бюджет токенов, не переписывая ни одного слова. Каждая оставленная строка скопирована из входа дословно, каждая выброшенная посчитана и отнесена к категории в манифесте, который прилагается к результату.

Почему контекст умирает от накопления, а не от размера

Разница принципиальная. Один большой файл агент худо-бедно переживает: его можно прочитать по частям, процитировать, отбросить. Накопление устроено иначе, потому что каждая порция по отдельности выглядит безобидно и потому не вызывает никаких защитных реакций. Агент честно сохраняет в истории все пять прогонов упавшего теста, и к пятому итерация модель уже не отличает свежий вывод от устаревшего.

Дальше включаются три механизма, которые хорошо изучены, но редко учитываются в инженерной практике. Во-первых, стоимость: каждый токен истории оплачивается на каждом следующем шаге, а не один раз. Во-вторых, внимание: качество ответа падает нелинейно, когда нужная строка оказывается в середине длинного контекста, а не в начале или конце. В-третьих, шум: устаревшая ошибка, оставшаяся в истории, конкурирует с актуальной и иногда выигрывает, потому что встречается чаще.

Отдельный слой проблемы, о котором мы уже писали, это описания инструментов: в материале MCP съедает контекст разобрано, как 111 тысяч токенов уходят до первого слова пользователя. Context Diet работает на другом уровне. Его интересует не схема инструментов, а то, что агент натаскал в сессию по ходу работы.

Пять инструментов и один манифест

Внутри проекта пять инструментов, и они складываются в цепочку. diet_count считает строки, байты и оценку токенов для любого текста. diet_dedupe убирает точные дубликаты строк и повторяющиеся блоки, то есть как раз те пять копий одного лога. diet_extract достаёт фрагменты по запросу с учётом релевантности и оставляет вокруг них контекст, чтобы вырванная из середины строка не потеряла смысл.

diet_summarize укладывает текст в бюджет токенов, сохраняя заголовки, строки ошибок и падений, а также первые и последние строки каждой секции. Ключевая деталь: он ничего не переписывает, только выбирает. diet_pack прогоняет весь конвейер сразу: дедупликация, извлечение по запросу, сжатие до бюджета и манифест по каждой строке.

Манифест здесь не украшение, а суть подхода. Обычное саммари, которое молча переписывает лог, это liability: если агент потом ошибётся, вы не сможете понять, потерялась информация при сжатии или её там никогда не было. Манифест отвечает на этот вопрос числами: сколько строк оставлено, сколько отброшено как дубликаты, сколько ушло при извлечении, сколько при сжатии. Плюс флаг verbatim: true, который прямо утверждает, что в оставленном тексте нет ни одного придуманного слова.

Арифметика квитанции

Разработчик приводит реальный пример: лог сессии с подробными прогонами тестов, фрагмент README и вывод сборки, упакованные в бюджет 400 токенов по запросу «test failure». Манифест показывает 169 строк, из которых 23 остались, 54 отброшены как дубликаты, 4 выброшены при извлечении и 88 при сжатии. Сумма сходится: 23 + 54 + 4 + 88 = 169.

Такая арифметика кажется мелочью, пока не попробуешь применить её к своему пайплайну. Любая система сжатия, которая не отчитывается построчно, оставляет вас с догадками. Вы видите, что ответ ухудшился, но не знаете, на каком шаге потерялась строка с настоящей причиной падения.

Честность отчёта тоже ограничена явно: токены считаются оценкой по правилу «символы делить на четыре», а строки и байты точны. Это нормальный инженерный компромисс, но именно поэтому в манифесте две разные единицы измерения, и путать их не стоит. Для русских логов, кстати, оценка будет заметно оптимистичнее, чем для английских: кириллица в токенизаторах дороже, а формула этого не знает. Об этом в README не сказано, но любой, кто считал токены для русского текста, знает разницу.

Чем это отличается от LLMLingua, Entroly и tool search

Автор сравнивает свой проект с четырьмя соседями и делает это без обычного маркетингового тона. Картина такая.

Инструмент Что сжимает Заявленное сжатие Проверяемость
Context Diet логи, выводы, ходы сессии 2–5x на логах построчный манифест
LLMLingua / LLMLingua-2 любой текст до 20x не проверяется на уровне токенов
Entroly кодовые базы целиком 78% меньше токенов чёрный ящик с дашбордом
mcp-token-optimizer код по AST зависит от файла восстановление через Prettier
Tool search в вендорах описания инструментов до 99.9% другой слой задачи

LLMLingua сжимает сильнее, до 20x на бенчмарках, но требует скачивания модели и стека Python с PyTorch, а её сокращения не аудируются на уровне отдельных токенов. Entroly заявляет 78% экономии на запрос целиком, однако цифра самоотчётная, а веса выученные: перечислить, почему конкретная строка выброшена, нельзя. mcp-token-optimizer умеет минифицировать код с учётом AST и восстанавливать форматирование через Prettier, но он работает с файлами кода и не трогает логи, выводы и ходы разговора, а именно там и накапливается вес сессии.

Вендорские решения вроде отложенной загрузки описаний в Claude Code или Code Mode у Cloudflare показывают самые впечатляющие проценты, до 99.9%, но уменьшают они определения инструментов, а не накопленный контент. Это другой слой, и он дополняет Context Diet, а не конкурирует с ним: можно включить оба и не пересекаться.

Где детерминизм проигрывает

Честная часть разбора важнее рекламной. Детерминированное извлечение не понимает смысла, поэтому может выбросить строку, которая формально не совпала с запросом, но была нужна. Спасают три вещи: запрос формулируется словами самой ошибки, строки падений сохраняются принудительно, а манифест позволяет увидеть, что именно ушло, и перезапустить сжатие с большим бюджетом или другим запросом.

Код проект трактует как текст, без анализа структуры. Для логов и выводов это плюс, для больших исходников минус: там mcp-token-optimizer аккуратнее. Сжатие на логах обычно даёт 2–5x, и это скромнее, чем у LLMLingua. В первой версии нет LLM-суммаризации (она опциональна и выключена), нет разбора JUnit и XML, нет вывода SARIF, нет редактирования секретов и нет дашборда. Всё это в README перечислено как отсутствующее, что само по себе редкость.

Есть и более тонкий риск, о котором стоит помнить: сжатие контекста не заменяет гигиену сессии. Если агент десять раз запускает один и тот же тест, проблема не только в размере истории, но и в том, что цикл не сходится. Компрессор лечит симптом и делает его дешевле, а причину искать всё равно человеку. Похожая логика разобрана в материале про обвязку агента: качество обвязки влияет на результат сильнее, чем размер модели.

Как попробовать на своём худшем логе

Проект ставится из исходников, npm-пакета на момент публикации ещё нет, зато есть CI на Node 20 и 22 и тесты, которые прогоняют сервер через настоящий MCP-клиент. Клонируем репозиторий, собираем, запускаем CLI на примере из репозитория с бюджетом 400 токенов и запросом «test failure». Дальше подставляем свой самый некрасивый лог и смотрим на манифест: если доля дубликатов выше трети, у вас не проблема контекста, а проблема цикла, который повторяет одно и то же.

Как MCP-сервер проект подключается по stdio, то есть работает с любым клиентом, который умеет этот транспорт: Claude Code, Cursor, собственный агент на MCP SDK. Ни аккаунта, ни сети, ни вызовов модели: всё считается локально, лицензия MIT. Для команд, где логи уходят в сторонние сервисы, это существенный аргумент.

Рабочий режим, который напрашивается: сырой лог остаётся на диске, агенту уходит упакованная версия с бюджетом в пару тысяч токенов и запросом по тексту ошибки. Когда сессия всё равно упирается, вы открываете манифест и видите, что именно не доехало до модели. Это дешевле, чем гадать, и заметно дешевле, чем платить за 60 тысяч токенов истории на каждом шаге.

Часто задаваемые вопросы

Context Diet заменяет RAG? Нет. RAG ищет нужные документы во внешней базе, а Context Diet сжимает то, что уже попало в сессию. Это разные задачи, и они нормально сочетаются: сначала retrieve, потом упаковка в бюджет. Подробнее о выборе между подходами мы писали в разборе RAG против длинного контекста.

Можно ли доверять оценке токенов? Оценка идёт по формуле «символы делить на четыре», поэтому для английских логов она близка к реальности, а для русского текста занижает расход. Строки и байты считаются точно, так что для проверки гипотез этого достаточно. Для точного бюджета считайте токены токенизатором своей модели.

Чем это лучше обычной суммаризации моделью? Суммаризация моделью переписывает текст и может придумать деталь, которой не было. Детерминированное извлечение только выбирает существующие строки, а манифест показывает, что выброшено. Если нужна именно переработка смысла, это другой класс инструментов, и мы разбирали его в статье про инкрементальное сжатие диалогов.

Итог

Context Diet не пытается сжать сильнее всех, и в этом его сила. Он ставит на другое: предсказуемость и отчётность. Сжатие контекста агента здесь перестаёт быть магией чёрного ящика и становится операцией с чеком, где видно каждую выброшенную строку. Для отладки агентных пайплайнов это ровно то, чего не хватает большинству компрессоров.

Если ваши сессии умирают на десятом повторе одного и того же теста, начните с манифеста на своём худшем логе. Одна цифра, доля дубликатов, скажет о вашем пайплайне больше, чем час чтения трассировок.

← Все записи