Длинный контекст
Контекстное окно — это сколько токенов модель может учитывать одновременно: промпт, документы, весь диалог и её собственный ответ. Оно выросло с 2048 токенов у GPT-3 до 128 000 у многих открытых моделей сегодня, а некоторые коммерческие модели принимают миллион и больше. Длинный контекст позволяет модели прочитать целую кодовую базу или книгу за раз. Но он приносит три проблемы: стоимость, точность и само кодирование позиций.
Проблема 1: стоимость
С длиной контекста растут две вещи:
- Память. KV-кэш хранит ключи и значения каждого токена: он растёт линейно, .
- Вычисления. Запрос каждого токена сравнивается с каждым предыдущим ключом. Число пар растёт квадратично, .
Все остальные умножения матриц (проекции и MLP) стоят одинаково на каждый токен, поэтому растут линейно. Вычисления префилла примерно равны
для параметров, слоёв и ширины модели (длины вектора каждого токена). Первое слагаемое — одно умножение и одно сложение на каждый параметр для каждого токена. Второе считает само внимание: примерно пар токенов (каждый смотрит только на предыдущие), и в каждом слое каждая пара стоит скалярного произведения длины ради оценки и ещё умножений-сложений, чтобы подмешать значение, — около операций.
На коротких промптах побеждает первое слагаемое. После длины, где они равны, , доминирует внимание, и кривая стоимости загибается вверх. Для Llama 3 8B это токенов.
Формы как у Llama 3 8B и 70B; «без GQA» — у каждой головы запросов свои ключи и значения.
Декодирование тоже чувствует длину — через память, а не через арифметику. Каждый шаг декодирования читает весь кэш (глава 10 объясняет, почему скорость декодирования задаёт чтение, а не вычисления). На 128k токенах кэш модели на 8B размером с её веса, так что каждый новый токен выходит примерно вдвое дольше, чем с коротким промптом.
Групповое внимание, квантизация KV и другие приёмы из главы Кэширование бьют по линии памяти. FlashAttention (Быстрый инференс) делает квадратичные вычисления быстрыми и экономными по памяти, но они остаются квадратичными. Чтобы изменить сам показатель степени, нужен другой шаблон внимания — об этом ниже.
Проблема 2: а пользуется ли им модель?
Модель, которая принимает миллион токенов, не обязательно хорошо их использует. Это показали два эксперимента.
Потеря в середине (Lost in the Middle, Liu и др., 2023): моделям давали 20 найденных документов, ответ был только в одном, и этот документ передвигали. Точность была выше всего, когда он стоял первым или последним, и резко падала в середине — в худшем случае почти до уровня ответа вообще без документов. Иголка в стоге сена (needle in a haystack) прячет одно чужеродное предложение на заданной глубине длинного текста и просит его найти, перебирая и глубину, и длину.
Условные числа, повторяющие форму опубликованных результатов, а не замеры конкретной модели.
Новые модели проходят простой тест с иголкой почти идеально, поэтому теперь используют более сложные (RULER, тесты с несколькими иголками и многошаговые, где ответ требует связать несколько фактов). Они по-прежнему показывают, что эффективный контекст — длина, на которой модель сохраняет качество короткого контекста, — часто заметно меньше заявленного и что качество медленно падает по мере добавления нерелевантного текста. Это называют «гниением контекста» (context rot).
Почему U-образная кривая? Причины всё ещё обсуждают; обычно называют три. В обучающих данных редко нужна информация из середины очень длинных текстов; шаблоны внимания тяготеют к началу («сток внимания» из главы Кэширование) и к самым последним токенам; а при причинном внимании ранние токены обрабатываются, когда вопрос ещё неизвестен.
Проблема 3: позиции, которых модель не видела
RoPE кодирует позицию, поворачивая пары чисел в каждом запросе и ключе, каждую пару со своей скоростью. Быстрые пары делают много полных оборотов в пределах обучающей длины, медленные — меньше одного. Модель, обученная на 4096 токенах, никогда не видела медленные пары повёрнутыми дальше их угла на 4k. Дайте ей позицию 30 000 — эти пары окажутся на незнакомых углах, и внимание сломается.
Все исправления сжимают позиции обратно в обученный диапазон:
- Интерполяция позиций (PI) делит каждую позицию на = целевая длина / обучающая длина. Все углы помещаются, но соседи теперь в раз ближе, и быстрые пары размываются.
- NTK-aware масштабирование (название — от теории о том, как учатся сети, «нейронного касательного ядра», neural tangent kernel) вместо этого увеличивает основание RoPE (то самое 10 000, которое задаёт скорости вращения, глава 4): быстрые пары почти не меняются, медленные растягиваются сильнее всего.
- YaRN обрабатывает каждую пару отдельно: пары, уже сделавшие много оборотов, не трогает, медленные интерполирует, между ними — плавный переход, плюс небольшая поправка температуры внимания — множителя, который делает softmax внимания чуть резче, примерно как температура при сэмплировании. Многие открытые модели с длинным контекстом используют YaRN или близкие методы.
5 из 10 показанных пар выходят за обученный диапазон
Позиции дальше 4k поворачивают медленные пары на углы, которых при обучении не было. Оценки внимания там непредсказуемы, и качество разваливается.
Одного масштабирования для лучшего качества мало. На практике модели предобучают на умеренной длине (4k–8k), а затем продолжают обучение на длинных документах, наращивая контекст по этапам до 128k и дальше. Эта последняя фаза занимает малую долю вычислений, но учит модель действительно пользоваться далёкими токенами.
Более дешёвые шаблоны внимания
Чтобы изменить квадратичный показатель, токен должен перестать смотреть на каждый предыдущий токен. Разреженное внимание оставляет структурированное подмножество. В главе 5 было видно, какие оценки эти шаблоны пропускают; здесь вопрос в дальности. Если токен не видит далёкое прошлое напрямую, может ли информация оттуда всё же до него добраться?
После этих слоёв токен 15 может опираться на 4 из 16 токенов
Нажмите на строку, чтобы выбрать токен-запрос.
Каждый токен видит только последние w = 4. Стоимость линейная; информация всё равно проходит w − 1 токенов за слой, поэтому глубокая сеть дотягивается далеко (Mistral 7B, многие гибридные модели).
- Скользящее окно (Mistral 7B, а в моделях вроде Gemma — чередуется со слоями полного внимания) стоит — работа растёт как длина, умноженная на окно, а не как квадрат длины, — и держит KV-кэш размером токенов на слой.
- Глобальные токены и стоки добавляют несколько позиций, видимых всем (Longformer, BigBird, StreamingLLM).
- Обучаемое разреженное внимание позволяет модели для каждого запроса выбирать, какие блоки предыдущих токенов читать, как в разреженном внимании DeepSeek и Native Sparse Attention.
- Некоторые архитектуры вообще отказываются от растущего кэша внимания и хранят состояние фиксированного размера: см. За пределами классического трансформера.
Очень длинным контекстам нужно больше одного GPU на последовательность. Кольцевое внимание (ring attention) и параллелизм по контексту делят последовательность между устройствами: каждое хранит часть запросов, а блоки ключей и значений передаются по кольцу, и передача идёт одновременно с вычислениями.
Длинный контекст на практике
- Длинный контекст или поиск? Сложить всё в промпт просто, и модель может связывать далёкие факты, но это медленно, дорого и страдает от «гниения контекста». Поиск (RAG) отправляет только нужные куски. Многие системы совмещают оба подхода: находят с запасом, а потом дают прочитать модели с длинным контекстом.
- Вопрос — в конец, важное — ближе к началу или концу. Эффект потери в середине у новых моделей меньше, но редко равен нулю.
- Кэшируйте длинную стабильную часть. Большой документ и много вопросов к нему — идеальный случай для кэширования промптов.
- Агенты сжимают историю. Долго работающие агенты пересказывают или выбрасывают старые результаты инструментов, ведут заметки в файлах и запускают подзадачи в свежих контекстах, а не дают контексту заполниться шумом.
Итоги
- KV-кэш растёт линейно с контекстом, вычисления внимания — квадратично; после нескольких десятков тысяч токенов доминирует внимание.
- Принять длинный контекст ещё не значит им пользоваться: поиск проседает в середине и ухудшается с длиной.
- RoPE за пределами обучающей длины нужно масштабировать (PI, NTK-aware, YaRN) и дообучать модель на длинных документах.
- Разреженные шаблоны, скользящие окна и архитектуры с состоянием атакуют квадратичную стоимость; кольцевое внимание распределяет одну последовательность по многим GPU.
Длинный контекст — один способ сделать модель дорогой, сам размер модели — другой. Следующая глава о том, как удешевить запуск и дообучение больших моделей: смесь экспертов, квантизация и LoRA.