Документация и примеры: унификация путей, стабильная работа на CPU, расширенный корпус для токенизатора, end-to-end пайплайн обучения и генерации. Исправлены все ошибки с устройствами и индексами, добавлены проверки и диагностика prompt.

This commit is contained in:
Sergey Penkovsky
2025-07-23 14:34:10 +03:00
parent a895c59bfe
commit e0813fedc6
22 changed files with 768 additions and 93 deletions

View File

@@ -3,6 +3,45 @@
[![Python Version](https://img.shields.io/badge/python-3.8%2B-blue)]() [![Python Version](https://img.shields.io/badge/python-3.8%2B-blue)]()
[![PyTorch Version](https://img.shields.io/badge/pytorch-1.10%2B-orange)]() [![PyTorch Version](https://img.shields.io/badge/pytorch-1.10%2B-orange)]()
> **Актуально для Simple-LLM v1.0 (июль 2025)**
---
## 🚀 Установка
### Через pip (локально)
```bash
pip install .
```
### Через pip (с PyPI)
```bash
pip install simple-llm
```
После установки вы сможете запускать примеры и использовать модули из любого места.
**Краткая инструкция по обучению на своих данных:**
1. Обучите BPE-токенизатор на тексте (см. `simple_llm.tokenizer.bpe.BPE`).
2. Токенизируйте корпус и создайте датасет через `GetData`.
3. Инициализируйте модель `GPT` с нужными параметрами.
4. Обучите модель одной строкой: `model.fit(train_loader, num_epoch=10)`.
5. Для подробной инструкции и примеров см. [документацию](doc/train_on_custom_data_ru.md).
---
**Структура README:**
- Обзор
- Быстрый старт
- Основные компоненты
- Документация
- Тестирование
- Как внести вклад
- Лицензия
- [FAQ](#faq)
---
Простая и понятная реализация языковой модели GPT-стиля с нуля на PyTorch Простая и понятная реализация языковой модели GPT-стиля с нуля на PyTorch
## 🔍 Обзор ## 🔍 Обзор
@@ -114,5 +153,29 @@ pytest tests/
4. Запушьте ветку (`git push origin feature/AmazingFeature`) 4. Запушьте ветку (`git push origin feature/AmazingFeature`)
5. Откройте Pull Request 5. Откройте Pull Request
---
## ❓ FAQ
**Q: Как установить Simple-LLM, чтобы работали все импорты?**
A: Рекомендуется установить через pip (локально: `pip install .` или с PyPI: `pip install simple-llm`). Тогда все примеры и импорты будут работать из любой директории.
**Q: Как запустить Simple-LLM на CPU?**
A: Передайте параметр `device="cpu"` при инициализации модели или обработке данных.
**Q: Как использовать свой датасет?**
A: Используйте класс `GetData` из `simple_llm.data.get_data` для подготовки своих последовательностей. Следуйте формату `(input_ids, targets)`.
**Q: Где посмотреть примеры?**
A: В папке [`example/`](./example/) есть скрипты генерации и обучения.
**Q: Ошибка CUDA out of memory!**
A: Уменьшите размер batch_size или размерность модели, либо используйте CPU.
**Q: Как добавить новый модуль или улучшение?**
A: Ознакомьтесь с документацией, следуйте рекомендациям по вкладу и открывайте Pull Request.
---
## 📜 Лицензия ## 📜 Лицензия
Распространяется под лицензией MIT. См. [LICENSE](./LICENSE) Распространяется под лицензией MIT. См. [LICENSE](./LICENSE)

30
data/corpus/corpus.txt Normal file
View File

@@ -0,0 +1,30 @@
Наука — это организованное стремление к познанию окружающего мира. Современные технологии позволяют анализировать большие объёмы данных и делать открытия в различных областях. Искусственный интеллект и машинное обучение становятся неотъемлемой частью нашей жизни, помогая автоматизировать рутинные задачи и открывать новые горизонты для исследований.
Образование играет ключевую роль в развитии общества. Благодаря доступу к информации, люди могут обучаться дистанционно, осваивать новые профессии и совершенствовать навыки.
Культура и искусство вдохновляют на творчество, объединяют людей и способствуют развитию критического мышления. Чтение книг, посещение театров и музеев обогащают внутренний мир каждого человека.
Здоровый образ жизни включает в себя правильное питание, физическую активность и заботу о психоэмоциональном состоянии. Регулярные занятия спортом укрепляют организм и повышают работоспособность.
Экология — важная сфера, требующая внимания каждого. Сохранение природы, рациональное использование ресурсов и снижение загрязнения окружающей среды — задачи, которые стоят перед современным обществом.
Азбука: А а Б б В в Г г Д д Е е Ё ё Ж ж З з И и Й й К к Л л М м Н н О о П п Р р С с Т т У у Ф ф Х х Ц ц Ч ч Ш ш Щ щ Ъ ъ Ы ы Ь ь Э э Ю ю Я я.
Латиница: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z.
Цифры: 0 1 2 3 4 5 6 7 8 9. Пример: В 2025 году 13 студентов успешно сдали экзамен по информатике.
Знаки препинания: . , ! ? : ; " ' ( ) [ ] { } < > — - _ / \ | @ # $ % ^ & * + = ~ `
Пример e-mail: test.user@example.com
Дата и время: 23 июля 2025 года, 14:30.
Математические выражения: x = y^2 + 3*z - (a/2).
Вопрос: Какой сегодня день недели? Ответ: Среда!
Спецсимволы в тексте: @home #важно $100 %успеха &друзья *звезда +плюс =равно ~волна `обратная кавычка`
"Каждый охотник желает знать, где сидит фазан" — известная фраза для проверки всех цветов радуги.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,52 +0,0 @@
<mxfile>
<diagram name="Page-1">
<mxGraphModel dx="1200" dy="580">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="2" value="Начало" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="100" y="60" width="120" height="60"/>
</mxCell>
<mxCell id="3" value="Разбить текст на символы" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="100" y="160" width="120" height="80"/>
</mxCell>
<mxCell id="4" value="" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="2" target="3" edge="1">
<mxGeometry relative="1"/>
</mxCell>
<mxCell id="5" value="Подсчитать частоты пар" style="whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="100" y="280" width="120" height="60"/>
</mxCell>
<mxCell id="6" value="" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="3" target="5" edge="1">
<mxGeometry relative="1"/>
</mxCell>
<mxCell id="7" value="Выбрать наиболее частую пару" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="100" y="380" width="120" height="80"/>
</mxCell>
<mxCell id="8" value="" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="5" target="7" edge="1">
<mxGeometry relative="1"/>
</mxCell>
<mxCell id="9" value="Заменить пару новым токеном" style="whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="100" y="500" width="120" height="60"/>
</mxCell>
<mxCell id="10" value="" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7" target="9" edge="1">
<mxGeometry relative="1"/>
</mxCell>
<mxCell id="11" value="Достигнут лимит словаря?" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="100" y="600" width="120" height="80"/>
</mxCell>
<mxCell id="12" value="" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9" target="11" edge="1">
<mxGeometry relative="1"/>
</mxCell>
<mxCell id="13" value="Конец" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="100" y="720" width="120" height="60"/>
</mxCell>
<mxCell id="14" value="Да" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="11" target="13" edge="1">
<mxGeometry relative="1"/>
</mxCell>
<mxCell id="15" value="Нет" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="11" target="5" edge="1">
<mxGeometry relative="1"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@@ -1,5 +1,26 @@
# Byte Pair Encoding (BPE) Algorithm # Byte Pair Encoding (BPE) Algorithm
> **Документ актуален для Simple-LLM v1.0 (июль 2025)**
---
**Краткое summary:**
Этот документ подробно описывает алгоритм Byte Pair Encoding (BPE) — как он используется для токенизации текста, как устроен процесс обучения словаря и как происходит энкодинг/декодинг текста. Документ предназначен для пользователей Simple-LLM и всех, кто хочет понять внутреннюю механику BPE.
---
**Структура документа:**
- Введение
- Основные понятия
- Алгоритм работы (обучение словаря)
- Псевдокод
- Пример работы
- Алгоритм энкодинга (токенизации)
- Алгоритм декодирования
- Типовые ошибки и их решения
---
## Введение ## Введение
Byte Pair Encoding (BPE) - это алгоритм компрессии данных, адаптированный для токенизации текста в обработке естественного языка. В контексте языковых моделей BPE используется для создания эффективного словаря подстрок (токенов). Byte Pair Encoding (BPE) - это алгоритм компрессии данных, адаптированный для токенизации текста в обработке естественного языка. В контексте языковых моделей BPE используется для создания эффективного словаря подстрок (токенов).

View File

@@ -1,5 +1,24 @@
# Декодер Transformer # Декодер Transformer
> **Документ актуален для Simple-LLM v1.0 (июль 2025)**
---
**Краткое summary:**
Документ описывает работу декодера Transformer: архитектуру, алгоритм, пример использования, параметры и типовые ошибки.
---
**Структура документа:**
- Назначение
- Алгоритм работы
- Использование
- Параметры
- Особенности
- Типовые ошибки и их решения
---
## Назначение ## Назначение
Декодер - ключевой компонент архитектуры Transformer, предназначенный для: Декодер - ключевой компонент архитектуры Transformer, предназначенный для:
- Генерации последовательностей (текст, код и др.) - Генерации последовательностей (текст, код и др.)
@@ -75,15 +94,40 @@ masked_output = decoder(x, mask)
- Генерация текста - Генерация текста
- Кодогенерация - Кодогенерация
## Особенности реализации ## Рекомендации
- Используйте корректные маски для автопрегрессивного декодирования
- Следите за размерностью входа и маски
- Для сложных случаев используйте teacher forcing
1. **Масштабирование**: ---
- Поддержка длинных последовательностей
- Оптимизированные вычисления внимания
2. **Обучение**: ## Типовые ошибки и их решения
- Поддержка teacher forcing
- Автопрегрессивное декодирование ### Ошибка: Размерности не совпадают при подаче входа или маски
**Возможные причины:**
- Размерность входного тензора не совпадает с emb_size
- Форма маски не совпадает с [seq_len, seq_len]
**Решение:**
- Проверьте, что размерность входа и маски соответствует требованиям
### Ошибка: Модель не обучается (loss не уменьшается)
**Возможные причины:**
- Ошибка в подключении слоя к модели
- Ошибка в маскировании (утечка будущего)
**Решение:**
- Проверьте корректность маски
- Проверьте, что параметры декодера передаются в оптимизатор
### Ошибка: CUDA out of memory
**Возможные причины:**
- Слишком большой batch_size, seq_len или emb_size
**Решение:**
- Уменьшите batch_size, seq_len или emb_size
---
3. **Оптимизации**: 3. **Оптимизации**:
- Кэширование ключей/значений - Кэширование ключей/значений

View File

@@ -1,5 +1,24 @@
# FeedForward - Прямая полносвязная сеть трансформера # FeedForward - Прямая полносвязная сеть трансформера
> **Документ актуален для Simple-LLM v1.0 (июль 2025)**
---
**Краткое summary:**
Документ описывает модуль двухслойной прямой полносвязной сети (Feed Forward) в трансформерах. Включает алгоритм, пример использования, параметры и типовые ошибки.
---
**Структура документа:**
- Назначение
- Алгоритм работы
- Пример использования
- Параметры
- Особенности
- Типовые ошибки и их решения
---
## Назначение ## Назначение
Модуль реализует двухслойную нейронную сеть, которая: Модуль реализует двухслойную нейронную сеть, которая:
- Добавляет нелинейность в трансформер - Добавляет нелинейность в трансформер
@@ -55,9 +74,40 @@ output = ff(x) # [1, 10, 512]
| `emb_size` | int | Размерность входных/выходных векторов | | `emb_size` | int | Размерность входных/выходных векторов |
| `dropout` | float | Вероятность dropout (0.0-1.0)| | `dropout` | float | Вероятность dropout (0.0-1.0)|
## Особенности ## Рекомендации
- Сохраняет размерность входа/выхода - Dropout обычно выбирают 0.10.3
- Автоматически обрабатывает batch и последовательности - Следите, чтобы emb_size совпадал с размерностью входа/выхода
- Используйте режимы train/eval корректно
- Для визуализации используйте [пример](/example/feed_forward_example.py)
---
## Типовые ошибки и их решения
### Ошибка: Размерности не совпадают при прямом проходе
**Возможные причины:**
- emb_size не совпадает с размерностью входных данных
**Решение:**
- Проверьте, что emb_size слоя FeedForward совпадает с размерностью последнего слоя перед ним
### Ошибка: Модель не обучается (loss не уменьшается)
**Возможные причины:**
- Dropout слишком высокий
- Ошибка в подключении слоя к модели
**Решение:**
- Попробуйте уменьшить dropout
- Проверьте, что слой FeedForward включён в модель и его параметры передаются в оптимизатор
### Ошибка: CUDA out of memory
**Возможные причины:**
- Слишком большой batch_size или размерность emb_size
**Решение:**
- Уменьшите batch_size или emb_size
---
- Поддерживает режимы train/eval - Поддерживает режимы train/eval
[Пример визуализации](/example/feed_forward_example.py) [Пример визуализации](/example/feed_forward_example.py)

View File

@@ -1,5 +1,24 @@
# Документация по GPT модели # Документация по GPT модели
> **Документ актуален для Simple-LLM v1.0 (июль 2025)**
---
**Краткое summary:**
Этот документ подробно описывает архитектуру и практическое применение GPT (Generative Pre-trained Transformer) — авторегрессивной языковой модели, реализованной в Simple-LLM. Документ предназначен для разработчиков и исследователей, желающих понять детали реализации и настройки GPT-модели.
---
**Структура документа:**
- Общее описание
- Архитектура и алгоритм
- Практическое использование
- Особенности генерации
- Обучение модели
- Типовые ошибки и их решения
---
## 1. Общее описание ## 1. Общее описание
GPT (Generative Pre-trained Transformer) - это авторегрессивная модель генерации текста на основе архитектуры трансформера. GPT (Generative Pre-trained Transformer) - это авторегрессивная модель генерации текста на основе архитектуры трансформера.

View File

@@ -1,5 +1,22 @@
# HeadAttention - Механизм самовнимания одной головы # HeadAttention - Механизм самовнимания одной головы
> **Документ актуален для Simple-LLM v1.0 (июль 2025)**
---
**Краткое summary:**
Данный файл описывает реализацию механизма внимания одной головы (Single Head Attention) в трансформерах. Охватывает основные этапы вычислений, пример использования и типовые ошибки.
---
**Структура документа:**
- Назначение
- Алгоритм работы
- Пример использования
- Типовые ошибки и их решения
---
## Назначение ## Назначение
Модуль реализует механизм внимания одной головы из архитектуры Transformer. Основные применения: Модуль реализует механизм внимания одной головы из архитектуры Transformer. Основные применения:
- Моделирование зависимостей в последовательностях - Моделирование зависимостей в последовательностях
@@ -58,6 +75,42 @@ x = torch.randn(2, 10, emb_size)
output = attn_head(x) # [2, 10, head_size] output = attn_head(x) # [2, 10, head_size]
``` ```
---
## Типовые ошибки и их решения
### Ошибка: Размерности не совпадают при умножении матриц
**Возможные причины:**
- Несовпадение emb_size и head_size при инициализации
- Некорректная форма входного тензора
**Решение:**
- Проверьте, что emb_size делится на head_size без остатка
- Убедитесь, что вход имеет форму [batch_size, seq_len, emb_size]
### Ошибка: CUDA out of memory
**Возможные причины:**
- Слишком большой batch_size или seq_len
**Решение:**
- Уменьшите batch_size или seq_len
### Ошибка: Не работает маскирование
**Возможные причины:**
- Неправильная форма или тип маски
**Решение:**
- Проверьте, что mask совпадает по размерности с attention scores
## Рекомендации по использованию
- Следите, чтобы emb_size делился на head_size без остатка
- Для визуализации весов используйте специализированные инструменты
- Для сложных задач используйте MultiHeadAttention
- Размер головы (`head_size`) обычно выбирают 64-128
- Для длинных последовательностей (>512) используйте оптимизации:
- Локальное внимание
- Разреженные паттерны
## Особенности реализации ## Особенности реализации
### Ключевые компоненты ### Ключевые компоненты
@@ -73,11 +126,6 @@ output = attn_head(x) # [2, 10, head_size]
- Поддерживает только causal-режим - Поддерживает только causal-режим
- Фиксированный максимальный размер последовательности - Фиксированный максимальный размер последовательности
## Рекомендации по использованию
1. Размер головы (`head_size`) обычно выбирают 64-128
2. Для длинных последовательностей (>512) используйте оптимизации:
- Локальное внимание
- Разреженные паттерны
3. Сочетайте с MultiHeadAttention для лучшего качества 3. Сочетайте с MultiHeadAttention для лучшего качества
[Дополнительные примеры](/example/attention_examples.py) [Дополнительные примеры](/example/attention_examples.py)

42
doc/index.md Normal file
View File

@@ -0,0 +1,42 @@
# Навигация по документации Simple-LLM
> **Документация актуальна для Simple-LLM v1.0 (июль 2025)**
---
## Содержание
- [Архитектура GPT](./gpt_documentation_ru.md)
- Описание, блок-схемы, режимы генерации, обучение, типовые ошибки
- [Алгоритм BPE](./bpe_algorithm.md)
- Теория, примеры, псевдокод, FAQ
- [Обработка данных](./get_data_documentation_ru.md)
- Форматы, примеры, рекомендации
- [Обучение на своих данных](./train_on_custom_data_ru.md)
- Подробная инструкция по обучению токенизатора и модели
- [Внимание (Attention)](./head_attention_ru.md)
- Описание механизма, формулы
- [Мультиголовное внимание](./multi_head_attention_ru.md)
- Теория, схемы
- [Позиционные эмбеддинги](./positional_embeddings_ru.md)
- Теория, примеры
- [Токен-эмбеддинги](./token_embeddings_ru.md)
- Описание, схемы, примеры
- [Feed Forward слой](./feed_forward_ru.md)
- Теория, формулы
- [Декодер](./decoder_ru.md)
- Архитектура, схема
---
## Как пользоваться документацией
- Для быстрого старта изучите [README.md](../README.md)
- Для понимания архитектуры — [GPT](./gpt_documentation_ru.md) и [BPE](./bpe_algorithm.md)
- Для деталей по каждому модулю — соответствующий файл из списка выше
- Для практики — смотрите примеры в папке `example/`
- Для тестирования — используйте тесты из папки `tests/`
---
**Если вы нашли ошибку или хотите предложить улучшение — создайте issue или pull request на GitHub!**

View File

@@ -1,5 +1,23 @@
# MultiHeadAttention - Многоголовый механизм внимания # MultiHeadAttention - Многоголовый механизм внимания
> **Документ актуален для Simple-LLM v1.0 (июль 2025)**
---
**Краткое summary:**
Документ описывает реализацию многоголового механизма внимания (Multi-Head Attention) в трансформерах. Включает описание алгоритма, пример использования и типовые ошибки.
---
**Структура документа:**
- Назначение
- Алгоритм работы
- Пример использования
- Параметры
- Типовые ошибки и их решения
---
## Назначение ## Назначение
Модуль реализует ключевой компонент архитектуры Transformer, который: Модуль реализует ключевой компонент архитектуры Transformer, который:
- Параллельно вычисляет несколько типов внимания - Параллельно вычисляет несколько типов внимания
@@ -58,6 +76,40 @@ output = mha(x) # [1, 50, 512]
## Параметры ## Параметры
| Параметр | Тип | Описание | | Параметр | Тип | Описание |
|---------------|------|------------------------------| |---------------|------|------------------------------|
## Рекомендации
- Размерность emb_size должна делиться на num_heads * head_size
- Для визуализации весов используйте специализированные инструменты
---
## Типовые ошибки и их решения
### Ошибка: Размерности не совпадают при разделении на головы
**Возможные причины:**
- emb_size не делится на num_heads * head_size
- Некорректная форма входного тензора
**Решение:**
- Проверьте, что emb_size = num_heads * head_size
- Убедитесь, что вход имеет форму [batch_size, seq_len, emb_size]
### Ошибка: CUDA out of memory
**Возможные причины:**
- Слишком большой batch_size, seq_len или число голов
**Решение:**
- Уменьшите batch_size, seq_len или num_heads
### Ошибка: Не работает маскирование
**Возможные причины:**
- Неправильная форма или тип маски
**Решение:**
- Проверьте, что mask совпадает по размерности с attention scores
---
| `num_heads` | int | Количество голов внимания | | `num_heads` | int | Количество голов внимания |
| `emb_size` | int | Размерность входных эмбеддингов| | `emb_size` | int | Размерность входных эмбеддингов|
| `head_size` | int | Размерность каждой головы | | `head_size` | int | Размерность каждой головы |

View File

@@ -1,5 +1,24 @@
# PositionalEmbeddings - Позиционные эмбеддинги # PositionalEmbeddings - Позиционные эмбеддинги
> **Документ актуален для Simple-LLM v1.0 (июль 2025)**
---
**Краткое summary:**
Документ описывает работу слоя позиционных эмбеддингов в трансформерах. Включает алгоритм, пример использования, сравнение подходов и типовые ошибки.
---
**Структура документа:**
- Назначение
- Алгоритм работы
- Пример использования
- Сравнение подходов
- Оптимальные практики
- Типовые ошибки и их решения
---
## Назначение ## Назначение
Позиционные эмбеддинги добавляют информацию о порядке элементов в последовательности. Критически важны для: Позиционные эмбеддинги добавляют информацию о порядке элементов в последовательности. Критически важны для:
- Transformer-архитектур - Transformer-архитектур
@@ -50,7 +69,35 @@ class TransformerBlock(nn.Module):
| Обучаемые | Да | Гибкость | Требует данных | | Обучаемые | Да | Гибкость | Требует данных |
| Синусоидальные | Нет | Хорошая обобщающая способность | Фиксированный паттерн | | Синусоидальные | Нет | Хорошая обобщающая способность | Фиксированный паттерн |
## Оптимальные практики ## Рекомендации
- Для `max_seq_len` берите с запасом (+20%) - Для `max_seq_len` берите с запасом (+20%)
- Размерность делайте равной размерности токенных эмбеддингов - Размерность делайте равной размерности токенных эмбеддингов
- Для длинных последовательностей комбинируйте с синусоидальными - Для длинных последовательностей комбинируйте с синусоидальными
---
## Типовые ошибки и их решения
### Ошибка: IndexError при запросе эмбеддингов
**Возможные причины:**
- seq_len превышает max_seq_len, заданный при инициализации слоя
**Решение:**
- Увеличьте max_seq_len при создании слоя
- Проверяйте длину входных данных заранее
### Ошибка: Размерности не совпадают при сложении с токенными эмбеддингами
**Возможные причины:**
- Размерность позиционных и токенных эмбеддингов не совпадает
**Решение:**
- Убедитесь, что emb_size одинаков для обоих слоев
### Ошибка: Модель не обучается (позиционные эмбеддинги не обновляются)
**Возможные причины:**
- Параметры слоя не добавлены в оптимизатор
**Решение:**
- Проверьте, что слой PositionalEmbeddings включён в модель и его параметры передаются в оптимизатор
---

View File

@@ -1,21 +0,0 @@
<mxfile>
<diagram name="Token Embeddings Flow" id="0">
<mxGraphModel>
<root>
<mxCell id="1"/>
<mxCell id="2" parent="1"/>
<mxCell id="3" value="Входные токены (индексы)" style="shape=rectangle" parent="2" vertex="1">
<mxGeometry x="100" y="100" width="120" height="60"/>
</mxCell>
<mxCell id="4" value="Lookup в таблице эмбеддингов" style="shape=rectangle" parent="2" vertex="1">
<mxGeometry x="100" y="200" width="120" height="60"/>
</mxCell>
<mxCell id="5" value="Выходные эмбеддинги" style="shape=rectangle" parent="2" vertex="1">
<mxGeometry x="100" y="300" width="120" height="60"/>
</mxCell>
<mxCell id="6" source="3" target="4" parent="2" edge="1"/>
<mxCell id="7" source="4" target="5" parent="2" edge="1"/>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@@ -1,5 +1,24 @@
# TokenEmbeddings - Векторные представления токенов # TokenEmbeddings - Векторные представления токенов
> **Документ актуален для Simple-LLM v1.0 (июль 2025)**
---
**Краткое summary:**
Документ описывает слой преобразования индексов токенов в плотные векторные представления (эмбеддинги). Включает алгоритм, пример использования, параметры и типовые ошибки.
---
**Структура документа:**
- Назначение
- Алгоритм работы
- Использование
- Параметры
- Особенности
- Типовые ошибки и их решения
---
## Назначение ## Назначение
Модуль `TokenEmbeddings` преобразует дискретные индексы токенов в плотные векторные представления (эмбеддинги). Это фундаментальный компонент большинства нейросетевых моделей для обработки естественного языка (NLP). Модуль `TokenEmbeddings` преобразует дискретные индексы токенов в плотные векторные представления (эмбеддинги). Это фундаментальный компонент большинства нейросетевых моделей для обработки естественного языка (NLP).
@@ -53,10 +72,38 @@ embeddings = embedding_layer(tokens) # векторные представле
| vocab_size | int | Размер словаря (количество уникальных токенов) | | vocab_size | int | Размер словаря (количество уникальных токенов) |
| emb_size | int | Размерность векторных представлений | | emb_size | int | Размерность векторных представлений |
## Особенности ## Рекомендации
- **Автоматическое обучение**: Векторы адаптируются в процессе тренировки модели - Для больших словарей используйте размерность 256-1024
- **Эффективность**: Быстрое преобразование индексов в векторы - При использовании предобученных эмбеддингов можно заморозить слой (embedding_layer.requires_grad_(False))
- **Гибкость**: Может использоваться как самостоятельный слой или часть более сложной архитектуры - Для обработки неизвестных токенов (OOV) резервируйте нулевой индекс
---
## Типовые ошибки и их решения
### Ошибка: Индекс токена вне диапазона словаря
**Возможные причины:**
- Входные индексы превышают vocab_size
**Решение:**
- Проверьте, что все индексы < vocab_size
- Добавьте обработку [UNK] токенов при необходимости
### Ошибка: Размерности не совпадают при сложении эмбеддингов с другими слоями
**Возможные причины:**
- emb_size не совпадает с размерностью других эмбеддингов
**Решение:**
- Приведите размерности к одному значению во всех слоях
### Ошибка: Эмбеддинги не обучаются
**Возможные причины:**
- Параметры слоя не добавлены в оптимизатор
**Решение:**
- Проверьте, что слой TokenEmbeddings включён в модель и его параметры передаются в оптимизатор
---
## Типичные сценарии использования ## Типичные сценарии использования
1. Первый слой в нейросетевых моделях NLP 1. Первый слой в нейросетевых моделях NLP

View File

@@ -0,0 +1,137 @@
# Обучение токенизатора и модели Simple-LLM на своих данных
> **Инструкция актуальна для Simple-LLM v1.0 (июль 2025)**
---
## Оглавление
- [1. Подготовка корпуса](#1-подготовка-корпуса)
- [2. Обучение BPE-токенизатора](#2-обучение-bpe-токенизатора)
- [3. Токенизация корпуса](#3-токенизация-корпуса)
- [4. Создание датасета](#4-создание-датасета)
- [5. Обучение модели с помощью fit()](#5-обучение-модели-с-помощью-fit)
- [6. Сохранение и генерация](#6-сохранение-и-генерация)
- [7. Советы и FAQ](#7-советы-и-faq)
---
## 1. Подготовка корпуса
- Соберите тексты в один или несколько `.txt` файлов.
- Очистите данные при необходимости.
## 2. Обучение BPE-токенизатора
```python
import torch
# Автоматический выбор устройства
if torch.cuda.is_available():
device = 'cuda'
elif getattr(torch.backends, 'mps', None) and torch.backends.mps.is_available():
device = 'mps' # Apple Silicon
else:
device = 'cpu'
print(f"Используется устройство: {device}")
from simple_llm.tokenizer.bpe import BPE
with open('corpus.txt', 'r', encoding='utf-8') as f:
texts = f.readlines()
tokenizer = BPE(vocab_size=5000)
tokenizer.train(texts, vocab_size=5000, min_freq=2)
tokenizer.save('bpe_tokenizer.json')
```
## 3. Токенизация корпуса
```python
from simple_llm.tokenizer.bpe import BPE
import pickle
tokenizer = BPE.load('bpe_tokenizer.json')
with open('corpus.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
tokenized = [tokenizer.encode(line) for line in lines]
with open('corpus_tokens.pkl', 'wb') as f:
pickle.dump(tokenized, f)
```
## 4. Создание датасета
```python
from simple_llm.data.get_data import GetData
import pickle
with open('corpus_tokens.pkl', 'rb') as f:
tokenized = pickle.load(f)
all_tokens = [token for line in tokenized for token in line]
seq_len = 64
dataset = GetData(data=all_tokens, seq_len=seq_len, device='cuda')
```
## 5. Обучение модели с помощью fit()
```python
from torch.utils.data import DataLoader
from simple_llm.transformer.gpt import GPT
loader = DataLoader(dataset, batch_size=32, shuffle=True)
model = GPT(
vocab_size=tokenizer.vocab_size,
max_seq_len=seq_len,
emb_size=256,
num_heads=4,
head_size=64,
num_layers=4,
device='cuda'
)
# Обучение одной строкой!
model.fit(
train_loader=loader,
valid_loader=None, # можно передать DataLoader для валидации
num_epoch=10,
learning_rate=1e-4
)
print('Train loss:', model.train_loss)
```
## 6. Сохранение и генерация
```python
import torch
# Сохранить веса
torch.save(model.state_dict(), 'simple_llm_gpt.pth')
# Генерация текста после обучения
from simple_llm.tokenizer.bpe import BPE
# Загрузим токенизатор и модель (если нужно)
tokenizer = BPE.load('bpe_tokenizer.json')
# model.load_state_dict(torch.load('simple_llm_gpt.pth')) # если требуется загрузка
model.eval()
# Пример: сгенерировать продолжение для строки prompt
prompt = "Привет, мир! "
input_ids = torch.tensor([tokenizer.encode(prompt)], device=model._device)
output = model.generate(
x=input_ids,
max_new_tokens=30,
do_sample=True,
temperature=1.0
)
# Декодируем результат
result = tokenizer.decode(output[0].tolist())
print("Сгенерированный текст:", result)
```
## 7. Советы и FAQ
- Используйте GPU для ускорения обучения.
- Размер словаря токенизатора должен совпадать с vocab_size модели.
- Для генерации текста используйте метод `generate` и декодируйте результат.
- Для валидации можно передать valid_loader в fit().
- Ошибки по размерностям чаще всего связаны с некорректными параметрами seq_len, batch_size или vocab_size.
---
**Полезные ссылки:**
- [Документация по классу GetData](./get_data_documentation_ru.md)
- [Документация по GPT](./gpt_documentation_ru.md)
- [README.md](../README.md)

50
example/generate_text.py Normal file
View File

@@ -0,0 +1,50 @@
"""
Генерация текста с помощью обученной GPT-модели и токенизатора
"""
import torch
from simple_llm.transformer.gpt import GPT
from simple_llm.tokenizer.bpe import BPE
if __name__ == "__main__":
import torch
# Определяем устройство
#if torch.cuda.is_available():
# device = 'cuda'
#elif getattr(torch.backends, 'mps', None) and torch.backends.mps.is_available():
# device = 'mps' # Apple Silicon
#else:
# device = 'cpu'
device = 'cpu'
print(f"Используется устройство: {device}")
# Загрузим токенизатор и модель
tokenizer = BPE.load('data/tokenizer/bpe_tokenizer.json')
model = GPT(
vocab_size=tokenizer.vocab_size,
max_seq_len=64,
emb_size=256,
num_heads=4,
head_size=64,
num_layers=4,
device=device
)
model.load_state_dict(torch.load('data/model/simple_llm_gpt.pth', map_location=device))
model.eval()
# Введите начальный текст
prompt = "Привет, мир! "
prompt_tokens = tokenizer.encode(prompt)
print(f"Токены prompt: {prompt_tokens}")
print(f"Размер словаря токенизатора: {tokenizer.vocab_size}")
if any(idx >= tokenizer.vocab_size or idx < 0 for idx in prompt_tokens):
print("ВНИМАНИЕ: В prompt есть токены с индексом вне диапазона словаря! Генерация невозможна.")
exit(1)
input_ids = torch.tensor([prompt_tokens], device=device)
output = model.generate(
x=input_ids,
max_new_tokens=30,
do_sample=True,
temperature=1.0
)
result = tokenizer.decode(output[0].tolist())
print("Сгенерированный текст:", result)

View File

@@ -0,0 +1,25 @@
"""
Токенизация текстового корпуса с помощью обученного BPE-токенизатора
"""
from simple_llm.tokenizer.bpe import BPE
import pickle
if __name__ == "__main__":
import torch
# Определяем устройство
#if torch.cuda.is_available():
# device = 'cuda'
#elif getattr(torch.backends, 'mps', None) and torch.backends.mps.is_available():
# device = 'mps' # Apple Silicon
#else:
# device = 'cpu'
device = 'cpu'
print(f"Используется устройство: {device}")
tokenizer = BPE.load('data/tokenizer/bpe_tokenizer.json')
with open('data/corpus/corpus.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
tokenized = [tokenizer.encode(line) for line in lines]
with open('data/tokens/corpus_tokens.pkl', 'wb') as f:
pickle.dump(tokenized, f)
print("Корпус токенизирован и сохранён в data/corpus_tokens.pkl")

View File

@@ -0,0 +1,50 @@
"""
Обучение GPT-модели на токенизированном корпусе
"""
import pickle
from torch.utils.data import DataLoader
from simple_llm.data.get_data import GetData
from simple_llm.transformer.gpt import GPT
if __name__ == "__main__":
import torch
# Определяем устройство
#if torch.cuda.is_available():
# device = 'cuda'
#elif getattr(torch.backends, 'mps', None) and torch.backends.mps.is_available():
# device = 'mps' # Apple Silicon
#else:
# device = 'cpu'
device = 'cpu'
print(f"Используется устройство: {device}")
with open('data/tokens/corpus_tokens.pkl', 'rb') as f:
tokenized = pickle.load(f)
all_tokens = [token for line in tokenized for token in line]
seq_len = 64
dataset = GetData(data=all_tokens, seq_len=seq_len, device=device)
loader = DataLoader(dataset, batch_size=32, shuffle=True)
# Загрузите токенизатор для определения размера словаря
from simple_llm.tokenizer.bpe import BPE
tokenizer = BPE.load('data/tokenizer/bpe_tokenizer.json')
model = GPT(
vocab_size=tokenizer.vocab_size,
max_seq_len=seq_len,
emb_size=256,
num_heads=4,
head_size=64,
num_layers=4,
device='cpu'
)
model.fit(
train_loader=loader,
valid_loader=None,
num_epoch=10,
learning_rate=1e-4
)
print('Train loss:', model.train_loss)
torch.save(model.state_dict(), 'data/model/simple_llm_gpt.pth')
print("Модель обучена и сохранена в data/model/simple_llm_gpt.pth")

View File

@@ -0,0 +1,23 @@
"""
Обучение BPE-токенизатора на текстовом корпусе
"""
from simple_llm.tokenizer.bpe import BPE
if __name__ == "__main__":
import torch
# Определяем устройство
#if torch.cuda.is_available():
# device = 'cuda'
#elif getattr(torch.backends, 'mps', None) and torch.backends.mps.is_available():
# device = 'mps' # Apple Silicon
#else:
# device = 'cpu'
device = 'cpu'
print(f"Используется устройство: {device}")
with open('data/corpus/corpus.txt', 'r', encoding='utf-8') as f:
texts = f.readlines()
tokenizer = BPE(vocab_size=5000)
tokenizer.fit(" ".join(texts))
tokenizer.save('data/tokenizer/bpe_tokenizer.json')
print("Токенизатор обучен и сохранён в data/tokenizer/bpe_tokenizer.json")