Главная / Статьи

От прогнозирования следующего токена к рабочему коду: как большие языковые модели генерируют Python

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

Издатель: REACTAPP.TOP9 мин чтения1998 слов

Источники: How LLMs Actually Work: From Predicting the Next Word to Writing Code.

Инструменты вроде ChatGPT и Copilot пишут функции, исправляют ошибки и объясняют алгоритмы, и может показаться, что происходит нечто большее, чем просто завершение текста. Приведённая ниже модель работы начинается с основ: прогнозирование токенов, механизм внимания, а также с объяснения того, почему механизм, завершающий предложение, одновременно генерирует корректный код на Python.

Один вопрос, задаваемый снова и снова

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

Не существует семантического понимания в традиционном смысле, и нет этапа, на котором модель решает написать функцию до того, как вывести слово def. Она предсказывает токены по одному. Благодаря миллиардам параметров и тексту для обучения, насчитывающему сотни миллиардов токенов, эти предсказания в конечном итоге выглядят очень похоже на процесс рассуждения.

Что такое токен

Точность помогает ещё до начала процесса предсказания. Модели работают не с символами или словами, а с токенами — подсловными единицами, создаваемыми алгоритмами вроде кодирования пар символов. В общих чертах:

  • Обычные слова обычно превращаются в отдельные токены, такие как "the", "def" и "return".
  • Редкие слова делятся на части, поэтому "unhappiness" превращается в ["un", "happiness"].
  • Символы кода часто представляют собой отдельные токены, например "(", ":", "==" и "->".
  • Для GPT-4 один токен соответствует примерно 0,75 английского слова, а в коде он обычно содержит 3–4 символа, поскольку код состоит из однозначных токенов вроде : и (.

    У модели также есть словарь — фиксированный список известных токенов, который обычно насчитывает от 50 000 до 100 000 элементов. На каждом шаге модель присваивает каждому элементу вероятность и либо выбирает наиболее вероятный вариант, либо берет значение из распределения, причем выбор определяется параметром температуры.

    Цикл прогнозирования

    Для последовательности «The cat sat on the» необходимо вычислить условную вероятность:

    P(next_token | "The", "cat", "sat", "on", "the")
    

    Это распределение по всему словарю. Прохождение сигнала через сеть генерирует вектор размером с словарь, который функция softmax преобразует в допустимое вероятностное распределение:

    P(token_i) = exp(logit_i) / Σⱼ exp(logit_j)
    

    При жадном декодировании выбирается токен с наибольшей вероятностью. В противном случае токен выбирается пропорционально распределению, причем параметр temperature контролирует степень его распространения:

    • temperature = 0 всегда выбирает токен с наивысшей вероятностью, поэтому результат является детерминированным.
    • temperature = 1 позволяет выбирать токены из исходного распределения, что придает результатам разнообразие и креативность.
    • При значении выше 1 распределение становится более плоским, и результаты становятся более случайными.
    • При значении ниже 1 распределение становится более острым, и результаты становятся более консервативными.

    Именно поэтому один и тот же запрос может давать разные ответы при разных запусках.

    Transformer

    Функция, преобразующая последовательность токенов в распределение следующего токена, — это Transformer, а именно версия, предназначенная исключительно для декодирования; именно такая архитектура лежит в основе GPT, Llama, Mistral и Claude. Общий алгоритм работы:

    Token IDs → Embedding layer → [Attention + FFN] × N layers → Linear head → Softmax → P(next token)
    

    Элементы в порядке:

    1. Слой встраивания. Каждый целочисленный идентификатор токена преобразуется в плотный вектор размером d_model; например, 4096 в Llama-3 8B. Позиционные встраивания, или RoPE в современных моделях, добавляют информацию о порядке.
    2. Слои Transformer, повторяющиеся N раз. Каждый из них содержит многоголовую самоаттенцию, сеть с передачей вперед, нормализацию слоя, применяемую перед каждым подслоем в стиле «pre-norm», и остаточные соединения.
    3. Линейный слой и функция softmax. Итоговое скрытое состояние преобразуется в логиты формы [|V|], а функция softmax формирует распределение.

    Самоаттенция

    Механизм самообратной связи позволяет токену учитывать другие токены в последовательности, чтобы получить более полное представление о себе. Именно это даёт трансформерам преимущество перед RNN: каждый токен может в одном шаге взаимодействовать со всеми остальными токенами, без снижения интенсивности градиента с увеличением расстояния.

    При наличии n токенов каждый из них проецируется тремя способами:

    Q = XWᴬ_Q    (Query: what am I looking for?)
    K = XWᴬ_K    (Key: what do I contain?)
    V = XWᴬ_V    (Value: what do I contribute?)
    

    Здесь X — это входная матрица формы [n, d_model], а три матрицы W представляют собой выученные веса. Оценка между токеном i, действующим в качестве запроса, и токеном j, действующим в качестве ключа, равна:

    score(i, j) = qᵢ · kⱼᵀ / √dₖ
    

    Деление на квадратный корень ключевого измерения предотвращает слишком большое увеличение скалярных произведений, когда dₖ велик, что могло бы привести к тому, что функция softmax окажется в областях с крайне малыми градиентами. Полная формула вычисления следующая:

    Attention(Q, K, V) = softmax(QKᵀ / √dₖ) · V
    

    В моделях, предназначенных исключительно для декодирования, таких как GPT, внимание носит причинно-следственный характер или является замаскированным: токен i может обращать внимание только на позиции до i. Позиции в будущем получают оценку в виде отрицательного бесконечности перед применением функции softmax, поэтому их веса равны нулю.

    Многоголовое внимание выполняет h независимых функций внимания параллельно, каждая из которых имеет меньшую размерность d_model / h, после чего объединяет полученные результаты:

    MultiHead(Q, K, V) = Concat(head₁, ..., headₕ) · W_O
    headᵢ = Attention(QWᵢ_Q, KWᵢ_K, VWᵢ_V)
    

    Разные механизмы внимания обрабатывают разные связи между элементами. Один может опираться на синтаксические зависимости, другой — на кореференцию, а третий — на близость расположения.

    Сеть с передачей сигнала вперед

    После формирования внимания представление каждого токена проходит через функцию FFN, зависящую от его позиции:

    FFN(x) = max(0, xW₁ + b₁)W₂ + b₂
    

    Современные архитектуры, такие как Llama и Mistral, вместо этого используют SwiGLU:

    FFN(x) = (SiLU(xW_gate) ⊙ xW_up) · W_down
    

    Большая часть запомненных знаний модели хранится в FFN. Он функционирует как хранилище типа «ключ-значение», обрабатывающее фактические связи. Механизм внимания передает информацию между токенами, а FFN находит сохраненные факты и шаблоны. В крупных моделях ширина FFN примерно в четыре раза превышает значение d_model. У Llama-3 70B d_model = 8192, а средний размер составляет 28672, и именно там находится большинство параметров.

    Почему модели могут писать код

    Код — это последовательность токенов, такая же, как и естественный язык. Для модели функция на Python не представляет ничего особенного — это просто набор токенов вроде def, sort, _list, (, arr, ), : и т. д.

    Синтаксически корректный вывод является чисто следствием процесса обучения. Рассмотрим следующие условные вероятности:

    P("(" | ..., "def", " quicksort") ≈ 1.0
    P(":" | ..., "def", " quicksort", "(", "arr", ")") ≈ 1.0
    P("return" | context inside function body) >> P("import" | same context)
    

    Они имеют резкий пик, поскольку модель ознакомилась с миллионами файлов на Python, все из которых соответствуют одинаковым правилам. Грамматика Python нигде не закодирована жестко в сети — она формируется на основе статистики корпуса данных.

    Это также объясняет, почему модели иногда пишут код, который формально корректен, но логически неверен. Они максимизируют вероятность следующего токена с учетом распределения данных обучения. Они не запускают код и не проверяют его.

    Функция сортировки, шаг за шагом

    Предположим, запрос звучит как «Напишите функцию на Python для сортировки списка». Модель рассматривает его как последовательность токенов и добавляет результат по одному токену за раз. Примерно так:

    • Шаг 1, после запроса: def с вероятностью около 0,91.
    • Шаг 2, после def: sort с вероятностью около 0,78.
    • Шаг 3: _list или ( с вероятностью около 0,65.
    • Шаг 4: после sort( — arr или lst примерно в 0,71.
    • Шаги 5–7: ), затем :, затем перенос строки; каждый элемент примерно в 0,99.
    • Шаг 8: отступ в четыре пробела примерно в 0,97.

    На шагах 5–8 модель достигает высокой степени уверенности в синтаксических токенах. Однако это не означает понимание Python — речь идет лишь о простом заполнении шаблонов, выученном на корпусе, в котором все определения функций выглядят одинаково.

    Настоящий выбор происходит раньше, на шагах 1–4, когда определяются имя функции, имена параметров и общая структура. Эти выборы формируются под влиянием содержимого запроса через механизм внимания. Токен sort в запросе имеет высокий вес внимания при генерации имени функции.

    Температура при генерации кода

    Инструменты вроде Copilot обычно работают при низкой температуре, около 0,1–0,3, для обработки кода:

    • Синтаксические токены должны быть почти детерминированными.
    • Часто существует только один правильный вариант реализации.
    • Изобретенные API становятся причиной серьезных сбоев при высокой температуре.

    Для творческих элементов, таких как имена переменных, документация и комментарии, допустима немного более высокая температура. Некоторые инструменты также используют метод поиска лучшего потока, который одновременно сохраняет кратчайшие последовательности из k элементов и в конце выбирает ту, у которой наибольшая совместная вероятность.

    Почему более крупные модели ведут себя иначе

    Модели объемом 7 миллиардов и 70 миллиардов элементов имеют одинаковую архитектуру. Разница заключается в масштабе: больше слоев, более большое значение d_model и больше голов внимания. Тем не менее более крупные модели демонстрируют качественные улучшения, включая многошаговое рассуждение, более корректный код и способность к обучению в контексте.

    В масштабном режиме модель учится не только статистике поверхностных токенов. Она формирует сжатые представления более глубоких закономерностей, таких как алгоритмическая структура, логические зависимости и ограничения типов. Модель объемом 70 миллиардов параметров имела достаточно кода с ошибками наряду с примерами неудачных тестов, что позволило ей косвенно связать определенные закономерности с корректностью работы. Это и является эмпирической основой гипотезы масштабирования: способности растут по плавной кривой в зависимости от вычислительных мощностей, объема данных и количества параметров, причем качество кода развивается так же надежно, как и любой другой навык.

    Ограничения, вытекающие из конструкции

    Знание механизма работы модели позволяет выявить некоторые строгие ограничения:

    1. Выполнение. Внутри модели отсутствует механизм выполнения. То, что она генерирует, напоминает результат корректного выполнения, но на самом деле ничего не выполнялось.
    2. Гарантированная точность. Прогноз основан на максимизации вероятности в рамках обучающего набора данных, а не на логической корректности.
    3. Настоящая новизна. Алгоритм без статистических аналогов в обучающих данных невозможен к созданию. Модель может комбинировать и адаптировать, но не создавать что-то новое.
    4. Точное воспроизведение. Запасных таблиц нет; вся память распределена между весами, поэтому API, сигнатуры функций и версии библиотек иногда могут быть искажены.

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

    Краткий обзор всей картины

    • Токен — это подсловная единица, соответствующая примерно 0,75 английского слова.
    • Прогноз формируется с помощью функции softmax над словарем на каждом шаге.
    • Механизм самообращения позволяет каждому токену учитывать все предыдущие токены с помощью масштабированных произведений запроса и ключа.
    • Многоголовой механизм обращения выполняет несколько таких процессов параллельно для захвата различных связей.
    • Функция FFN выполняет роль памяти вида «ключ-значение», хранящей фактические ассоциации.
    • Генерация кода происходит аналогично генерации текста, причем синтаксис формируется на основе статистики обучения.
    • Параметр температуры определяет степень «остроты» распределения выборки.
    • Ключевые ограничения заключаются в отсутствии гарантированной корректности выполнения и настоящей новизны.

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

    Связанные материалы

  • Практические заметки: Как на самом деле работают LLM: токены, трансформеры и следующий токен — Подробное руководство по Практическим заметкам: Как на самом деле работают LLM: токены, трансформеры и следующий токен, включающее шаблоны контрактов, проверок и готовые фрагменты кода для команд, использующих эту модель.
  • Пятьдесят лет исследований по поиску информации, скрытых в вашей системе RAG — Технологии разбиения данных на фрагменты в RAG, гибридный поиск, HyDE, переранжирование и оценка результатов имеют свои предшественников, существующих уже десятилетиями, в области поиска информации. Обзор этих исследований и их ограничений.
  • Практические заметки: ZQ Intelligence: Orchestrator-Specialist Agents для финансовой сферы — Подробное руководство по использованию Практических заметок: ZQ Intelligence: Orchestrator-Specialist Agents для финансовой сферы: контракты, проверки и слоты для вставки кода для команд, разрабатывающих эту архитектуру.
  • Почему индийские языки потребляют больше токенов в LLM и как исправить токенизаторы — Одно и то же предложение занимает 5 токенов на английском и 34 на тамильском. Рассматривается, как это происходит из-за данных для обучения BPE, как осуществляется перебалансировка и изменение размера словаря, а также как работает расширение словаря.