Контекстное окно

Материал из llmdocs — справочник разработчика
Контекстное окно
Единица измерениятокены
Что входитсистемный промпт, история диалога, документы, результаты инструментов, ответ модели
Ранние моделиGPT-3 — 2048 токенов (2020)
Современные моделиот 128 тыс. до 1 млн токенов и больше
Ограничивающий факторквадратичная сложность внимания, память KV-кэша
Связанные эффекты«потеря в середине», рост стоимости и задержки

Контекстное окно — максимальный объём текста, измеряемый в токенах, который языковая модель может учитывать при обработке одного запроса. В окно входит всё сразу: системные инструкции, история диалога, приложенные документы, описания инструментов и результаты их вызовов, а также ответ, который модель генерирует. Всё, что за пределами окна, для модели не существует: у неё нет памяти между запросами, кроме того, что передано в контексте.[2]

Как менялся размер

Период Типичный размер окна
2020 (GPT-3) 2 048 токенов[4]
2023 8–32 тыс., затем 100–200 тыс. токенов
2024–2026 от 128 тыс. до 1 млн токенов и больше

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

Почему окно ограничено

Механизм внимания в трансформере сравнивает каждый токен с каждым, поэтому вычисления растут квадратично с длиной входа. Кроме того, при генерации модель хранит ключи и значения всех предыдущих токенов (KV-кэш), и его объём растёт линейно, занимая память GPU. Модели также нужно уметь работать с позициями, которых не было при обучении: для расширения окна применяют масштабирование позиционных кодировок (например, YaRN) и дообучение на длинных текстах.[3]

Заявленный и эффективный контекст

То, что текст помещается в окно, не значит, что модель одинаково хорошо использует все его части.

  • Потеря в середине. Исследование 2023 года показало, что модели лучше всего извлекают информацию из начала и конца длинного контекста и хуже — из середины.[1] Новые модели заметно улучшили этот показатель, но эффект полностью не исчез.
  • «Иголка в стоге сена». Популярный тест — спрятать факт в длинный текст и попросить его найти. Простой поиск современные модели проходят почти идеально, но задачи, требующие сопоставить много фактов из разных мест, даются заметно хуже; бенчмарки вроде RULER оценивают «реальный» размер контекста.[6]
  • Отвлечение. Нерелевантный текст в контексте может ухудшать ответы, поэтому «положить всё» не всегда лучше, чем отобрать нужное.

Стоимость и задержка

Входные токены оплачиваются при каждом запросе. В многошаговом диалоге или работе агента вся история отправляется заново на каждом шаге, поэтому стоимость растёт быстро. Длинный контекст увеличивает и время до первого токена ответа. Повторяющуюся часть запроса — системный промпт, документацию, описание инструментов — выгодно кэшировать на стороне провайдера: это снижает цену и задержку (см. Кэширование промптов).[5]

Управление контекстом

Длинный контекст не отменяет необходимости им управлять:

  1. Отбор вместо загрузки всего. RAG находит и подставляет только релевантные фрагменты; документы при этом режут на части (см. Чанкинг документов).
  2. Сжатие истории. Старые сообщения диалога заменяются кратким пересказом, а длинные результаты инструментов — выжимкой.
  3. Структура. Важные инструкции размещают в начале или повторяют в конце, документы оборачивают в явные разделители или теги.
  4. Компактные форматы. Чистый Markdown вместо HTML, удаление повторов и служебного текста экономит токены (см. Markdown как формат для LLM и llms.txt).
  5. Внешняя память. Агенты сохраняют заметки и промежуточные результаты в файлы или базы и подгружают по необходимости, вместо того чтобы держать всё в окне.

Окно и длина ответа

У многих моделей отдельно ограничено число токенов в ответе (max_tokens): оно меньше общего окна, а сумма входа и выхода не может превышать окно. Если ответ упирается в лимит, генерация обрывается на полуслове — это стоит проверять в коде по признаку причины остановки, а не только по тексту ответа.

resp = client.messages.create(model="claude-sonnet-5-5", max_tokens=2048, messages=msgs)
if resp.stop_reason == "max_tokens":
    print("Ответ обрезан — увеличьте max_tokens или попросите продолжить")
print(resp.usage.input_tokens, resp.usage.output_tokens)

См. также

Источники

  1. N. F. Liu et al. — Lost in the Middle: How Language Models Use Long Contexts (2023)
  2. Anthropic — Context windows
  3. B. Peng et al. — YaRN: Efficient Context Window Extension of Large Language Models (2023)
  4. T. Brown et al. — Language Models are Few-Shot Learners (2020)
  5. Anthropic — Prompt caching
  6. C.-P. Hsieh et al. — RULER: What's the Real Context Size of Your Long-Context Language Models? (2024)