Авторское право и лицензия
Код, представленный в статье, написан Await IT (await.it.bx@gmail.com)
и распространяется под лицензией MIT с обязательным указанием авторства.
Дата публикации кода: 01.06.2026
GitHub репозиторий: https://github.com/Await-IT/GPT-Like
© 2026 Await IT. Все права на исходный код защищены.
Введение: почему своя GPT?
Когда все вокруг пользуются ChatGPT и Claude, возникает естественный вопрос: а что, если попробовать сделать нечто подобное самому? Не для того, чтобы конкурировать с гигантами, а чтобы понять изнутри, как работают современные языковые модели.
Этот проект — моя попытка пройти весь путь: от токенизации текста до генерации кода. Не используя готовые решения от HuggingFace, а реализуя каждый компонент самостоятельно. И знаете что? Это оказалось одновременно сложнее и интереснее, чем я предполагал.
Сложность №1: токенизация кода — это не просто разбить на слова
Проблема
Обычный BPE-токенизатор ломается на Python-коде. Он не понимает:
-
Значимость отступов
-
Разницу между
defкак ключевым словом иdefкак частью слова -
Структуру кода (классы, функции, условия)
Решение: CodeTokenizer с AST-анализом
class CodeTokenizer:
@staticmethod
def tokenize_python_code(code):
tokens = []
try:
token_stream = tokenize.generate_tokens(io.StringIO(code).readline)
for tok in token_stream:
token_type = tokenize.tok_name[tok.type]
token_value = tok.string
if token_type == 'INDENT':
tokens.append(Config.code_indent_token)
elif token_type == 'DEDENT':
tokens.append(Config.code_dedent_token)
# ... обработка ключевых слов, строк, чисел
Что это даёт?
-
<indent>/<dedent>вместо четырёх пробелов — модель учится структуре -
<def>,<class>,<if>как специальные токены — понимание синтаксиса -
<string>,<number>,<comment>— типовая информация
Результат
# Исходный код:
def factorial(n):
if n == 0:
return 1
# Токенизация:
['<def>', 'factorial', '(', 'n', ')', ':', '<newline>',
'<indent>', '<if>', 'n', '==', '<number>', ':', '<newline>',
'<indent>', '<return>', '<number>', '<newline>', '<dedent>']
Сложность №2: архитектура Transformer — мои ошибки
Ошибка №1: Encoder вместо Decoder
Первая версия использовала nn.TransformerEncoder — это архитектура BERT, а не GPT. GPT требует маскированного внимания (look-ahead mask), чтобы токен “видел” только предыдущие токены.
# Было (НЕПРАВИЛЬНО):
encoder_layer = nn.TransformerEncoderLayer(...)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers)
# Стало (правильнее, но ещё не идеально):
def generate_attention_mask(self, seq_len, device):
mask = torch.triu(torch.ones(seq_len, seq_len, device=device), diagonal=1).bool()
return mask
Ошибка №2: устаревшие позиционные эмбеддинги
Использование nn.Embedding для позиций — подход 2018 года. Современные модели используют:
-
RoPE (Rotary Positional Embeddings) — как в LLaMA
-
ALiBi — как в MPT
-
Sinusoidal — классика, но лучше, чем learnable
Я оставил learnable эмбеддинги для простоты, но в README проекта честно указал это как ограничение.
Сложность №3: обучение на маленьких данных
Проблема
У меня не было доступа к терабайтам текста. Только небольшие датасеты с:
-
Примерами Python-кода
-
Диалогами в формате вопрос-ответ
-
Техническими статьями
Решения
-
Аугментация данных: перестановка строк кода, замена имён переменных
-
Контролируемая генерация: использование специальных токенов
<user>,<bot> -
Смешанная точность (AMP): позволила увеличить batch size
def fast_train_step(model, batch, optimizer, scaler=None, use_amp=False):
if use_amp and scaler is not None:
with torch.cuda.amp.autocast(): # Mixed precision
outputs = model(inputs)
loss = model.compute_loss(outputs, targets)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
# ...
Что получилось (честные результаты)
Успехи
-
Токенизатор работает отлично — корректно разбирает сложный Python-код
-
Модель обучается — loss стабильно снижается
-
Генерация синтаксически корректного кода (в простых случаях)
Пример генерации
Вход: <user> Напиши функцию для суммы двух чисел
Выход: <bot> <start>
def add_numbers(a, b):
result = a + b
return result
<end>
Неудачи
-
Логические ошибки — модель генерирует синтаксически правильный, но семантически бессмысленный код
-
Ограниченный контекст — 1024 токена недостаточно для сложных программ
-
Переобучение на маленьких данных — модель запоминает примеры, а не учится общим принципам
Технические детали реализации
Архитектура
class TransformerModel(nn.Module):
def __init__(self, vocab_size, d_model=256, n_head=8,
num_layers=6, d_ff=2048, dropout=0.1):
super().__init__()
self.token_embedding = nn.Embedding(vocab_size, d_model)
self.position_embedding = nn.Embedding(max_seq_len, d_model)
# ... Transformer слои
Параметры модели:
-
d_model: 256 (микроскопически мало, но для обучения достаточно)
-
Слои: 6
-
Головы внимания: 8
-
Всего параметров: ~10 миллионов (GPT-3: 175 миллиардов)
Pipeline обучения
# 1. Токенизация данных
tokenizer.train(Config.pretrain_file, Config.vocab_size)
# 2. Создание датасета
dataset = DialogDataset(file_path, tokenizer, max_length)
# 3. Обучение модели
model = train_fast(model, train_loader, val_loader, epochs=30)
# 4. Генерация
text = generate_text(model, tokenizer, prompt, max_length=100)
Что я узнал (ключевые инсайты)
1. Токенизация — ключ к успеху
Плохая токенизация = плохая модель. Особенно для кода.
2. Данные важнее архитектуры
Можно иметь идеальную архитектуру, но без качественных данных модель не научится.
3. Отладка LLM — это сложно
Когда модель генерирует ерунду, непонятно: проблема в данных, архитектуре или обучении?
4. Сообщество — лучший учитель
Каждый issue и PR на GitHub учил меня чему-то новому.
Как использовать проект
Для обучения
git clone https://github.com/Await-IT/GPT-Like
cd educational-gpt-python
pip install -r requirements.txt
python train.py
Для экспериментов
from src.tokenizer import ImprovedBPETokenizer
from src.model import TransformerModel
# Создайте свою модель
model = TransformerModel(vocab_size=50000)
# Обучите на своих данных
# Экспериментируйте с архитектурой
Ограничения и что дальше
Текущие ограничения
-
Слишком маленькая модель
-
Устаревшие компоненты (нет RoPE, SwiGLU)
-
Нет эффективных оптимизаций (FlashAttention)
-
Только Python (хотя токенизатор можно расширить)
Планы на будущее
-
Реализация RoPE — уже в работе
-
Поддержка больше языков — JavaScript, Java, C++
-
Увеличение масштаба — переход к моделям на 100M+ параметров
-
Интеграция с IDE — плагин для VSCode
Выводы
Этот проект — не про создание конкурента ChatGPT. Это про понимание. Про то, чтобы за красивым интерфейсом и плавными ответами увидеть сложную систему из эмбеддингов, внимания и слоев нормализации.
Самые важные уроки:
-
Начинайте с простого — даже минимальная работающая модель даёт невероятное понимание
-
Не бойтесь ошибок — каждая ошибка в архитектуре учит лучше, чем успех
-
Делитесь кодом — обратная связь от сообщества бесценна
Ссылки
-
GitHub репозиторий: https://github.com/Await-IT/GPT-Like
-
Colab ноутбук для быстрого старта: (в разработке)
-
Документация API: (в разработке)
Лицензия
Проект распространяется под MIT лицензией. Вы можете:
-
Использовать код в коммерческих проектах
-
Модифицировать и распространять изменения
-
Использовать в академических работах
Единственное условие: сохранение уведомления об авторских правах.
Это учебный проект. Для production использования рекомендую библиотеки типа HuggingFace Transformers, которые реализуют современные архитектуры с оптимизациями.
Для тех, кто хочет глубже: в репозитории есть issues с пометкой “good first issue” — отличные задачи для начала контрибьютинга. А если у вас есть идеи, как улучшить токенизатор или архитектуру — welcome to PR!
P.S. Если статья была полезной, посетите наш Телеграмм канал
Автор: Await-IT


