Как я экономлю 80% контекста нейросетей при работе с логами

от автора

Проблема

Я разрабатываю приложение KeyRay — кроссплатформенный аналог Punto Switcher, имеющий на порядок лучшую стабильность переключения раскладки. При разработке активно использую нейросети для отладки багов. И столкнулся с неприятной проблемой: при копировании логов в чат огромная часть контекстного окна уходит впустую. Работа с логами во время разработки в паре с ИИ занимает львиную долю времени и контекста чата.

Типичная картина: заметил баг, копирую 1000 строк логов и вставляю в чат. Нейросеть начинает разбирать текст, но из этих 1000 строк реально уникальных — максимум 300. Остальные — это один и тот же шаблон, повторенный сотни раз:

2026-04-18T11:54:02.746 [WinFocusMonitor] computeIsSecureField: queryMsaaProtected == 0   2026-04-18T11:54:02.747 [WinFocusMonitor] workerMain: hwnd=00000000016000FE idObject=-4 idChild=0 -> secure=02026-04-18T11:54:02.765 [WinFocusMonitor] computeIsSecureField: queryMsaaProtected == 0   2026-04-18T11:54:02.765 [WinFocusMonitor] workerMain: hwnd=00000000003B0640 idObject=-4 idChild=-45107 -> secure=02026-04-18T11:54:04.787 [MemDiag] periodic t+9s WorkingSet=352.257812MB Peak=368.761719MB 2026-04-18T11:54:04.788 [MemDiag] WordIndex en_US READY at t+9s2026-04-18T11:54:04.788 [MemDiag] after  WordIndex en_US READY WorkingSet=352.320312MB Peak=368.761719MB

В логах видны одни и те же компоненты ([WinFocusMonitor], [MemDiag]), одни и те же ключи (WorkingSet=, hwnd=), одни и те же фразы.

Идея состояла в том, чтобы скопировать логи в буфер обмена стандартными способами, затем с помощью сочетания клавиш Ctrl+Alt+V вставить оптимизированный вариант. В результате, с помощью такой простой фоновой утилиты, удалось добиться сжатия логов до 80% в зависимости от объема и количества повторений.

Этап 1: Базовая идея — словарь повторений

Первая мысль была простой: если что-то повторяется — вынесу это в “легенду” (словарь) и заменю коротким тегом. Попросил нейронку написать скрипт на PowerShell, который анализирует логи и выносит повторяющиеся элементы в теги вида #1#, #2# .

Вот как выглядят те же логи после первой версии скрипта:

--- LEGEND ---#T# = 2026-04-18T11:54:#0# = [WinFocusMonitor]#1# = [MemDiag]#2# = hwnd=#3# = idObject=#4# = idChild=#5# = secure=#6# = WorkingSet=#7# = Peak=#8# = ' computeIsSecureField: queryMsaaProtected == 0'#9# = ' WordIndex '--- LOGS ---#T#02.746 #0##8##T#02.747 #0# workerMain: #00000000016000FE #3#-4 #4#0 -> #5#0#T#02.765 #0#8   #T#02.765 #0# workerMain: #00000000003B0640 #3#-4 #4#-45107 -> #5#0#T#04.787 #1# periodic t+9s #6352.257812MB #7#368.761719MB #T#04.788 #1# #9#en_US READY at t+9s#T#04.788 #1# after  #9#en_US READY #6#352.320312MB #7#368.761719MB

Все базовые повторяющиеся элементы вынесены в легенду наверху.

Результат первого этапа: 4072 символов → 2625 символов. Экономия~35%.

Этап 2: Оптимизация тегов через Base62

Когда переменных становится много, теги начинают выглядеть как #123, #456 — это уже 4-5 символов на тег.

Это можно оптимизировать возможностью добавления в теги строчных и заглавных букв. В этой системе первые 62 переменные можно записать всего двумя символами:

  • #0, #1, #2#9 (10 штук)

  • #a, #b, #c#z (26 штук)

  • #A, #B, #C#Z (26 штук)

Итого 62 переменные в двух символах. Дальше идут #10, #11 и так далее, но в три символа.

--- LEGEND ---#T# = 2026-04-18T11:54:#0# = [WinFocusMonitor]#1# = [MemDiag]#2# = hwnd=#3# = idObject=#4# = idChild=#5# = secure=#6# = WorkingSet=#7# = Peak=#8# = ' computeIsSecureField: queryMsaaProtected == 0'#9# = ' WordIndex '--- LOGS ---#T#02.746 #0##8#   #T#02.747 #0# workerMain: #2#16000FE #3#-4 #4#0 -> #5#0

На больших масштабах это может давать дополнительные 3-5% компрессии.

Этап 3: Удаление ведущих нулей

Ещё одна мелочь, которая режет глаз в C++ логах — hex-указатели с фиксированной шириной. Windows API возвращает HWND как 00000000016000FE — восемь ведущих нулей, которые не несут никакой смысловой нагрузки.

Оптимизировал это обрезанием ведущих нулей. Было 00000000016000FE — стало 16000FE.

--- LOGS ---#T#02.746 #0##8#   #T#02.747 #0# workerMain: #2#16000FE #3#-4 #4#0 -> #5#0#T#02.765 #0#8   #T#02.765 #0# workerMain: #2#3B0640 #3#-4 #4#-45107 -> #5#0

На 45 КБ логов это дало экономию примерно в 300 символов. Немного, но тем не менее.

Этап 4: Meta-BPE — теги из тегов

Работа с большими логами выявили дубликаты из самих тегов:

