Никакого PyTorch. Никакого TensorFlow. Только чистый Python и базовая математика.
За время работы над докторской я перечитал множество реализаций трансформеров. Плотные кодовые базы. Тысячи файлов. Зависимости, нагроможденные на зависимости. Открываешь репозиторий, запускаешь pip install -r requirements.txt и смотришь, как скачиваются 400 пакетов, прежде чем ты вообще увидишь, как твоя модель тренируется (а потом ошибки, проблемы с версиями... и так далее).
А потом, 11 февраля 2026 года, Андрей Карпаты выложил один-единственный файл на Python, который обучает и запускает GPT с нуля. 243 строки. Ноль зависимостей.
Его единственный импорт? os, math, random и argparse. Вот и все. Это весь LLM. Он назвал это «арт-проектом». Я называю это лучшим образовательным материалом по ИИ, который сейчас существует в интернете. Позвольте мне провести вас через каждую часть этого кода, как если бы я объяснял это другу за чашкой кофе.
Прежде чем мы прикоснемся к коду, давайте проясним, что делает microGPT. Он скачивает список детских имен. Изучает закономерности в этих именах. Затем генерирует новые, фейковые имена, которые звучат как настоящие, но никогда не существовали.
Вот и все. Тот же концепт, что и у ChatGPT, только крошечный. ChatGPT учился на всем интернете. Эта модель учится на текстовом файле с именами. Но алгоритм идентичен. Механизм внимания, цикл обучения, то, как он предсказывает следующий токен: это та же математика, что работает внутри GPT-4. Просто в микромасштабе.
Думайте об этом так: у игрушечной машинки и у Tesla есть двигатель, колеса, руль и тормоза. Игрушечная машинка не выиграет гонок, но если вы хотите понять, как работает автомобиль, игрушка подойдет идеально.
Компьютеры не понимают букв. Они понимают цифры.
Поэтому самая первая задача - превратить каждый символ в число. Буква a становится 2, b становится 3 и так далее. Есть также два специальных токена: <BOS> (Начало последовательности, «Эй, модель, начинается новое имя!») и <EOS> (Конец последовательности, «Это имя закончено!»).
stoi конвертирует строки в целые числа. itos конвертирует целые числа обратно в строки. Вот и весь ваш токенизатор.
ChatGPT использует гораздо более модный токенизатор под названием BPE (Byte Pair Encoding), который группирует частые комбинации букв в единые токены. Но идея идентична: текст на входе, цифры на выходе.
Вот где начинается красота.
Карпаты создает мини-версию движка автоградиента PyTorch примерно за 40 строк.
Позвольте объяснить, почему это важно.
Когда нейросеть делает предсказание, поначалу она обычно ошибается. Нам нужно выяснить: какие числа (веса) нам нужно подкрутить и на сколько, чтобы она ошибалась меньше?
Именно это делает обратное распространение ошибки (backpropagation). А ему нужны градиенты - по сути, ему нужно знать: «если я чуть-чуть пошевелю этот вес, как сильно изменится финальная ошибка?»
Класс Value оборачивает каждое число в сети и отслеживает:
data: само число
grad: насколько сильно меняется финальная потеря, если изменить это число
_backward: инструкции для вычисления этого градиента
_prev: какие другие значения использовались для создания этого числа
Каждый раз, когда вы занимаетесь математикой (сложение, умножение, возведение в степень и т.д.), класс Value тихо строит граф операций за кулисами. Когда обучение на одном примере закончено, вы вызываете .backward(), и градиенты текут обратно через этот граф автоматически.
Это буквально тот же алгоритм, что работает внутри PyTorch, когда вы вызываете loss.backward(). Карпаты просто написал его с нуля, используя списки Python и рекурсию.
Каждая нейросеть - это просто набор чисел (называемых весами или параметрами). До обучения они случайны. После обучения они кодируют выученные закономерности.
Вот что делает каждая матрица весов:
wte (Word Token Embedding): Превращает каждый ID токена в вектор из 16 чисел. Думайте об этом как о наделении каждого символа «личностью»: позицией в 16-мерном пространстве, где похожие символы оказываются рядом.
wpe (Word Position Embedding): Говорит модели, где в последовательности находится каждый символ. «а» на позиции 1 должно обрабатываться иначе, чем «а» на позиции 5.
Стандартная конфигурация: 16 измерений эмбеддинга, 4 головы внимания, 1 слой, длина последовательности 8. Это дает примерно 4000 параметров. У GPT-4 их более триллиона. Архитектура та же, масштаб дико разный.
Это ядро. Давайте разберем функцию gpt() по частям.
Шаг 1: Эмбеддинг
Берем эмбеддинг символа. Берем эмбеддинг позиции. Складываем их вместе. Теперь модель знает и что это за символ, и где он находится.
Шаг 2: RMSNorm
Перед каждым крупным вычислением мы нормализуем значения, чтобы они не взрывались и не сжимались до нуля. Представьте это как просьбу ко всем участникам дискуссии говорить с одинаковой громкостью.
Шаг 3: Внимание (Звезда шоу)
Это та часть, о которой все говорят. «Attention is All You Need»: знаменитая статья 2017 года. Вот она, голая, на чистом Python.
Для текущего токена вычисляем три вещи:
Query (Q) - Запрос: «Что я ищу?»
Key (K) - Ключ: «Что я содержу?»
Value (V) - Значение: «Какую информацию я несу?»
Вот что происходит на простом языке:
Запрос текущего токена спрашивает: «Какие предыдущие токены важны для меня?»
Он вычисляет скалярное произведение с Ключом каждого предыдущего токена (как оценка совместимости).
Эти оценки проходят через softmax (превращаясь в вероятности, которые в сумме дают 1).
Векторы Значений всех токенов затем смешиваются, взвешенные по этим оценкам.
Если модель генерирует имя «Micha» и собирается предсказать следующую букву, механизм внимания позволяет текущей позиции «оглянуться» на M, i, c, h и a, и решить, какие из них важнее всего для предсказания того, что будет дальше.
Шаг 4: Остаточное соединение
После внимания мы добавляем обратно исходный вход. Это называется остаточным соединением (или skip connection).
Зачем? Потому что это создает «шоссе» для градиентов во время обучения. Без этого глубокие сети тренировать почти невозможно. Это как сказать: «Чему бы ты ни научился благодаря вниманию, просто добавь это к тому, что ты уже знал».
Шаг 5: MLP (Полносвязная сеть)
После того как внимание решило, на какие токены смотреть, MLP обрабатывает эту информацию. MLP расширяет 16-мерный вектор до 64 измерений, применяет нелинейность и сжимает обратно до 16.
Зачем расширять и сжимать? Думайте об этом как о мозговом штурме. Сначала вы генерируете кучу идей (расширение до 64), отфильтровываете плохие (ReLU убивает отрицательные значения), затем резюмируете (сжатие обратно до 16).
Шаг 6: Проекция в словарь
Наконец, модель использует ту же матрицу эмбеддингов (wte), чтобы спроецировать данные обратно в размер словаря. Выход - это оценка для каждого возможного следующего символа. Выше оценка = модель думает, что этот символ вероятнее всего будет следующим.
Для каждого шага берем одно имя из датасета. Превращаем в ID токенов. Добавляем BOS в начало и EOS в конец.
Для каждой позиции модель видит текущий токен и предсказывает следующий. Потеря (loss) - это отрицательное логарифмическое правдоподобие: если модель присваивает высокую вероятность правильному следующему символу, потеря низкая. Если низкую - потеря высокая.
Затем loss.backward() вычисляет градиенты для каждого параметра, и оптимизатор Adam обновляет их.
Adam похож на градиентный спуск с памятью. Вместо того чтобы просто следовать текущему градиенту, он отслеживает импульс (среднее направление) и скорость (среднюю величину), чтобы большие градиенты не доминировали. Это тот же оптимизатор, что используется для обучения GPT-4, DALL-E и всех крупных современных моделей.
Начинаем с BOS. Спрашиваем модель: «что дальше?». Выбираем из распределения вероятностей. Подаем это предсказание обратно на вход. Повторяем, пока модель не выдаст EOS.
Это авторегрессионная генерация: то же самое, что делает ChatGPT каждый раз, когда вы отправляете ему сообщение. Один токен за раз, каждый обусловлен всем, что было до него.
Кстати, о практике. Понимать, как работает код - бесценно, но иногда нужно просто быстро получить результат от мощной модели.
Сервисы вроде BotHub дают возможность экспериментировать с различными моделями ИИ для разработки и других задач - от генерации кода до анализа и оптимизации.
Для доступа не требуется VPN, можно использовать российскую карту.
Вот вещь, которая взорвала мне мозг.
Каждая строчка кода за пределами этих 243 строк: тысячи файлов в PyTorch, ядра CUDA, фреймворки распределенного обучения, модные токенизаторы - все это просто оптимизация. Чтобы сделать быстрее. Чтобы сделать больше. Чтобы запустить на тысячах видеокарт.
Но алгоритм? Сам интеллект? Он прямо здесь.
Как сказал Карпаты: «Это полное алгоритмическое содержание того, что необходимо. Все остальное - лишь для эффективности. Я не могу упростить это еще сильнее».
Это путь сжатия длиной в 6 лет для Карпаты:
2020: micrograd (движок автоградиента)
2020: minGPT (GPT на PyTorch)
2023: nanoGPT (обучение продакшн-уровня)
2024: llm.c (чистый C/CUDA, без фреймворков)
2026: microGPT (алгоритм и ничего больше)
Каждый шаг снимал слой абстракции. Эта финальная версия удалила их все.
Индустрия тратит 400 миллиардов долларов на инфраструктуру ИИ в этом году. Но ключевой алгоритм, который питает все это? Он помещается в файл меньше, чем большинство документов README.
Источник


