Документация и примеры: унификация путей, стабильная работа на 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

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")