#T#19.557 #0##C##8##81# #90##T#19.557 #0##K##8##81# #90##T#19.601 #0##U##8##81# #90##T#19.601 #0##C##8##32# #91##T#19.601 #0##w##8##32# #91##T#19.601 #0##x##8##32# #91#

Префикс #T#19.557 #0# повторяется несколько раз подряд. Теперь нужно искать повторяющиеся последовательности тегов и выносить их в новые переменные.

Я добавил дополнительный цикл обработки, который работает поверх обычного. Новые переменные стал помечать (!) вместо (#), для разделения:

--- LEGEND ---#T# = 2026-04-18T11:54:#0# = [TTDiag]#8# = vk=#32# = 881#81# = 890#C# = ' > shouldBlockAllFeatures '#K# = ' > drainPendingReset '#U# = ' > entry '#w# = ' > executePendingReplacementIfAny '#x# = ' > hotkeyManager.processKeyEvent '!1! = #T#19.557 #0##C##8#!2! = #T#19.601 #0#!3! = #8##32# #91#--- LOGS ---!1!#81# #90#!1!#K##81# #90#!2!#U##81# #90#!2!#C#!3!!2!#w#!3!!2!#x#!3!

Теперь обычные теги складываются в мета-теги.

Результат четвертого этапа: 45 839 символов → 13 398 символа. Сжатие 70.8% от оригинала.

Этап 5: Макросы с подстановкой

Дальнейшая работа показала следующие паттерны:

!26!#o#!3!!26!#E#!3!!26!#K#!3!!26!#D#!3!!26!#w#!3!!26!#z#!3!!26!#x#!3!

Здесь меняется только один средний элемент! Префикс !26 и суффикс !3 одинаковые во всех строках. Данную конструкцию мы можем вынести в следующий паттерн !26!#@#!3!, где @ — указатель на место подстановки, а само значение в итоговом макросе будем передавать после : , например &1:o

--- LEGEND ---#o# = ' > shouldExecute '#E# = ' > hotkeyDefs->snapshot '#K# = ' > drainPendingReset '#D# = ' > handleCaseSwitchHotkey '#w# = ' > executePendingReplacementIfAny '#z# = ' > handleTranslationHotkey '#x# = ' > hotkeyManager.processKeyEvent '!26! = #T##1d#0!3! = #8#81 #90#&1 = !26!#@#!3!--- LOGS ---&1:o&1:E&1:K&1:D&1:w&1:z&1:x

Теперь логи превратились в чистый перечень указателей. Каждая строка &1:o читается так: “Возьми шаблон &1 (который раскрывается в !26!#@#!3!), подставь вместо @ значение o, и получишь исходную строку лога”.

Результат пятого этапа: 45 839 символа → 10 192 символов. Финальное сжатие 78.4%!

Бонус: Производительность

PowerShell — хорошо подходит для быстрой автоматизации на коленке, но он медленно работает с циклами по массивам строк и вложенными итерациями. Это приводило к долгой задержке вставки, которая могла доходить до 20 секунд. В итоге ИИ переписал мне все на Rust и теперь вставка происходит мгновенно.

Как это работает с нейросетями?

Возникает вопрос: “А поймут ли нейросети такой формат? Не запутается ли модель в этих тегах?”

Ответ — не только поймут, но работают с ним даже лучше, чем с сырыми логами.

1. LLM обучены на структурированных данных

Современные нейросети тренируются на коде, JSON, YAML, markdown. Когда модель видит блок --- LEGEND --- с парами “ключ = значение”, она автоматически понимает: это словарь, нужно держать его в контексте. Ей не нужно объяснять как работать с этим форматом — она сама “разворачивает” теги в уме.

2. Фокус на аномалиях

Это самое важное. Когда вы вставляете в чат 1000 строк с одинаковым текстом [WinFocusMonitor] workerMain: hwnd=..., внимание модели (attention mechanism) “размазывается” по повторяющемуся мусору.

В сжатом формате модель видит:

&24:o&24:E&24:K&24:D

Для нейросети это идеальный сигнал: “Ага, структура строки идентична, меняется только один параметр. Давай-ка посмотрю в легенде, что означают o, E, K, D, и сфокусируюсь на отличиях”.

Ошибки и аномалии в таком формате буквально светятся. Если вдруг среди десяти &24:K появится &24:X или вообще &25:K — модель мгновенно увидит нарушение паттерна.

3. Экономия контекстного окна

Даже у самых продвинутых моделей есть проблема: чем больше контекст, тем больше “забывчивость”.

Сэкономив до 80% символов на логах, вы оставляете модели больше “оперативной памяти” для:

  • Удержания архитектуры вашего проекта

  • Истории текущего чата

  • Написания качественного кода в ответе

Модель не “забудет” контекст задачи из-за раздутого лога.

4. Нет галлюцинаций

Ключевое отличие данного подхода от “попросить ИИ сократить лог” — мы сжимаем математически, а не через пересказ. Все миллисекунды, hex-адреса, коды ошибок остаются на своих местах. Алгоритм BPE гарантирует нулевую потерю данных.

Как использовать?

Приложение доступно пока только для windows. Работает следующим образом:

  1. Копируете сырые логи из терминала/файла (Ctrl+C)

  2. Переключаетесь в любой чат

  3. Нажимаете Ctrl+Alt+V вместо обычного Ctrl+V

  4. Вставляются сжатые логи

  5. Бонус: исходные логи автоматически восстанавливаются в буфере обмена (на случай, если нужно вставить оригинал куда-то ещё)

Исходный код проекта доступен на GitHub. Вы можете за пару минут портировать этот алгоритм под свою платформу, а также доработать под свои нужды.

ссылка на оригинал статьи https://habr.com/ru/articles/1026040/