Проблема: больше контекста ≠ лучше
Интуиция подсказывает: раз окно 200k токенов, надо использовать его целиком — вся история, все документы, все инструменты. На практике это ухудшает агента сразу по трём осям.
| Ось | Что происходит при раздутом контексте |
|---|---|
| Качество | Модель хуже находит нужное среди шума, путается, следует не тем инструкциям |
| Стоимость | Платишь за каждый входной токен на каждом шаге агента — растёт квадратично по ходу диалога |
| Латентность | Больше входных токенов → дольше обработка → выше время ответа |
Особенно коварна экономика: у агента каждый шаг reasoning отправляет весь накопленный контекст заново. Диалог из 10 шагов с растущей историей — это не 10 отправок по 1k токенов, а 1k+2k+3k+…: суммарно на порядок больше. Раздутый контекст бьёт по счёту тем сильнее, чем длиннее работает агент.
Ключевой эффект, который надо принять: способность модели надёжно использовать информацию деградирует по мере роста контекста. Известное проявление — «lost in the middle»: факты в начале и в конце промпта модель использует заметно лучше, чем закопанные в середине. Практический вывод: 200k-окно — это не «200k полезной памяти», а верхняя техническая граница, у которой качество уже не то. Помещается ≠ работает. Важное клади ближе к краям (особенно к концу) и убирай лишнее.
Бюджет контекста
Первый шаг инженерного подхода — перестать считать контекст «бесконечным» и начать считать его бюджетом: сколько токенов на что тратится. У агента конкуренты за окно всегда одни и те же.
Практика бюджетирования проста: прикинь лимит на каждую статью и следи, чтобы сумма не приближалась к окну (оставив место под ответ). Например: system — до 1k, инструменты — до 2k, RAG — до 4k, история — до 8k. Как только история упирается в свой лимит — включается сжатие (ниже), а не «пусть растёт, окно большое».
Управление историей диалога
История — главный «пожиратель» контекста у агента, потому что она единственная растёт неограниченно. Основные стратегии (часто комбинируют):
| Стратегия | Как работает | Минус |
|---|---|---|
| Sliding window | Держим последние N сообщений, старые выбрасываем | Полная потеря ранних деталей |
| Summarization | Старую часть сжимаем в краткую сводку (LLM) | Стоит вызова; сводка теряет нюансы |
| Обрезка tool-выходов | Огромные ответы инструментов урезаем/суммаризируем | Можно срезать нужное |
| Вынос наружу | Детали в файл/БД, в контексте — только ссылка | Нужен инструмент чтения |
KEEP_RECENT = 6 # последние сообщения — дословно
HISTORY_BUDGET = 8000 # лимит токенов на историю
def compact_history(messages: list, summary: str | None):
if count_tokens(messages) <= HISTORY_BUDGET:
return messages, summary # влезаем — ничего не делаем
recent = messages[-KEEP_RECENT:] # хвост важен: свежий контекст
older = messages[:-KEEP_RECENT]
# старое сжимаем в сводку (доклеивая к предыдущей — сводка накопительная)
summary = llm(f"""Кратко суммируй ход диалога, сохранив:
решения, факты, незакрытые задачи. Предыдущая сводка: {summary or '—'}
Новые сообщения: {render(older)}""", temperature=0)
# сводка идёт как system-сообщение ПЕРЕД свежими
return [{"role": "system", "content": f"Сводка ранее: {summary}"}] + recent, summary
# обрезаем и «толстые» ответы инструментов — они раздувают историю быстрее всего
def trim_tool_output(text: str, limit: int = 2000) -> str:
return text if len(text) <= limit else text[:limit] + "\n…[обрезано]"
Самый дешёвый выигрыш: ответы инструментов (JSON API, дампы поиска, HTML страницы) часто занимают больше, чем весь остальной диалог, а полезной информации в них — пара строк. Обрезай/суммаризируй их до попадания в историю, а не потом. Правило: инструмент должен возвращать ответ, а не сырые данные. Это же снижает риск того, что модель утонет в мусоре и потеряет инструкцию.
Отбор: инструменты и документы
История — не единственный источник раздувания. Два других — описания инструментов и RAG-документы, и оба лечатся отбором.
- Инструменты. Описания всех tools уходят в каждый запрос. 40 инструментов — это тысячи токенов на каждом шаге, плюс модели труднее выбрать нужный. Решение: давать только релевантные текущей задаче (динамический отбор по этапу/намерению) — прямая связь с Skills-роутингом из модуля 05.
- RAG-документы. Соблазн «дадим top-50 чанков, вдруг пригодится» вредит: релевантное тонет в шуме (context rot). Лучше меньше, но точнее — качественный retrieval и reranking важнее объёма (модуль 04).
- Порядок важен. Раз середина работает хуже — критичные инструкции и самые релевантные документы ставь ближе к концу промпта, ближе к вопросу.
Каждый лишний блок в контексте не нейтрален: он стоит денег, добавляет латентность и снижает вероятность, что модель заметит действительно нужное. Правильный вопрос не «влезет ли?», а «изменит ли это ответ?». Если блок не влияет на решение — он не должен попадать в окно. Контекст — не склад, а рабочий стол: чем чище, тем точнее работа.
Изоляция контекста через субагентов
Мощная структурная техника (мостик к модулю 05): если задача требует много «грязной» работы с большими данными, вынеси её в субагента с отдельным контекстным окном. Субагент перелопачивает документы в своём окне и возвращает наверх короткую выжимку, а не сырьё.
❌ Один агент на всё:
главный контекст ← 50 документов + история + всё подряд → распух, качество ↓
✅ Изоляция через субагента:
главный агент (чистый контекст, видит только итоги)
│ «изучи эти 50 документов по теме X»
▼
субагент (СВОЙ контекст: 50 документов, черновая работа)
│ возвращает выжимку на 300 токенов
▼
главный агент ← +300 токенов вместо +40 000
Грязная работа — в изолированном окне, наверх — только результат.
Это тот же принцип, что «агент-как-инструмент» из модуля 05: снаружи виден компактный результат, а сложность (и раздутый контекст) спрятаны внутри. Так же работают и файлы как внешняя память: агент пишет промежуточные результаты в файл и читает нужное по требованию, вместо того чтобы тащить всё в окне.
Сводя воедино: сжимай (суммаризация истории, обрезка tool-выходов), отбирай (только нужные инструменты и документы, важное — ближе к концу), изолируй (субагенты и внешняя память вместо одного распухшего окна). Эти три рычага решают почти все проблемы с контекстом — и одновременно снижают стоимость и латентность, о которых пойдёт речь в следующих уроках раздела.
Типичные ошибки
Помещается ≠ работает. Длинный контекст роняет качество (context rot), стоимость и скорость. Считай бюджет, а не заполняй окно до предела.
Агент шлёт всю историю на каждом шаге — расходы растут лавинообразно, качество падает. Нужны sliding window + суммаризация с лимитом токенов.
Дампы API/поиска занимают больше всего места при минимуме пользы. Обрезай и суммаризируй их до попадания в историю.
Описания всех tools и лишние документы уходят в каждый запрос, топя релевантное в шуме. Отбирай динамически, важное ставь ближе к концу.
Шпаргалка
КОНТЕКСТ = ограниченный ДОРОГОЙ ресурс с убывающей отдачей (не бесконечная память)
больше ≠ лучше: КАЧЕСТВО↓ (context rot) · СТОИМОСТЬ↑ · ЛАТЕНТНОСТЬ↑
CONTEXT ROT: чем длиннее, тем хуже модель находит нужное
«lost in the middle» — края работают лучше середины · ПОМЕЩАЕТСЯ ≠ РАБОТАЕТ
ЭКОНОМИКА АГЕНТА: каждый шаг шлёт ВЕСЬ накопленный контекст ЗАНОВО
10 шагов ≠ 10×1k, а 1k+2k+3k+… → раздутый контекст бьёт тем сильнее, чем дольше работа
БЮДЖЕТ КОНТЕКСТА (лимит на каждую статью, + место под ОТВЕТ):
system · описания tools · ИСТОРИЯ (растёт!) · RAG-документы · запрос
3 РЫЧАГА:
① СЖИМАЙ: sliding window (последние N) · summarization старого (накопительная сводка) ·
ОБРЕЗКА TOOL-ВЫХОДОВ (самый дешёвый выигрыш!) · вынос деталей в файл/БД
правило: инструмент возвращает ОТВЕТ, а не сырые данные
② ОТБИРАЙ: только релевантные tools (40 tools = тысячи токенов КАЖДЫЙ шаг) ·
меньше, но точнее чанков (reranking > объём) · важное БЛИЖЕ К КОНЦУ
вопрос не «влезет ли?», а «ИЗМЕНИТ ЛИ ЭТО ОТВЕТ?»
③ ИЗОЛИРУЙ: субагент со СВОИМ окном делает грязную работу → наверх выжимка (300 токенов
вместо 40 000) · файлы как внешняя память · = «агент-как-инструмент» (модуль 05)
ГРАБЛИ: «окно большое — влезет всё» · безлимитная история · сырые tool-выходы ·
все tools + top-50 чанков всегда
Практическое задание
Задание: наведи порядок в контексте агента
- Для агента из модулей 03–05 замерь по трейсу (LangSmith/Langfuse), сколько входных токенов уходит на шаге 1 и на последнем шаге. Во сколько раз вырос контекст?
- Разложи контекст по статьям (system / tools / история / RAG / запрос): что занимает больше всего? Назначь бюджет каждой статье.
- Найди самый «толстый» ответ инструмента. Сколько в нём полезного? Добавь обрезку/суммаризацию до попадания в историю — насколько упал общий контекст?
- Реализуй гибрид: последние N сообщений дословно + накопительная сводка старых. Проверь, что агент не теряет ключевые решения из ранней части диалога.
- Посчитай, сколько токенов занимают описания всех твоих инструментов. Можно ли давать не все? По какому признаку отбирать?
- Найди задачу, которую стоит вынести в субагента с изолированным контекстом. Сколько токенов это сэкономит главному агенту?
- Со звёздочкой: прогони offline-оценку (раздел «Оценка качества») до и после сжатия контекста. Качество сохранилось? Насколько упала стоимость запроса?
Что дальше
Мы сократили контекст до необходимого. Но часть его неизбежно повторяется в каждом запросе: системный промпт, описания инструментов, инструкции. Платить за них заново на каждом шаге — расточительство, и провайдеры дают способ этого избежать. Следующий урок — prompt caching: как кэшировать неизменную часть промпта и экономить до 90% стоимости.