Методы решения проблемы длинного контекста в LLM

Курс рассматривает технические ограничения механизма внимания и современные способы их преодоления для обработки больших объемов данных. Слушатели изучат архитектурные оптимизации, методы масштабирования позиционного кодирования и альтернативные подходы к управлению памятью моделей.

1. Фундаментальные ограничения: Квадратичная сложность Self-Attention и проблема «Lost in the Middle»

Фундаментальные ограничения: Квадратичная сложность Self-Attention и проблема «Lost in the Middle»

Добро пожаловать на курс «Методы решения проблемы длинного контекста в LLM». Мы начинаем погружение в одну из самых актуальных областей современного искусственного интеллекта. Почему возможность загрузить в нейросеть целую книгу, кодовую базу или юридический архив так важна? Потому что это превращает LLM из простого чат-бота в мощный аналитический инструмент.

Однако, несмотря на стремительный прогресс, мы всё ещё сталкиваемся с ограничениями. Почему мы не можем просто сделать контекстное окно бесконечным? Почему GPT-4 или Claude 3, имея огромные окна контекста, иногда «забывают» информацию, находящуюся в середине текста? В этой статье мы разберем физические и архитектурные барьеры, стоящие на пути к бесконечной памяти.

Механизм Self-Attention: Сердце Трансформера

Чтобы понять проблему, нужно взглянуть на то, как работают современные языковые модели (LLM). В основе архитектуры Transformer лежит механизм Self-Attention (самовнимания). Его задача — определить, насколько каждое слово (токен) в предложении связано с каждым другим словом.

Представьте фразу: «Банк заблокировал карту, потому что она была скомпрометирована». Чтобы понять, к чему относится слово «она», модель должна «обратить внимание» на слово «карта», а не на «банк».

Математически это выражается следующей формулой:

