Обрезка контекста LLM без потери смысла: окна и сводки
Обрезка контекста LLM помогает держать диалог в рамках лимита токенов: разберем окна, приоритеты, сводки истории и быстрые проверки.

Почему диалог теряет фокус
Проблема обычно начинается не с модели, а с длины переписки. Каждая новая реплика тратит токены, и окно контекста заполняется быстрее, чем кажется. Пять минут живого разговора с уточнениями, цитатами и вставками из логов легко превращаются в длинный хвост текста, где полезного уже меньше половины.
Модель сильнее опирается на то, что видит прямо сейчас. Если в начале вы задали строгие правила, формат ответа и границы задачи, а потом добавили двадцать сообщений с новыми деталями, ранние условия уходят далеко назад. Формально они еще есть в истории. По факту поздние реплики начинают их перекрывать.
Особенно быстро место съедают повторы. Вежливые фразы, дубли вопросов, пересказ уже сказанного, длинные подтверждения вроде "да, верно, продолжай" почти не добавляют смысла. Для человека это обычный разговорный шум. Для модели это такой же текст, как и важное требование.
Из-за этого память бота кажется хуже, чем она есть. Он не "забыл" задачу в человеческом смысле. Он просто получил слишком много слабого сигнала и слишком мало плотного контекста. В итоге ответ смещается к последнему вопросу, а не к общей цели диалога.
Чаще всего окно контекста забивают четыре вида мусора:
- повторные инструкции теми же словами
- пустые фразы вежливости
- длинные цитаты переписки без отбора
- побочные ветки, которые уже не нужны
Представьте внутреннего помощника для банка или ритейла. В первом сообщении ему дали правила: не выдумывать цифры, отвечать кратко, держать формат таблицы. Через десять ходов пользователь начал спорить с формулировками, копировать старые ответы и добавлять новые исключения. Если не сокращать историю и не делать сводку, модель скоро начнет отвечать по ближайшему смыслу. Она выберет свежий кусок разговора и пропустит старые ограничения.
Поэтому потеря фокуса почти всегда связана не с "магией" модели, а с плохим управлением токенами. Если история растет без правил, диалог расползается даже у сильных моделей.
Что стоит держать в истории
Если отправлять модели весь лог целиком, она тратит токены на шум и чаще уходит в сторону. В истории должно остаться только то, что двигает текущую задачу: чего пользователь хочет сейчас, о чем уже договорились и что еще не решено.
Сначала сохраните цель текущего запроса. Лучше в короткой формулировке, без длинной переписки вокруг нее. Если человек пять раз перефразировал одну и ту же просьбу, оставьте последнюю и самую точную версию.
Почти всегда нужно держать под рукой такие детали:
- числа: бюджеты, лимиты, проценты, объемы
- сроки: дедлайны, даты запуска, период отчета
- роли: кто утверждает, кто пишет, кто проверяет
- жесткие ограничения: нельзя упоминать бренд, нужен русский язык, ответ до 500 слов
- последние решения и открытые вопросы
Именно эти вещи модель теряет первой, когда контекст переполнен. Тогда она начинает менять цифры, забывает дедлайн или возвращается к уже закрытому спору.
Полезно хранить не всю цепочку обсуждения, а только принятые решения. Допустим, команда уже решила, что отчет нужен для CFO, тон должен быть нейтральным, а таблицы не нужны. Этого достаточно. Длинный спор о том, почему таблицы не подошли, обычно можно убрать.
С незавершенными вопросами правило простое. Если без ответа на них нельзя сделать следующий шаг, они остаются в истории. Если вопрос был проходным и на итог не влияет, его лучше вырезать.
Еще один частый мусор - приветствия, подтверждения и пустые уточнения. Фразы вроде "спасибо", "принято", "делай", "попробуй еще раз" редко несут смысл. Повторы тоже не нужны, особенно если модель уже получила более свежую формулировку.
Хороший ориентир такой: каждый фрагмент истории должен отвечать на вопрос "что сломается, если это убрать?" Если ничего, удаляйте. Если исчезнет ограничение, число или нерешенный выбор, оставляйте. Тогда окно контекста работает на задачу, а не хранит весь разговор ради самого разговора.
Как работает окно контекста
Окно контекста - это та часть переписки, которую модель видит в текущем запросе. Все, что в него не попало, для нее как будто исчезло. Поэтому ответ зависит не от всей истории диалога, а только от того набора сообщений, который вы передали.
Из-за этого команды часто путают хранение истории и передачу истории. У вас может быть полный лог за месяц, но в модель нужно отправлять только нужный срез. В этом и состоит обрезка контекста LLM: оставить то, без чего ответ сломается, и убрать все остальное.
Удобно разделить контекст на четыре слоя. Системные правила лучше держать отдельно от переписки: формат ответа, запреты, тон, требования по безопасности. Последние реплики обычно стоит передавать целиком, потому что в них есть текущая цель и свежие ограничения. Факты, которые нельзя терять, нужно закреплять вне скользящего окна: номер договора, язык ответа, выбранный тариф, роль пользователя. Старые ветки диалога лучше сжимать в короткую сводку, иначе окно быстро забьется деталями, которые уже отработали.
Скользящее окно работает просто: с каждым новым сообщением старые куски начинают выпадать. Если полагаться только на этот механизм, модель забудет то, что было важно десять минут назад. Поэтому постоянные правила и закрепленные факты не стоит смешивать с обычной перепиской.
Хороший пример - внутренний чат поддержки. Пользователь пять сообщений обсуждал возврат, потом спросил про доставку, а затем вернулся к возврату. Если хранить только последние реплики, модель легко утащит разговор в сторону. Если же рядом есть короткая сводка вроде "клиент уже подтвердил номер заказа и просит возврат за один товар", ответ остается точным даже после смены темы.
На практике схема часто выглядит так: постоянные инструкции, затем закрепленные факты, затем краткая сводка прошлого, и только после этого последние сообщения целиком. Такой порядок помогает модели не терять смысл и не тратить токены на шум.
Как сокращать историю по шагам
Если отправлять в модель весь лог целиком, она тратит токены на старые повторы и лишние детали. Историю лучше чистить перед каждым новым запросом по одному короткому сценарию.
- Сначала сформулируйте цель текущего хода в одном предложении. Не "продолжить диалог", а конкретное действие: "подготовить ответ клиенту по возврату" или "сравнить два варианта договора".
- Затем отметьте факты, без которых ответ сломается. Обычно это числа, даты, имена сущностей, выбранный формат, уже принятые решения и фрагменты текста, на которые модель должна опираться.
- Старую часть диалога сожмите в короткую сводку на 5-7 строк. Оставьте только смысл: чего хотел пользователь, к чему пришли, что уже проверили, какие варианты отбросили.
- Проверьте, что в окне контекста остались ограничения и открытые задачи. Ограничения часто теряются первыми, хотя именно они держат ответ в рамках.
- Только после этого отправляйте запрос. Если токенов все еще много, режьте примеры, повторы и старые объяснения. Не режьте правила, факты и незакрытые вопросы.
Хорошая обрезка контекста LLM похожа на работу редактора. Вы не переписываете весь разговор, а оставляете только то, без чего следующий ответ станет хуже.
Небольшой пример. Пользователь десять сообщений обсуждал интеграцию, а потом попросил составить короткий план запуска. Для нового запроса не нужен весь спор о моделях и ценах. Нужны цель, выбранный стек, срок запуска, ограничения по данным и список нерешенных пунктов. Остальное можно свернуть в несколько строк.
Если команда использует единый шлюз для доступа к моделям, такой порядок особенно удобен. Например, в AI Router можно менять маршрут до модели, но правило остается тем же: сначала сократить историю до рабочего ядра, потом отправить запрос. Это экономит токены и заметно уменьшает число ответов, где модель уходит в сторону.
Когда сводка лучше полного лога
Полный лог нужен не всегда. После длинной ветки обсуждения модель начинает тратить окно контекста на повторы, старые версии решений и мелкие отступления. В этот момент сводка истории диалога работает лучше, чем десятки прошлых сообщений подряд.
Обычно сводку стоит делать в двух случаях. Первый - когда одна тема уже закрыта и команда пошла дальше. Второй - когда разговор заметно сменил направление. Сначала обсуждали классификацию обращений, потом перешли к тексту ответа, лимитам и правилам безопасности. Для обрезки контекста LLM это один из самых полезных шагов.
Сводку пора обновить, если произошло что-то из этого: выбрали вариант и отказались от других, сменили тему или подзадачу, появились новые ограничения, модель снова спрашивает то, что уже решили.
Но сырой лог не стоит выбрасывать всегда. Если важны точные слова, храните исходную переписку и при необходимости подмешивайте нужный фрагмент обратно в окно контекста. Это относится к юридическим формулировкам, системным промптам, SQL запросам, параметрам API, числам, срокам и обещаниям клиенту. Сводка не заменяет источник. Она только помогает текущему диалогу держать фокус.
Частая ошибка - делать сводку слишком общей. Фраза вроде "решили улучшить ответ" почти бесполезна. Модели нужен рабочий смысл: "ответ не длиннее 500 знаков, без диагноза, с советом обратиться к врачу, если есть тревожные симптомы". Такая запись занимает мало места, но сохраняет договоренности.
Сводку лучше обновлять после каждого заметного решения, а не в конце длинной сессии. Тогда память бота остается ровной, без скачков и потерь. Если новых решений не было, переписывать ничего не нужно.
Хорошее правило простое: полный лог храните для точности, сводку держите для работы. После 30-40 сообщений в активном окне часто хватает 6-8 строк с целью, ограничениями, принятыми решениями и спорными вопросами.
Пример на реальном сценарии
Представьте чат поддержки интернет-магазина. Клиент сначала пишет, что хочет вернуть товар, потому что размер не подошел. В первых сообщениях модели нужны конкретные данные: номер заказа, дата покупки, срок возврата и правила по этой категории товара. Полезно держать рядом и обещанный срок ответа, чтобы бот не придумывал его заново.
Через несколько реплик разговор меняется. Агент уточняет состав заказа, и клиент решает оставить одну позицию, а по другой уже не просит возврат. Вместо этого он хочет поменять адрес доставки для еще не отправленной части заказа.
Если положить в окно контекста весь лог целиком, модель может зацепиться за старую цель. Она продолжит обсуждать возврат, хотя разговор уже ушел в другую сторону. Такое случается часто: ранние сообщения занимают много места и тянут ответ назад.
После десяти реплик в истории обычно накапливается шум. Там есть приветствия, повторы номера заказа, извинения, длинные формулировки клиента и фразы агента вроде "сейчас проверю". Для следующего ответа это почти не нужно. Обрезка контекста LLM хорошо работает именно здесь: она убирает повторы и оставляет факты, от которых зависит следующее действие.
Как выглядит рабочая сводка
Вместо полного лога системе достаточно передать короткую запись:
- заказ №48173
- запрос на возврат по одной позиции принят в обработку
- адрес доставки для оставшейся части заказа изменен
- агент обещал подтвердить изменения до 18:00
Этой сводки хватает, чтобы новый агент или следующий вызов модели сразу понял, что уже решено, а что еще ждет ответа. Ему не нужно читать всю переписку и разбирать, на каком шаге клиент передумал.
Такой подход полезен и человеку, и боту. Человек тратит меньше времени на вход в тему. Модель реже путает старый запрос с текущим и не расходует токены на лишние детали. Когда у команды много похожих обращений, такая память бота обычно дает ровнее ответы, чем хранение полного чата до бесконечности.
Где команды ошибаются
Команды чаще ломают диалог не в модели, а в правилах памяти. Они ставят простое ограничение по токенам, отрезают старые сообщения и думают, что этого достаточно. На практике такой подход убирает не шум, а смысловые опоры: зачем пользователь пришел, что уже запретили, какие условия нельзя нарушать.
Обрезка только по длине почти всегда дает перекос. Два коротких сообщения могут быть важнее десяти длинных. Фраза "не отправляй клиенту черновик без согласования" занимает мало места, но если она исчезнет из окна контекста, ошибка будет дорогой.
Часто вырезают отрицания, исключения и запреты, потому что они кажутся мелочами. Это одна из самых неприятных ошибок. Модель хорошо держит общий курс, но именно такие детали меняют ответ полностью: "не звони после 18:00", "не упоминай диагноз", "кроме тарифов для юрлиц". Если команда сохраняет только тему разговора и теряет ограничения, бот начинает отвечать уверенно и неверно.
Еще одна проблема - смешивание фактов пользователя с догадками модели. Пользователь сказал, что у него сеть из 12 филиалов. Это факт. Модель предположила, что ему нужен централизованный SLA. Это уже гипотеза. Если обе вещи попадут в сводку как равные, следующая версия ответа будет строиться на догадке как на истине.
Сводку тоже часто ведут неправильно. Некоторые команды переписывают ее с нуля на каждом ходе. Так они теряют стабильные правила, меняют формулировки и постепенно вносят дрейф. Лучше обновлять сводку по частям: постоянные факты отдельно, рабочие договоренности отдельно, временные задачи отдельно.
Есть и более тихая ошибка: в новый запрос тянут старые договоренности, которые уже не действуют. Пользователь поменял цель, выбрал другой формат ответа или снял прежний запрет, а система продолжает жить по старым правилам. В результате память вроде бы полная, но уже устарела.
Проверка здесь простая. Перед каждым сокращением истории спросите: это факт, ограничение или просто след разговора? Если это факт или запрет, его лучше сохранить. Если это промежуточная версия, догадка или старое решение, ее часто можно убрать без потери смысла.
Быстрая проверка перед запросом
Перед отправкой запроса полезно потратить полминуты на короткую проверку. Эта привычка часто спасает диалог от странных ответов, потери решений и лишних токенов.
Если механизм сокращения уже настроен, проблема обычно не в нем самом, а в мелких промахах. Модель получает короткую, но кривую историю и уверенно продолжает неверную линию.
- Первая строка должна сразу объяснять, что нужно сделать сейчас, без длинного вступления.
- Факты, которые нельзя искажать, должны остаться в окне: числа, даты, лимиты, статусы, суммы, сроки.
- Последнее принятое решение должно быть видно модели. Если команда уже выбрала вариант B, не нужно снова сравнивать A и B.
- В сводке должны быть только подтвержденные факты, без догадок и удобных выводов.
- Нужно оставить запас токенов под ответ. Если окно забито почти целиком, модель начнет пропускать детали или оборвет ответ на середине.
Небольшой пример хорошо это показывает. Пользователь пять сообщений назад утвердил бюджет в 2 млн тенге и срок до 15 июня. В короткой памяти осталась только общая цель проекта, а решение про бюджет выпало. В ответ модель предлагает новый план на 3 млн и с другим сроком. Формально логика у нее есть. Она просто не увидела то, что для вас уже закрытый вопрос.
Отдельно проверяйте сводки после длинных веток обсуждения. Если в них появляется фраза вроде "пользователь, вероятно, хочет ускорить запуск", это уже домысел. Лучше написать короче: "срок запуска обсуждался, итогового решения нет".
Такой контроль особенно полезен в продакшене, где у одного запроса есть цена. Если команда работает через airouter.kz, удобно отдельно смотреть и на маршрут запроса, и на лимиты, чтобы не забивать окно контекста до отказа.
Что делать дальше
Если общая схема уже понятна, не переносите ее сразу в прод. Сначала превратите обрезку контекста LLM в короткий набор проверок, где видно и стоимость, и качество ответа.
Начните с замеров. Возьмите несколько реальных диалогов и посчитайте расход токенов до сводки и после нее. Смотрите не только на среднее число, но и на длинные хвосты. Именно там бюджет утекает быстрее всего.
Потом проверьте, не просело ли качество. Один и тот же набор диалогов прогоните на двух или трех моделях. Оценивайте простые вещи: модель помнит задачу, не путает факты из прошлых ходов, не теряет ограничения, не начинает отвечать слишком общо.
Для такой проверки хватит короткого плана:
- собрать 10-15 типовых диалогов из продукта
- прогнать их в полном логе и со сводкой
- сравнить число токенов, задержку и качество ответа
- отдельно проверить длинные цепочки на 20-30 ходов
- записать, в какой момент система обновляет сводку
Длинные диалоги стоит тестировать отдельно. На коротких примерах почти все выглядит нормально, а проблемы всплывают позже: модель забывает решение, повторно задает уже закрытый вопрос или цепляется за старую версию задачи.
После тестов закрепите одно правило для всей команды. Например, обновлять сводку каждые N ходов, после смены темы или после любого шага, где пользователь меняет цель. Если у каждого сервиса будет свое правило, быстро появится хаос и спорные баги, которые трудно воспроизвести.
Если вы проводите такие тесты через совместимый с OpenAI API шлюз, сравнение обычно идет проще. В AI Router можно менять модель и провайдера без переписывания кода, SDK и промптов, поэтому команде легче увидеть, где сводка истории диалога работает хорошо, а где модель начинает терять смысл.
Хороший ориентир простой: после внедрения система должна тратить меньше токенов, держать мысль на длинной дистанции и давать почти те же ответы, что и полный лог. Если один из этих пунктов не сходится, правило сокращения истории еще сырое.
Часто задаваемые вопросы
Что такое обрезка контекста LLM простыми словами?
Это короткая чистка истории перед новым запросом. Вы оставляете цель, ограничения, факты и последние решения, а повторы, вежливый шум и старые ветки убираете.
Когда лучше держать полный лог, а не сводку?
Полный лог нужен, когда модели важны точные формулировки: условия договора, SQL, параметры API, суммы, сроки или обещания клиенту. Для обычной рабочей переписки чаще хватает короткой сводки и последних сообщений.
Что обязательно сохранять в истории диалога?
Оставляйте то, без чего следующий ответ сломается: текущую цель, числа, даты, роли, запреты, выбранный формат и открытые вопросы. Если фрагмент ничего не меняет в ответе, его можно убрать.
Что можно удалять первым без риска?
Сначала режьте приветствия, подтверждения, дубли вопросов, длинные цитаты без новой информации и закрытые побочные ветки. Такой текст занимает место, но почти не помогает модели.
Как понять, что модель уже потеряла фокус?
Обычно она начинает игнорировать старые запреты, меняет цифры, забывает срок или снова обсуждает уже закрытый выбор. Если ответ тянется к последней реплике и теряет общую цель, контекст собран плохо.
Как часто нужно обновлять сводку истории?
Обновляйте ее после заметного решения, смены темы или когда пользователь меняет цель. Если разговор идет ровно и новых договоренностей нет, переписывать сводку на каждом ходе не нужно.
Хватит ли просто передавать последние сообщения?
Нет, этого мало для длинных диалогов. Последние сообщения полезны, но без закрепленных фактов и короткой сводки модель быстро теряет старые ограничения.
Чем сводка отличается от полного лога?
Лог хранит исходные слова и весь ход разговора, а сводка держит только рабочий смысл для следующего шага. Лог нужен для точности, сводка — чтобы экономить токены и не уводить ответ в сторону.
Как не смешать факты пользователя с догадками модели?
Записывайте в сводку только то, что подтвердил пользователь или система проверила сама. Если это лишь предположение модели, помечайте его как незакрытый вопрос или не включайте вовсе.
Что быстро проверить перед новым запросом?
Перед отправкой проверьте четыре вещи: понятна ли текущая задача, видны ли числа и сроки, осталось ли последнее решение и есть ли запас токенов под ответ. Такая проверка занимает меньше минуты и часто спасает от странных ответов.