Где:

  • (Query) — матрица запросов (то, что мы ищем).
  • (Key) — матрица ключей (то, где мы ищем).
  • (Value) — матрица значений (содержание информации).
  • — транспонированная матрица ключей.
  • — размерность ключа (используется для масштабирования).
  • — функция активации, превращающая числа в вероятности.
  • Эта формула — фундамент всего. Но именно в операции умножения на кроется главная проблема масштабируемости.

    Проклятие квадратичной сложности

    Когда модель обрабатывает последовательность длиной токенов, она должна вычислить взаимосвязь каждого токена с каждым другим токеном. Это создает матрицу внимания (Attention Matrix).

    !Матрица внимания размером N на N, где каждая ячейка представляет собой вычисление связи между двумя токенами.

    Арифметика взрывного роста

    Давайте посмотрим на сложность вычислений. Количество операций, необходимых для вычисления матрицы внимания, пропорционально квадрату длины последовательности. Это записывается как .

    Рассмотрим пример:

  • Если длина контекста токенов, то матрица внимания содержит (один миллион) элементов.
  • Если мы увеличим контекст в 10 раз, до , количество элементов станет (сто миллионов).
  • Увеличение длины входа в 10 раз приводит к увеличению объема вычислений и требуемой памяти в 100 раз.

    KV Cache и память GPU

    Проблема не только в скорости вычислений, но и в памяти видеокарты (VRAM). Во время генерации текста модель использует так называемый KV Cache (кэш ключей и значений), чтобы не пересчитывать всё заново для каждого нового слова. Размер этого кэша линейно растет с длиной контекста, но сама матрица внимания в процессе обучения и обработки промпта «съедает» память квадратично.

    Для контекста в 100,000 токенов стандартный механизм Attention потребовал бы терабайты видеопамяти, что физически невозможно на одном устройстве без специальных оптимизаций.

    Проблема «Lost in the Middle» (Потерянные в середине)

    Допустим, у нас есть достаточно мощное железо, и мы смогли технически загрузить в модель 100,000 токенов. Значит ли это, что модель идеально «понимает» весь этот текст? К сожалению, нет.

    Исследования (например, работа Liu et al., 2023) выявили феномен, получивший название «Lost in the Middle».

    Суть феномена заключается в том, что точность извлечения информации из контекста зависит от того, где именно находится эта информация:

  • Начало контекста (Primacy bias): Модель отлично помнит то, что было в самом начале (обычно это системные инструкции или начало промпта).
  • Конец контекста (Recency bias): Модель прекрасно видит то, что было написано только что (последние сообщения пользователя).
  • Середина контекста: Информация, находящаяся в середине длинного документа, часто игнорируется или извлекается с ошибками.
  • !График зависимости точности модели от позиции факта в контексте, демонстрирующий U-образную кривую.

    Почему это происходит?

    Существует несколько гипотез, объясняющих этот эффект:

    * Особенности обучения: Во время тренировки (Pre-training) модели редко видят зависимости между очень далекими токенами, так как обучающие данные часто нарезаются на куски фиксированной длины. * Архитектура Positional Encoding: Способ, которым трансформеры кодируют порядок слов (позиционное кодирование), может терять эффективность на больших дистанциях. Модели сложнее различить относительные позиции токенов в середине «каши» из информации. * Природа внимания: Механизм Softmax, используемый в формуле Attention, стремится выделить самые важные элементы. Когда элементов (токенов) становится слишком много, распределение вероятностей «размазывается», и модели становится сложнее сфокусироваться на конкретном факте в середине, если он не подсвечен явно.

    Влияние на реальные задачи

    Эти два ограничения — квадратичная сложность и «Lost in the Middle» — создают серьезные препятствия для бизнеса и разработки:

    * RAG (Retrieval Augmented Generation): Если мы добавим в контекст 50 найденных документов, модель может проигнорировать тот, который оказался 25-м по счету. * Анализ кода: При загрузке всего репозитория модель может забыть определение функции, объявленной в середине файла. * Юридический анализ: Поиск противоречий в многостраничном договоре может быть ненадежным, если ключевой пункт спрятан в середине текста.

    Что нас ждет дальше?

    Мы выяснили, что «грубая сила» (простое увеличение в стандартном Attention) — это тупиковый путь. Это дорого вычислительно и неэффективно с точки зрения качества ответов.

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

  • Разреженное внимание (Sparse Attention): Зачем смотреть на все токены, если можно смотреть только на важные?
  • Линейное внимание (Linear Attention): Как превратить в с помощью математических трюков.
  • RoPE и ALiBi: Современные методы позиционного кодирования, улучшающие работу с длиной.
  • Ring Attention и FlashAttention: Аппаратные оптимизации для ускорения вычислений.
  • Понимание фундаментальных проблем, описанных в этой статье, необходимо для того, чтобы оценить красоту и эффективность решений, о которых мы поговорим далее.

    2. Архитектурные оптимизации: FlashAttention, разреженное внимание (Sparse Attention) и линейные трансформеры

    Архитектурные оптимизации: FlashAttention, разреженное внимание (Sparse Attention) и линейные трансформеры

    В предыдущей статье мы диагностировали главную болезнь современных LLM при работе с длинным контекстом — квадратичную сложность . Если мы хотим увеличить длину контекста в 10 раз, нам нужно в 100 раз больше вычислительных ресурсов и памяти. Это тупик.

    Но инженеры не привыкли сдаваться. Если «в лоб» задачу не решить, нужно искать обходные пути. Сегодня мы разберем три главных направления инженерной мысли, которые позволяют моделям читать книги и анализировать огромные базы кода: FlashAttention, Sparse Attention (разреженное внимание) и Linear Transformers (линейные трансформеры).

    FlashAttention: Оптимизация памяти, изменившая всё

    Начнем с технологии, которая стала де-факто стандартом в индустрии. Когда вы используете GPT-4 или Llama 3 с длинным контекстом, под капотом почти наверняка работает FlashAttention.

    Самое удивительное в FlashAttention то, что математически это точный механизм внимания. Он не упрощает формулу, не выбрасывает данные. Он выдает тот же результат, что и стандартный Attention, но делает это в разы быстрее и потребляет значительно меньше памяти. Как?

    Проблема пропускной способности памяти (Memory Bandwidth)

    Чтобы понять суть FlashAttention, нужно спуститься на уровень «железа» — видеокарт (GPU). В GPU есть два типа памяти:

  • HBM (High Bandwidth Memory): Это основная видеопамять (например, 80 ГБ на A100). Она большая, но медленная.
  • SRAM (Static RAM): Это кэш внутри вычислительных ядер. Она невероятно быстрая, но её очень мало (порядка 20 МБ).
  • В стандартном механизме Attention видеокарта постоянно перегоняет огромные матрицы из медленной HBM в быструю SRAM и обратно, чтобы выполнить операции Softmax и умножения. Это похоже на повара, который за каждым ингредиентом бегает в магазин через дорогу, вместо того чтобы держать всё на столе.

    !Сравнение потоков данных между HBM и SRAM в стандартном Attention и FlashAttention.

    Tiling (Тайлинг) и Recomputation

    Авторы FlashAttention (Tri Dao и др.) предложили два трюка:

  • Tiling (Разбиение на блоки): Матрица внимания не вычисляется целиком. Она разбивается на маленькие блоки, которые помещаются в быструю память SRAM. Вычисления происходят внутри SRAM, и в основную память (HBM) записывается только финальный результат.
  • Recomputation (Пересчет): Чтобы не хранить промежуточную матрицу внимания (которая занимает терабайты памяти при длинном контексте) для обратного распространения ошибки (backpropagation), FlashAttention просто быстро пересчитывает её на лету. Оказывается, пересчитать данные быстрее, чем читать их из медленной памяти.
  • Результат: сложность по памяти снижается с квадратичной до линейной , а скорость обучения возрастает в разы.

    Sparse Attention: Искусство игнорировать неважное

    Если FlashAttention оптимизирует как мы считаем, то Sparse Attention (разреженное внимание) предлагает изменить то, что мы считаем. Идея проста: зачем каждому токену смотреть на каждый другой токен? Ведь слово в начале книги вряд ли грамматически связано со словом в конце.

    Вместо полной матрицы внимания (Dense), где заполнены все ячейки, мы создаем разреженную матрицу (Sparse), где вычисляются только определенные связи.

    Популярные паттерны разреженности

    Существует несколько стратегий выбора важных токенов:

  • Sliding Window (Скользящее окно): Каждый токен смотрит только на соседей слева и справа. Это отлично работает для локальных связей (синтаксис), но убивает понимание глобального контекста.
  • Global Attention (Глобальное внимание): Выделяются специальные токены (например, [CLS] или первые токены абзацев), на которые смотрят все остальные. Они служат «хабами» для передачи информации через весь текст.
  • Random Attention (Случайное внимание): Добавляются случайные связи, чтобы сократить среднее расстояние между любыми двумя токенами в графе.
  • !Визуализация паттернов внимания: полное, скользящее окно и комбинированное (BigBird).

    Примеры архитектур: Longformer и BigBird. Они позволяют обрабатывать длинные тексты, снижая сложность вычислений. Однако, в отличие от FlashAttention, это аппроксимация. Мы сознательно теряем часть информации, надеясь, что она была неважной. Иногда это приводит к ухудшению качества.

    Линейные трансформеры (Linear Transformers): Математическая магия

    Третий подход — самый радикальный. Он пытается переписать саму формулу Attention, чтобы избавиться от квадратичной зависимости математически.

    Вспомним формулу внимания:

    Где:

  • — матрицы запросов, ключей и значений.
  • — размерность вектора.
  • Проблема здесь в порядке умножения. Сначала мы умножаем на . Если размерность последовательности , то результат — матрица . Это и есть узкое место.

    Свойство ассоциативности

    В матричном умножении работает правило: . Если бы мы могли сначала умножить на , мы бы получили матрицу размером (где — размерность скрытого слоя, обычно 64-128), что ничтожно мало по сравнению с . Тогда сложность стала бы линейной .

    Но нам мешает функция , которая стоит посередине и «ломает» линейность операций.

    Kernel Trick (Ядерный трюк)

    Идея линейных трансформеров (например, Performer или Linear Transformer) заключается в замене на другую функцию (ядерную функцию ), которая позволяет разложить вычисления:

    Где:

  • — функция отображения (kernel function), заменяющая softmax.
  • — часть, которую можно вычислить один раз, получив компактную матрицу состояния.
  • Это превращает трансформер в своего рода рекуррентную нейросеть (RNN). Мы можем обрабатывать бесконечный поток токенов с фиксированным объемом памяти!

    Почему же мы не используем их везде? К сожалению, замена на линейную аппроксимацию часто приводит к падению качества генерации. Модель хуже фокусируется на конкретных деталях («иголке в стоге сена»), так как распределение внимания становится более «размытым».

    Сравнительная таблица методов

    | Метод | Сложность | Точность | Особенности | | :--- | :--- | :--- | :--- | | Standard Attention | | Максимальная | Фундаментальное ограничение по памяти. | | FlashAttention | (выч.), (память) | Максимальная (Exact) | Оптимизация IO. Стандарт де-факто сегодня. | | Sparse Attention | или | Аппроксимация | Экономит ресурсы, но может терять контекст. | | Linear Attention | | Аппроксимация | Бесконечный контекст, но качество часто страдает. |

    Заключение

    Мы рассмотрели три пути решения проблемы:

  • FlashAttention — оптимизируем работу с «железом» (победитель на данный момент).
  • Sparse Attention — выкидываем лишние связи.
  • Linear Attention — меняем математику.
  • Сегодня индустрия сделала ставку на FlashAttention, так как он не требует компромиссов в качестве. Однако, даже с ним мы упираемся в то, как модель понимает позицию слов на огромных расстояниях. О том, как научить модель понимать, что слово №100 связано со словом №100,000 (проблема позиционного кодирования), мы поговорим в следующей статье про RoPE и ALiBi.

    3. Масштабирование контекста: Интерполяция позиционного кодирования, RoPE Scaling и методы ALiBi

    Масштабирование контекста: Интерполяция позиционного кодирования, RoPE Scaling и методы ALiBi

    В предыдущих статьях мы совершили настоящий прорыв. Мы узнали, как FlashAttention позволяет нам технически поместить огромные объемы текста в память видеокарты, избавившись от проклятия квадратичной сложности по памяти. Казалось бы, проблема решена? Загружай «Войну и мир» и общайся!

    Но здесь нас поджидает новая ловушка. Даже если мы технически можем подать на вход модели 100,000 токенов, это не значит, что она сможет их адекватно обработать. Если модель обучалась на текстах длиной 4,096 токенов, то всё, что находится за пределами этой границы, для неё — terra incognita (неизведанная земля).

    В этой статье мы разберем, как научить модель ориентироваться в пространствах, которые она никогда не видела во время обучения. Мы поговорим о позиционном кодировании, магии RoPE, трюках с интерполяцией и элегантном методе ALiBi.

    Проблема: «Где я нахожусь?»

    Архитектура Трансформер, в отличие от рекуррентных сетей (RNN), обрабатывает все токены параллельно. Для механизма Self-Attention фраза «Мама мыла раму» и «Раму мыла мама» выглядит как набор одинаковых слов, если мы явно не укажем модели порядок этих слов.

    Чтобы дать модели чувство порядка, мы добавляем к каждому токену позиционное кодирование (Positional Encoding — PE). Это своего рода «адрес» слова в предложении.

    Почему старые методы не работают с длинным контекстом?

    Классические трансформеры (как BERT или GPT-2) использовали абсолютное позиционное кодирование. У модели был фиксированный набор «адресов» от 0 до (например, до 2048). Если вы подавали токен на позицию 2049, у модели просто не было для него вектора адреса. Это как пытаться поселить человека в комнату №105 в отеле, где всего 100 номеров.

    RoPE: Вращение вместо сложения

    Современные LLM (Llama 2, Llama 3, Mistral, PaLM) используют более продвинутый метод — Rotary Positional Embeddings (RoPE). Идея RoPE заключается в том, чтобы кодировать позицию не добавлением числа, а поворотом вектора в пространстве.

    Представьте, что вектор токена — это стрелка часов. Позиция токена определяет, на какой угол мы повернем эту стрелку.

    !Визуализация принципа RoPE: кодирование позиции через угол поворота вектора.

    Математически это описывается так:

    Где:

  • — вектор на позиции после применения кодирования.
  • — исходный вектор токена.
  • — мнимая единица (используется для описания вращения в комплексной плоскости).
  • — позиция токена (индекс, например, 1, 2, 3...).
  • — базовый угол поворота.
  • Главное преимущество RoPE — относительность. Внимание между двумя токенами зависит только от разницы их углов (расстояния между ними), а не от их абсолютных позиций. Это критически важно для длинного контекста.

    Проблема экстраполяции: Стена обучения

    Допустим, мы обучили Llama 2 с длиной контекста 4096 (4k). Во время обучения модель видела повороты векторов, соответствующие позициям от 0 до 4096. Она выучила, как взаимодействуют слова на таких дистанциях.

    Что произойдет, если мы подадим на вход 8000 токенов? Для позиций > 4096 векторы будут повернуты на углы, которые модель никогда не видела. Нейросеть «сходит с ума», и генерация превращается в бессвязный шум. Это называется проблемой экстраполяции.

    Решение 1: Position Interpolation (PI) — Растягиваем линейку

    Инженеры из Meta (команда Llama) предложили гениальное в своей простоте решение. Если модель не умеет работать с позициями больше 4096, давайте обманем её.

    Вместо того чтобы экстраполировать (продлевать линейку в неизведанное), мы будем интерполировать (сжимать наши данные в знакомый диапазон).

    Представьте, что у вас есть линейка длиной 1 метр. Вам нужно измерить объект длиной 2 метра. Вместо того чтобы искать новую линейку, вы переписываете деления на старой: там, где было «1 см», теперь вы считаете, что это «2 см».

    Линейное масштабирование (Linear Scaling)

    Мы берем реальные позиции токенов и делим их на коэффициент масштабирования .

    Где:

  • — новая «виртуальная» позиция, которую увидит модель.
  • — реальная позиция токена.
  • — коэффициент масштабирования (например, 2, если мы хотим увеличить контекст с 4k до 8k).
  • Теперь токен на позиции 8000 для модели выглядит как токен на позиции 4000. Модель «думает», что работает в привычном диапазоне, но на самом деле охватывает в 2 раза больше текста. Это требует небольшой дообучения (Fine-tuning), но это в тысячи раз дешевле, чем учить модель с нуля.

    Решение 2: NTK-Aware Scaling — Умная интерполяция

    Линейная интерполяция имеет недостаток. Когда мы «сжимаем» позиции, мы теряем разрешение на высоких частотах. Это похоже на то, как если бы мы ускорили аудиозапись в 2 раза — слова стали бы писклявыми и неразборчивыми.

    В RoPE векторы имеют разные частоты вращения (некоторые компоненты вектора вращаются быстро, некоторые медленно). Линейное сжатие одинаково влияет на все частоты, что плохо сказывается на внимании к деталям.

    Метод NTK-Aware Scaling (названный в честь Neural Tangent Kernel) предлагает менять не сами позиции , а базу системы счисления (частоту вращения).

    Вместо того чтобы сжимать время, мы замедляем вращение часов. Это позволяет сохранить точность для близких токенов (высокие частоты) и при этом охватить далекие токены (низкие частоты).

    Этот метод позволяет расширять контекст даже без дообучения, просто меняя формулу при запуске модели!

    Решение 3: ALiBi — Простота хуже воровства?

    Пока исследователи бились над сложной математикой вращений, команда из Facebook AI Research (FAIR) предложила альтернативу — ALiBi (Attention with Linear Biases).

    Идея радикальна: давайте вообще выкинем позиционные эмбеддинги. Модели не нужно знать координаты слов. Ей нужно просто знать, что слово А ближе, чем слово Б.

    В ALiBi мы добавляем статический штраф к матрице внимания, который зависит от расстояния между токенами.

    Где:

  • — стандартное произведение запросов и ключей (матрица внимания).
  • — фиксированный коэффициент наклона (slope), уникальный для каждой «головы» внимания (attention head).
  • — расстояние между токеном на позиции и токеном на позиции .
  • — матрица значений.
  • !Визуализация матрицы штрафов в методе ALiBi.

    В чем суть магии?

    Мы говорим модели: «Чем дальше от тебя слово, тем меньше обращай на него внимания». Это создает естественное смещение (bias) в сторону локального контекста.

    Преимущество: ALiBi обладает истинной способностью к экстраполяции. Модель, обученная на 2048 токенах с ALiBi, может спокойно работать с 8000+ токенами без какого-либо дообучения и хитрых трюков с интерполяцией. Штраф просто продолжает расти линейно.

    Недостаток: ALiBi хуже справляется с задачами, где нужно найти «иголку в стоге сена» на очень большом расстоянии, так как штраф за дальность может заглушить полезный сигнал.

    YaRN: Современный стандарт

    На сегодняшний день одним из самых продвинутых методов является YaRN (Yet another RoPE extensioN). Это комбинация идей NTK-Aware и специальных поправок на энтропию. YaRN позволяет эффективно расширять контекст Llama 2 с 4k до 128k токенов с минимальной потерей качества.

    Сводная таблица методов

    | Метод | Принцип работы | Плюсы | Минусы | | :--- | :--- | :--- | :--- | | Absolute PE | Каждой позиции свой вектор | Простота | Не работает за пределами обучения | | RoPE | Вращение векторов | Относительность, гибкость | Плохая прямая экстраполяция | | Linear Interpolation | Сжатие позиций () | Легко реализовать | Требует дообучения, теряет детали | | NTK-Aware | Изменение частот вращения | Работает без дообучения | Сложнее в настройке | | ALiBi | Штраф к вниманию за дальность | Идеальная экстраполяция, быстро | Слабее на задачах дальнего поиска |

    Заключение

    Мы научились не только быстро считать внимание (FlashAttention), но и правильно кодировать позиции для огромных текстов, используя математические трюки вроде RoPE Scaling и ALiBi. Теперь наша модель может «видеть» на километры вперед.

    Однако, остается последний барьер — аппаратный. Даже с FlashAttention и RoPE, один GPU не может вместить контекст в миллион токенов. В следующей, заключительной статье курса, мы поговорим о Ring Attention и распределенных вычислениях — методах, которые позволяют объединять сотни видеокарт в единый мозг.

    4. Внешняя память и RAG: Расширение контекста через векторный поиск и базы знаний

    Внешняя память и RAG: Расширение контекста через векторный поиск и базы знаний

    Мы прошли долгий путь. Мы разобрали, как оптимизировать вычисления с помощью FlashAttention, чтобы они не «взрывали» память видеокарты. Мы научились кодировать бесконечные последовательности с помощью RoPE и ALiBi. Казалось бы, теперь мы можем подавать в модель целые книги.

    Но давайте будем реалистами. Даже с самыми современными методами, контекстное окно имеет жесткий предел. У GPT-4 это 128k токенов, у Claude 3 — 200k, у Gemini 1.5 — до миллиона. Но что, если ваша база знаний — это корпоративный архив размером в 10 терабайт? Или вся юридическая практика страны за 50 лет?

    Никакое контекстное окно не вместит весь интернет. Здесь нам на помощь приходит концепция внешней памяти. Вместо того чтобы пытаться «запомнить» всё (обучение) или «прочитать» всё сразу (длинный контекст), мы учим модель пользоваться поисковиком. Этот подход называется RAG (Retrieval-Augmented Generation).

    Философия RAG: Экзамен с открытой книгой

    Представьте двух студентов, готовящихся к экзамену по истории:

  • Студент А (Fine-Tuning): Выучил наизусть все даты и имена. Если его спросят о чем-то, чего не было в учебнике, он начнет галлюцинировать (выдумывать факты).
  • Студент Б (RAG): Знает общие принципы истории, но на экзамен пришел с огромной библиотекой справочников. Получив вопрос, он находит нужную страницу, читает её и формулирует ответ.
  • LLM с длинным контекстом — это попытка сделать Студента А с очень большой головой. RAG — это Студент Б.

    Суть метода заключается в разделении хранения знаний и обработки информации.

    !Схематичное изображение архитектуры RAG: от запроса пользователя через поиск документов к генерации ответа.

    Векторные представления: Язык смыслов

    Как найти нужный абзац в миллионе документов? Поиск по ключевым словам (как Ctrl+F) здесь не работает эффективно. Если пользователь спросит «Как починить яблочный девайс?», обычный поиск не поймет, что статья про «ремонт iPhone» — это то, что нужно, так как там нет слова «яблочный».

    Для решения этой задачи мы используем эмбеддинги (embeddings). Это превращение текста в вектор чисел.

    Математика смысловой близости

    Нейросеть-энкодер (например, BERT) преобразует любой текст в вектор фиксированной размерности (например, 768 или 1536 чисел). Главное свойство этих векторов: близкие по смыслу тексты имеют близкие векторы.

    Чтобы определить, насколько два текста похожи, мы вычисляем косинусное сходство (Cosine Similarity) между их векторами.

    Где:

  • и — векторы двух сравниваемых текстов (запроса и документа).
  • — скалярное произведение векторов.
  • и — евклидовы нормы (длины) векторов.
  • — угол между векторами в многомерном пространстве.
  • Если косинус равен 1, векторы идентичны (угол 0 градусов). Если 0 — они ортогональны и не имеют ничего общего. Если -1 — они противоположны по смыслу.

    Векторные базы данных: Хранилище бесконечного контекста

    Вычислять косинусное сходство запроса со всеми миллионами документов «в лоб» слишком долго. Поэтому используются специальные векторные базы данных (Vector Databases), такие как Pinecone, Milvus, Qdrant или Weaviate.

    Они используют алгоритмы приближенного поиска ближайших соседей (ANN — Approximate Nearest Neighbors), например, HNSW (Hierarchical Navigable Small World). Это позволяет находить топ-5 самых похожих документов среди миллиарда записей за миллисекунды.

    Архитектура RAG-пайплайна

    Давайте разберем пошагово, как работает современная система расширения контекста.

    1. Чанкинг (Chunking)

    Мы не можем векторизовать целую книгу одним вектором — смысл «размажется». Поэтому мы разбиваем текст на кусочки — чанки.

    Стратегия нарезки критически важна: * Фиксированный размер: Например, по 500 токенов. * Перекрытие (Overlap): Мы делаем нахлест (например, 50 токенов), чтобы не разорвать предложение или мысль посередине.

    2. Индексация (Indexing)

    Каждый чанк прогоняется через модель эмбеддингов (например, text-embedding-3-small от OpenAI или e5-large из Open Source). Полученные векторы сохраняются в базу данных.

    3. Поиск (Retrieval)

    Когда пользователь задает вопрос:

  • Вопрос превращается в вектор тем же энкодером.
  • Векторная база находит (обычно 3-10) самых близких чанков.
  • 4. Генерация (Generation)

    Найденные чанки подставляются в системный промпт LLM. Это выглядит примерно так:

    > Используй следующую информацию (контекст), чтобы ответить на вопрос пользователя. Если информации недостаточно, скажи «я не знаю». > > Контекст: > [Текст чанка 1] > [Текст чанка 2] > ... > > Вопрос: [Вопрос пользователя]

    Теперь LLM, обладая «шпаргалкой», генерирует точный ответ.

    Проблемы Naive RAG и методы их решения

    Описанная выше схема называется Naive RAG (Наивный RAG). У неё есть свои недостатки, которые возвращают нас к проблемам, обсуждавшимся в начале курса.

    Проблема «Lost in the Middle» в RAG

    Если мы найдем 50 документов и подадим их в контекст, модель может проигнорировать те, что находятся в середине списка (как мы выяснили в первой статье). Простое увеличение (количества найденных документов) не всегда улучшает качество.

    Решение: Re-ranking (Переранжирование)

    Векторный поиск быстр, но не всегда точен. Он ищет семантическую близость, но не всегда понимает нюансы вопроса. Поэтому часто используют двухступенчатую схему:

  • Retrieval: Быстро достаем 100 кандидатов из векторной базы.
  • Re-ranking: Используем более тяжелую модель (Cross-Encoder), которая медленно и внимательно сравнивает вопрос с каждым из 100 кандидатов и выдает оценку релевантности. Оставляем топ-5 лучших.
  • Проблема потери контекста при нарезке

    Иногда ответ на вопрос требует информации из начала и конца документа, а они попали в разные чанки и потеряли связь.

    Решение: Parent Document Retriever

    Мы нарезаем документ на маленькие чанки для поиска (чтобы точно ловить смысл), но в базу сохраняем связь с «родительским» большим чанком. Если поиск находит маленький кусок, мы подтягиваем в контекст LLM весь родительский блок, сохраняя связность повествования.

    Гибридный поиск: Лучшее из двух миров

    Векторный поиск отлично находит концепции («собака» «щенок»), но плохо справляется с точными совпадениями (артикулы, имена, специфические термины). Старый добрый поиск по ключевым словам (BM25) здесь выигрывает.

    Современные RAG-системы используют Hybrid Search:

  • Ищем по векторам.
  • Ищем по ключевым словам.
  • Объединяем результаты с весами (например, алгоритм Reciprocal Rank Fusion).
  • Заключение

    RAG позволяет нам обойти ограничение контекстного окна, превращая его из «жесткого диска» в «оперативную память», куда подгружается только то, что нужно прямо сейчас. Это решает проблему стоимости и памяти, но вносит задержки (время на поиск) и зависимость от качества базы знаний.

    Однако, что делать, если нам нужно не просто найти факт, а проанализировать взаимосвязи между тысячами документов одновременно? RAG здесь бессилен, так как он видит только фрагменты. В следующей статье мы рассмотрим Ring Attention и распределенные вычисления — технологии, позволяющие объединять множество GPU в единый кластер для обработки действительно гигантских контекстов целиком.

    5. Сжатие и альтернативы: Token Pruning, компрессия промптов и архитектуры State Space Models (Mamba)

    Сжатие и альтернативы: Token Pruning, компрессия промптов и архитектуры State Space Models (Mamba)

    Мы продолжаем наш курс по методам работы с длинным контекстом. В предыдущих лекциях мы рассмотрели, как оптимизировать вычисления (FlashAttention), как кодировать позицию в бесконечных последовательностях (RoPE, ALiBi) и как использовать внешнюю память (RAG).

    Однако у всех этих методов есть общий знаменатель — архитектура Transformer. Несмотря на все оптимизации, трансформер имеет фундаментальную особенность: во время генерации текста ему необходимо хранить KV Cache (кэш ключей и значений) для всех предыдущих токенов. Если контекст составляет 1 миллион токенов, кэш будет занимать сотни гигабайт видеопамяти, даже если мы используем RAG для поиска информации.

    Сегодня мы зададимся двумя радикальными вопросами:

  • А нужно ли нам хранить все токены в памяти, или часть из них — это просто шум?
  • А является ли Трансформер единственно возможной архитектурой для работы с текстом?
  • В этой статье мы разберем методы Token Pruning (выбрасывание лишнего), Prompt Compression (сжатие смысла) и революционную архитектуру Mamba, которая бросает вызов гегемонии трансформеров.

    Token Pruning: Искусство забывать

    Представьте, что вы читаете книгу. Помните ли вы каждое слово «и», «но», «который» на 50-й странице, когда находитесь на 300-й? Скорее всего, нет. Вы помните ключевые факты, имена и сюжетные повороты. Трансформеры же по умолчанию помнят всё.

    Методы Token Pruning (прунинг или прореживание токенов) основаны на гипотезе, что не все токены одинаково важны для генерации следующего слова. Если мы сможем на лету определять бесполезные токены и выбрасывать их из KV Cache, мы сэкономим огромное количество памяти.

    H2O: Heavy Hitter Oracle

    Один из популярных методов — H2O. Исследователи заметили, что матрица внимания очень разрежена. Для генерации ответа модель обычно смотрит на небольшую группу токенов, которые называют Heavy Hitters («тяжеловесы»).

    Алгоритм работает так:

  • Во время вычисления внимания мы накапливаем статистику: на какие токены модель смотрит чаще всего.
  • Если токен долгое время не получает внимания, он удаляется из кэша.
  • В памяти остаются только самые важные слова.
  • Это позволяет сократить потребление памяти в 5-10 раз с минимальной потерей качества.

    Феномен Attention Sinks (Стоки внимания)

    При попытке просто выбрасывать старые токены (метод скользящего окна) инженеры столкнулись с проблемой: модель начинала «ломаться». Оказалось, что трансформеры уделяют огромное внимание самым первым токенам (обычно это системный промпт или начало текста), даже если они не несут смысла.

    Этот феномен назвали Attention Sinks. Первые токены служат «якорем» для механизма Softmax. Если их удалить, распределение вероятностей рассыпается. Современные методы прунинга (например, StreamingLLM) обязательно сохраняют несколько начальных токенов («якоря») и последние токены (локальный контекст), а середину жестко фильтруют.

    !Визуализация стратегии управления кэшем: сохранение "якорей" в начале и активного окна в конце, с прореживанием середины.

    Prompt Compression: Сжатие смысла

    Если Token Pruning работает внутри модели во время генерации, то Prompt Compression (компрессия промпта) работает до того, как текст попадет в модель. Это похоже на архиватор ZIP, но для смыслов.

    Идея проста: если у вас есть промпт на 10,000 токенов, можно ли переписать его так, чтобы он занимал 1,000 токенов, но модель поняла бы то же самое?

    LLMLingua и семантическое сжатие

    Проект LLMLingua от Microsoft использует маленькую и быструю модель (например, Llama-7B или BERT), чтобы оценить перплексию (неожиданность) каждого токена в промпте.

    * Если токен легко предсказывается из контекста (например, слово «была» во фразе «погода была хорошая»), он несет мало информации. * Если токен сложно предсказать (например, имя собственное или число), он несет много информации.

    Алгоритм удаляет токены с низкой перплексией. В результате получается текст, который человеку читать сложно («погода хорошая» вместо «погода была хорошая»), но LLM понимает его прекрасно, так как сохранена вся семантическая суть.

    Это позволяет запихнуть в контекстное окно в 5-10 раз больше документов при использовании RAG.

    State Space Models (SSM): Жизнь после Трансформера

    Все методы, описанные выше — это «костыли» для Трансформера. Но что, если сама архитектура с матрицей внимания — это тупик для сверхдлинных контекстов?

    Здесь на сцену выходят State Space Models (SSM) и их самый яркий представитель — архитектура Mamba.

    Проблема линейного роста памяти

    Вспомним, как работает рекуррентная нейросеть (RNN). Она читает слово, обновляет свое скрытое состояние (память) и забывает слово. Ей не нужно хранить историю. Память RNN — это вектор фиксированного размера.

    Трансформер же хранит историю всех токенов. * RNN: Быстрый инференс, мало памяти, но плохо учится и забывает старое. * Transformer: Идеально помнит, отлично учится, но требует колоссальной памяти на длинных текстах.

    SSM пытаются объединить лучшее из двух миров.

    Математика SSM

    В основе SSM лежит непрерывное уравнение состояния, пришедшее из теории управления (Control Theory). Дискретная версия описывается так:

    Где: * — скрытое состояние (память) в момент времени . Это сжатое представление всего прочитанного ранее. * — скрытое состояние на предыдущем шаге. * — входной токен в момент времени . * — матрица перехода, определяющая, сколько информации из прошлого мы сохраняем. * — матрица входа, определяющая, как новый токен влияет на состояние.

    Выход модели вычисляется как:

    Где: * — выходной вектор (предсказание следующего токена). * — матрица проекции состояния на выход.

    Главное чудо здесь в том, что во время обучения эту рекурсию можно развернуть через свертку (Convolution) и обучать параллельно, как Трансформер. А во время генерации (инференса) она работает как RNN.

    Это означает, что затраты памяти на генерацию не зависят от длины контекста. Будь то 100 токенов или 1 миллион — Mamba тратит одинаковое количество байт памяти ( state).

    Mamba и механизм селекции (Selection Mechanism)

    Классические SSM (например, S4) были хороши для аудио, но плохи для текста. Проблема была в том, что матрицы и были статичными. Модель обрабатывала всю информацию одинаково, не умея «фокусироваться».

    Авторы Mamba (Albert Gu и Tri Dao) ввели Selection Mechanism. Они сделали матрицы , и шаг дискретизации зависимыми от входа .

    Это позволяет модели динамически решать:

  • Какую информацию запомнить (открыть шлюз в ).
  • Какую информацию игнорировать (закрыть шлюз).
  • Какую информацию сбросить (забыть старое состояние).
  • !Схематичное сравнение архитектур: Трансформер с растущим кэшем против Mamba с фиксированным состоянием.

    Гибридные архитектуры: Jamba

    Несмотря на эффективность, Mamba пока уступает Трансформерам в способности извлекать информацию из произвольного места контекста (Recall). У Трансформера есть «фотографическая память» (KV Cache), а у Mamba — «сжатая суть».

    Поэтому сейчас набирают популярность гибридные подходы, такие как Jamba (от AI21 Labs). Идея проста: чередовать слои Mamba и слои Attention.

    Например: * 7 слоев Mamba (для эффективного сжатия и обработки). * 1 слой Attention (для точной синхронизации и извлечения фактов). * Снова 7 слоев Mamba.

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

    Заключение

    Мы рассмотрели способы борьбы с длинным контекстом, выходящие за рамки простого «давайте купим больше видеокарт».

  • Token Pruning позволяет Трансформерам работать эффективнее, выбрасывая мусор из памяти, но требует осторожности с «якорями» внимания.
  • Prompt Compression сжимает входные данные, экономя токены и деньги, но является методом с потерями.
  • SSM (Mamba) предлагает фундаментально новый путь — отказ от квадратичного внимания в пользу рекуррентных состояний с линейной сложностью.
  • В следующей, заключительной статье курса, мы поднимемся на уровень инфраструктуры и разберем Ring Attention — технологию, которая позволяет распределять вычисления одного гигантского контекста между сотнями GPU, создавая модели масштаба GPT-4.