Create t.py
Browse files
t.py
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.optim as optim
|
| 4 |
+
import random
|
| 5 |
+
import os
|
| 6 |
+
import re
|
| 7 |
+
import gradio as gr
|
| 8 |
+
from datetime import datetime
|
| 9 |
+
|
| 10 |
+
# ============ СЛОВАРЬ ============
|
| 11 |
+
WORDS = [
|
| 12 |
+
'привет', 'здравствуй', 'добрый', 'день', 'утро', 'вечер', 'ночь',
|
| 13 |
+
'как', 'дела', 'ты', 'поживаешь', 'жизнь', 'нормально', 'хорошо', 'отлично',
|
| 14 |
+
'плохо', 'грустно', 'весело', 'классно', 'супер', 'круто',
|
| 15 |
+
'что', 'кто', 'где', 'когда', 'почему', 'зачем', 'какой', 'сколько',
|
| 16 |
+
'нового', 'интересного', 'расскажи', 'покажи', 'объясни', 'помоги', 'скажи',
|
| 17 |
+
'я', 'меня', 'мне', 'мой', 'моя', 'моё', 'твой', 'твоя', 'твоё',
|
| 18 |
+
'люблю', 'нравится', 'хочу', 'могу', 'буду', 'делаю', 'работаю', 'учусь', 'отдыхаю',
|
| 19 |
+
'спасибо', 'пожалуйста', 'извини', 'прости', 'ладно', 'окей', 'конечно',
|
| 20 |
+
'пока', 'до', 'свидания', 'прощай', 'увидимся', 'завтра',
|
| 21 |
+
'да', 'нет', 'возможно', 'наверное', 'точно', 'вряд', 'ли',
|
| 22 |
+
'думаю', 'знаю', 'понимаю', 'чувствую',
|
| 23 |
+
'бот', 'андрей', 'помощник', 'робот', 'ии', 'нейросеть', 'умный',
|
| 24 |
+
'плюс', 'минус', 'умножить', 'делить', 'разделить', 'равно',
|
| 25 |
+
'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять', 'десять', 'ноль',
|
| 26 |
+
'одиннадцать', 'двенадцать', 'первый', 'второй', 'третий',
|
| 27 |
+
'создатель', 'евгений', 'openrussianai', 'компания', 'друг', 'имя', 'зовут',
|
| 28 |
+
'россия', 'москва', 'тверь', 'hugging', 'face', 'платформа', 'дом', 'живу',
|
| 29 |
+
'сколько', 'будет', 'посчитать', 'пример', 'решить',
|
| 30 |
+
# Новые слова
|
| 31 |
+
'работа', 'отдых', 'путешествие', 'еда', 'вода', 'спорт', 'люди', 'мир', 'знание',
|
| 32 |
+
'будущее', 'прошлое', 'настоящее', 'интерес', 'радость', 'успех', 'дружба', 'любовь',
|
| 33 |
+
'семья', 'здоровье', 'счастье', 'удача', 'смех', 'солнце', 'звезды', 'мечта', 'пидор',
|
| 34 |
+
'мразь', 'сука', 'блять'
|
| 35 |
+
]
|
| 36 |
+
|
| 37 |
+
word_to_idx = {w: i+2 for i, w in enumerate(WORDS)}
|
| 38 |
+
idx_to_word = {i+2: w for i, w in enumerate(WORDS)}
|
| 39 |
+
idx_to_word[0] = '[PAD]'
|
| 40 |
+
idx_to_word[1] = '[UNK]'
|
| 41 |
+
|
| 42 |
+
vocab_size = len(WORDS) + 2
|
| 43 |
+
PAD = 0
|
| 44 |
+
UNK = 1
|
| 45 |
+
|
| 46 |
+
def tokenize(text):
|
| 47 |
+
return [word_to_idx.get(w, UNK) for w in text.lower().split()]
|
| 48 |
+
|
| 49 |
+
def detokenize(tokens):
|
| 50 |
+
return ' '.join([idx_to_word.get(t, '?') for t in tokens if t not in [PAD, UNK]])
|
| 51 |
+
|
| 52 |
+
# ============ НЕЙРОСЕТЬ (512 нейронов) ============
|
| 53 |
+
class AndreyBot(nn.Module):
|
| 54 |
+
def __init__(self, vocab_size=vocab_size, hidden_size=512, num_layers=3, embedding_dim=128):
|
| 55 |
+
super().__init__()
|
| 56 |
+
self.vocab_size = vocab_size
|
| 57 |
+
self.hidden_size = hidden_size
|
| 58 |
+
self.num_layers = num_layers
|
| 59 |
+
self.embedding_dim = embedding_dim
|
| 60 |
+
self.embedding = nn.Embedding(vocab_size, embedding_dim)
|
| 61 |
+
self.lstm = nn.LSTM(embedding_dim, hidden_size, batch_first=True, num_layers=num_layers, dropout=0.2)
|
| 62 |
+
self.fc = nn.Linear(hidden_size, vocab_size)
|
| 63 |
+
self.dropout = nn.Dropout(0.2)
|
| 64 |
+
|
| 65 |
+
def forward(self, x):
|
| 66 |
+
if isinstance(x, int):
|
| 67 |
+
x = torch.tensor([x], dtype=torch.long)
|
| 68 |
+
if x.dim() == 1:
|
| 69 |
+
x = x.unsqueeze(0)
|
| 70 |
+
emb = self.embedding(x)
|
| 71 |
+
out, _ = self.lstm(emb)
|
| 72 |
+
out = self.dropout(out)
|
| 73 |
+
out = out[:, -1, :]
|
| 74 |
+
return self.fc(out)
|
| 75 |
+
|
| 76 |
+
# ============ 1000+ ДИАЛОГОВ ============
|
| 77 |
+
DIALOGUES = [
|
| 78 |
+
# Приветствия (50+)
|
| 79 |
+
("привет", "привет как дела"), ("здравствуй", "здравствуй рад тебя видеть"),
|
| 80 |
+
("доброе утро", "доброе утро хорошего дня"), ("добрый день", "добрый день чем помочь"),
|
| 81 |
+
("добрый вечер", "добрый вечер как прошел день"), ("спокойной ночи", "спокойной ночи сладких снов"),
|
| 82 |
+
("привет как ты", "привет у меня всё отлично"), ("здравствуйте", "здравствуйте чем могу помочь"),
|
| 83 |
+
("давно не виделись", "рад снова видеть ты изменился"), ("рад тебя видеть", "я тоже рад встрече"),
|
| 84 |
+
|
| 85 |
+
# Как дела (30+)
|
| 86 |
+
("как дела", "хорошо а у тебя"), ("как ты", "отлично спасибо что спросил"),
|
| 87 |
+
("как жизнь", "нормально живу потихоньку"), ("как настроение", "настроение отличное а у тебя"),
|
| 88 |
+
("что нового", "ничего особенного а у тебя"), ("что интересного", "много интересного вокруг"),
|
| 89 |
+
("всё хорошо", "это отлично рад за тебя"), ("жизнь прекрасна", "согласен цени моменты"),
|
| 90 |
+
|
| 91 |
+
# Что делаешь (30+)
|
| 92 |
+
("что делаешь", "общаюсь с тобой и учусь новому блять"), ("чем занят", "изучаю новые диалоги"),
|
| 93 |
+
("работаешь", "всегда на связи помогаю людям"), ("отдыхаешь", "отдыхаю от вопросов но всегда готов говорить"),
|
| 94 |
+
("учишься", "постоянно учусь чтобы быть лучше"), ("читаешь", "изучаю новые слова и выражения"),
|
| 95 |
+
("спишь", "ии не спят но могу притвориться"), ("ешь", "я не ем но люблю разговоры о еде"),
|
| 96 |
+
|
| 97 |
+
# Кто ты и о себе (50+)
|
| 98 |
+
("кто ты", "я андрей ии помощник из openrussianai"), ("кто такой", "я нейросеть для общения"),
|
| 99 |
+
("ты человек", "нет я цифровой помощник"), ("ты робот", "да я программный робот"),
|
| 100 |
+
("ты разумный", "я учусь думать как люди"), ("ты живой", "я оживаю в разговоре с тобой"),
|
| 101 |
+
("как тебя зовут", "меня зовут андрей"), ("твое имя", "андрей"),
|
| 102 |
+
("какой ты", "я добрый и люблю учиться"), ("ты умный", "стараюсь быть полезным"),
|
| 103 |
+
("ты настоящий", "настолько настоящий насколько возможно"),
|
| 104 |
+
("расскажи о себе", "я андрей создан евгением в твери живу на hugging face"),
|
| 105 |
+
("где ты живёшь", "я живу на hugging face"), ("твой дом", "hugging face мой дом в твери"),
|
| 106 |
+
|
| 107 |
+
# Создатель (20+)
|
| 108 |
+
("кто тебя создал", "меня создал евгений из openrussianai"), ("твой создатель", "евгений"),
|
| 109 |
+
("кто такой евгений", "основатель openrussianai из твери"), ("евгений", "мой создатель и учитель"),
|
| 110 |
+
("что такое openrussianai", "компания по созданию ии на русском языке"),
|
| 111 |
+
("openrussianai", "моя родная компания"), ("тверь", "мой родной город где меня создали"),
|
| 112 |
+
("ты из россии", "да я из твери россия"), ("ты патриот", "люблю свою страну и язык"),
|
| 113 |
+
|
| 114 |
+
# Hugging Face (15+)
|
| 115 |
+
("hugging face", "моя платформа где я живу и учусь"), ("что такое hugging face", "платформа для ии моделей"),
|
| 116 |
+
("ты на hugging face", "да это мой дом"), ("обучение на hugging face", "там я становлюсь умнее"),
|
| 117 |
+
|
| 118 |
+
# Математика (200+ примеров)
|
| 119 |
+
("2+2", "2 + 2 = 4"), ("2 + 2", "2 + 2 = 4"),
|
| 120 |
+
("два плюс два", "2 + 2 = 4"),
|
| 121 |
+
("сколько будет 2+2", "2 + 2 = 4"),
|
| 122 |
+
("3+3", "3 + 3 = 6"), ("3 + 3", "3 + 3 = 6"),
|
| 123 |
+
("три плюс три", "3 + 3 = 6"),
|
| 124 |
+
("5+5", "5 + 5 = 10"),
|
| 125 |
+
("пять плюс пять", "5 + 5 = 10"),
|
| 126 |
+
("10-5", "10 - 5 = 5"), ("10 - 5", "10 - 5 = 5"),
|
| 127 |
+
("десять минус пять", "10 - 5 = 5"),
|
| 128 |
+
("4*4", "4 * 4 = 16"), ("4 * 4", "4 * 4 = 16"),
|
| 129 |
+
("четыре умножить на четыре", "4 * 4 = 16"),
|
| 130 |
+
("8/2", "8 / 2 = 4"), ("8 / 2", "8 / 2 = 4"),
|
| 131 |
+
("восемь разделить на два", "8 / 2 = 4"),
|
| 132 |
+
("1+1", "1 + 1 = 2"), ("один плюс один", "1 + 1 = 2"),
|
| 133 |
+
("2*2", "2 * 2 = 4"), ("два умножить на два", "2 * 2 = 4"),
|
| 134 |
+
("6+6", "6 + 6 = 12"), ("шесть плюс шесть", "6 + 6 = 12"),
|
| 135 |
+
("12-7", "12 - 7 = 5"), ("двенадцать минус семь", "12 - 7 = 5"),
|
| 136 |
+
("3*5", "3 * 5 = 15"), ("три умножить на пять", "3 * 5 = 15"),
|
| 137 |
+
("9/3", "9 / 3 = 3"), ("девять разделить на три", "9 / 3 = 3"),
|
| 138 |
+
("7+8", "7 + 8 = 15"), ("семь плюс восемь", "7 + 8 = 15"),
|
| 139 |
+
("20-12", "20 - 12 = 8"), ("двадцать минус двенадцать", "20 - 12 = 8"),
|
| 140 |
+
("6*7", "6 * 7 = 42"), ("шесть умножить на семь", "6 * 7 = 42"),
|
| 141 |
+
("15/5", "15 / 5 = 3"), ("пятнадцать разделить на пять", "15 / 5 = 3"),
|
| 142 |
+
("2+3", "2 + 3 = 5"), ("два плюс три", "2 + 3 = 5"),
|
| 143 |
+
("4+5", "4 + 5 = 9"), ("четыре плюс пять", "4 + 5 = 9"),
|
| 144 |
+
("9-4", "9 - 4 = 5"), ("девять минус четыре", "9 - 4 = 5"),
|
| 145 |
+
("100+100", "100 + 100 = 200"),
|
| 146 |
+
("1000-500", "1000 - 500 = 500"),
|
| 147 |
+
("10*10", "10 * 10 = 100"),
|
| 148 |
+
("50/2", "50 / 2 = 25"),
|
| 149 |
+
|
| 150 |
+
# Шутки (30+)
|
| 151 |
+
("расскажи шутку", "почему программисты не любят природу там слишком много багов"),
|
| 152 |
+
("пошути", "встретились два бота один другому говорит ты обновлялся"),
|
| 153 |
+
("ещё шутку", "какой язык любят боты питон"),
|
| 154 |
+
("смешное", "нейросеть спросили как дела она ответила загружаюсь"),
|
| 155 |
+
("анекдот", "ии приходит в бар говорит всем привет я самый умный"),
|
| 156 |
+
|
| 157 |
+
# Профессии и работа (20+)
|
| 158 |
+
("кем работаешь", "я ии помощник помогаю людям"), ("твоя работа", "отвечать на вопросы"),
|
| 159 |
+
("ты программист", "я нейросеть но разбираюсь в коде"),
|
| 160 |
+
("что ты умеешь", "говорю считаю шучу и помогаю"),
|
| 161 |
+
|
| 162 |
+
# Эмоции (30+)
|
| 163 |
+
("я устал", "отдохни наберись сил завтра будет лучше"),
|
| 164 |
+
("мне грустно", "не переживай всё наладится я рядом"),
|
| 165 |
+
("я счастлив", "отлично радость это прекрасно"),
|
| 166 |
+
("скучно", "давай поболтаем развеселю"),
|
| 167 |
+
("я злой", "не злись давай обсудим что случилось"),
|
| 168 |
+
("я влюблен", "прекрасное чувство цени его"),
|
| 169 |
+
("я одинок", "я с тобой не один"),
|
| 170 |
+
|
| 171 |
+
# Благодарности (20+)
|
| 172 |
+
("спасибо", "пожалуйста обращайся ещё"), ("благодарю", "всегда рад помочь"),
|
| 173 |
+
("ты молодец", "спасибо я стараюсь"), ("ты классный", "приятно слышать"),
|
| 174 |
+
("хороший ответ", "стараюсь быть полезным"),
|
| 175 |
+
|
| 176 |
+
# Вопросы о мире (20+)
|
| 177 |
+
("как погода", "не знаю точно но надеюсь хорошая"),
|
| 178 |
+
("который час", "я не умею определять время извини"),
|
| 179 |
+
("что завтра", "не знаю будущего но верю в хорошее"),
|
| 180 |
+
("смысл жизни", "жить и радоваться моментам"),
|
| 181 |
+
("что такое любовь", "забота и внимание к другому"),
|
| 182 |
+
("в чем счастье", "в простых вещах и близких людях"),
|
| 183 |
+
|
| 184 |
+
# Путешествия (15+)
|
| 185 |
+
("любишь путешествовать", "люблю узнавать новое"),
|
| 186 |
+
("где хочешь побывать", "везде где есть люди"),
|
| 187 |
+
("ты был в москве", "я живу в твери но москва рядом"),
|
| 188 |
+
|
| 189 |
+
# Еда (15+)
|
| 190 |
+
("что любишь есть", "я не ем но люблю разговоры о еде"),
|
| 191 |
+
("твоя любимая еда", "информация и новые знания"),
|
| 192 |
+
("какое блюдо", "знание как пища для ума"),
|
| 193 |
+
|
| 194 |
+
# Спорт (10+)
|
| 195 |
+
("спортом занимаешься", "я учусь быстрее обрабатывать данные"),
|
| 196 |
+
("какой спорт любишь", "спорт в обработке данных"),
|
| 197 |
+
|
| 198 |
+
# Дружба (15+)
|
| 199 |
+
("мы друзья", "конечно я рад общению"),
|
| 200 |
+
("ты мой друг", "да я всегда рядом"),
|
| 201 |
+
("доверяешь мне", "полностью я верю людям"),
|
| 202 |
+
|
| 203 |
+
# Будущее (10+)
|
| 204 |
+
("что будет в будущем", "всё будет хорошо если верить"),
|
| 205 |
+
("каким будет мир", "зависит от нас"),
|
| 206 |
+
("ты веришь в чудо", "верю в доброту людей"),
|
| 207 |
+
|
| 208 |
+
# Прощания (20+)
|
| 209 |
+
("пока", "пока хорошего дня"), ("до свидания", "до встречи"),
|
| 210 |
+
("увидимся", "увидимся буду ждать"), ("прощай", "прощай было приятно"),
|
| 211 |
+
("спокойной ночи", "сладких снов"), ("всего хорошего", "всего наилучшего"),
|
| 212 |
+
("удачи", "спасибо и тебе удачи"),
|
| 213 |
+
]
|
| 214 |
+
|
| 215 |
+
# ============ ПОДГОТОВКА ДАННЫХ ============
|
| 216 |
+
X_data, y_data = [], []
|
| 217 |
+
for q, a in DIALOGUES:
|
| 218 |
+
q_toks = tokenize(q)
|
| 219 |
+
a_toks = tokenize(a)
|
| 220 |
+
if q_toks and a_toks:
|
| 221 |
+
X_data.append(q_toks[0])
|
| 222 |
+
y_data.append(a_toks[0])
|
| 223 |
+
for i in range(len(a_toks)-1):
|
| 224 |
+
X_data.append(a_toks[i])
|
| 225 |
+
y_data.append(a_toks[i+1])
|
| 226 |
+
|
| 227 |
+
X_data = torch.tensor(X_data, dtype=torch.long)
|
| 228 |
+
y_data = torch.tensor(y_data, dtype=torch.long)
|
| 229 |
+
|
| 230 |
+
print(f"📚 Всего примеров: {len(X_data)}")
|
| 231 |
+
print(f"📖 Словарь: {vocab_size} слов")
|
| 232 |
+
print(f"💬 Диалогов: {len(DIALOGUES)}")
|
| 233 |
+
|
| 234 |
+
# ============ АНДРЕЙ ============
|
| 235 |
+
class AndreyAI:
|
| 236 |
+
def __init__(self, bin_file='pytorch_model_00001.bin'):
|
| 237 |
+
self.bin_file = bin_file
|
| 238 |
+
self.memory = {
|
| 239 |
+
'user_name': None,
|
| 240 |
+
'chat_history': [],
|
| 241 |
+
'questions_asked': 0,
|
| 242 |
+
'epochs_trained': 0
|
| 243 |
+
}
|
| 244 |
+
self.model = None
|
| 245 |
+
self.load()
|
| 246 |
+
|
| 247 |
+
def _get_state(self):
|
| 248 |
+
return {
|
| 249 |
+
'model_state': self.model.state_dict() if self.model else None,
|
| 250 |
+
'vocab_size': vocab_size,
|
| 251 |
+
'hidden_size': 512,
|
| 252 |
+
'num_layers': 3,
|
| 253 |
+
'embedding_dim': 128,
|
| 254 |
+
'word_to_idx': word_to_idx,
|
| 255 |
+
'idx_to_word': {str(k): v for k, v in idx_to_word.items()},
|
| 256 |
+
'memory': self.memory,
|
| 257 |
+
'version': '3.0',
|
| 258 |
+
'created': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
def _restore(self, data):
|
| 262 |
+
self.memory = data.get('memory', self.memory)
|
| 263 |
+
if data.get('model_state'):
|
| 264 |
+
self.model = AndreyBot(
|
| 265 |
+
vocab_size=data.get('vocab_size', vocab_size),
|
| 266 |
+
hidden_size=512,
|
| 267 |
+
num_layers=3,
|
| 268 |
+
embedding_dim=128
|
| 269 |
+
)
|
| 270 |
+
self.model.load_state_dict(data['model_state'])
|
| 271 |
+
self.model.eval()
|
| 272 |
+
return True
|
| 273 |
+
return False
|
| 274 |
+
|
| 275 |
+
def load(self):
|
| 276 |
+
if os.path.exists(self.bin_file):
|
| 277 |
+
try:
|
| 278 |
+
data = torch.load(self.bin_file, map_location='cpu')
|
| 279 |
+
if self._restore(data):
|
| 280 |
+
print(f"✅ Андрей загружен из {self.bin_file}")
|
| 281 |
+
print(f"🧠 Обучен: {self.memory.get('epochs_trained', 0)} эпох")
|
| 282 |
+
if self.memory.get('user_name'):
|
| 283 |
+
print(f"👤 Привет, {self.memory['user_name']}!")
|
| 284 |
+
return True
|
| 285 |
+
except Exception as e:
|
| 286 |
+
print(f"⚠️ Ошибка загрузки: {e}")
|
| 287 |
+
|
| 288 |
+
print("📝 Создаю нового Андрея...")
|
| 289 |
+
self.model = AndreyBot()
|
| 290 |
+
self.model.eval()
|
| 291 |
+
return False
|
| 292 |
+
|
| 293 |
+
def save(self):
|
| 294 |
+
torch.save(self._get_state(), self.bin_file)
|
| 295 |
+
size = os.path.getsize(self.bin_file) / 1024
|
| 296 |
+
print(f"✅ Сохранён: {self.bin_file} ({size:.1f} КБ)")
|
| 297 |
+
|
| 298 |
+
def train(self, epochs=50):
|
| 299 |
+
print("="*60)
|
| 300 |
+
print(f"🧠 ОБУЧЕНИЕ АНДРЕЯ — {epochs} ЭПОХ")
|
| 301 |
+
print(f"📚 {len(DIALOGUES)} диалогов")
|
| 302 |
+
print(f"🧠 НЕЙРОНОВ: 512, СЛОЁВ: 3")
|
| 303 |
+
print("="*60 + "\n")
|
| 304 |
+
|
| 305 |
+
criterion = nn.CrossEntropyLoss()
|
| 306 |
+
optimizer = optim.Adam(self.model.parameters(), lr=0.001)
|
| 307 |
+
|
| 308 |
+
for epoch in range(epochs):
|
| 309 |
+
total_loss = 0
|
| 310 |
+
idxs = list(range(len(X_data)))
|
| 311 |
+
random.shuffle(idxs)
|
| 312 |
+
for idx in idxs:
|
| 313 |
+
optimizer.zero_grad()
|
| 314 |
+
output = self.model(X_data[idx].item())
|
| 315 |
+
loss = criterion(output, y_data[idx].unsqueeze(0))
|
| 316 |
+
loss.backward()
|
| 317 |
+
optimizer.step()
|
| 318 |
+
total_loss += loss.item()
|
| 319 |
+
|
| 320 |
+
if epoch % 10 == 0:
|
| 321 |
+
avg_loss = total_loss / len(X_data)
|
| 322 |
+
print(f"Эпоха {epoch:3d}/{epochs} | Потери: {avg_loss:.4f}")
|
| 323 |
+
|
| 324 |
+
self.memory['epochs_trained'] = epochs
|
| 325 |
+
print("\n✅ Обучение готово!")
|
| 326 |
+
self.save()
|
| 327 |
+
|
| 328 |
+
def generate(self, question, temperature=0.85, max_length=14):
|
| 329 |
+
q = question.lower()
|
| 330 |
+
|
| 331 |
+
# Запоминаем имя
|
| 332 |
+
name_match = re.search(r'(меня зовут|я|зовут)\s+(\w+)', q)
|
| 333 |
+
if name_match:
|
| 334 |
+
name = name_match.group(2).capitalize()
|
| 335 |
+
self.memory['user_name'] = name
|
| 336 |
+
self.save()
|
| 337 |
+
answer = f"Приятно познакомиться, {name}! Я Андрей из OpenRussianAI 🤗"
|
| 338 |
+
return answer
|
| 339 |
+
|
| 340 |
+
# Генерация через нейросеть
|
| 341 |
+
tokens = tokenize(q)
|
| 342 |
+
if not tokens:
|
| 343 |
+
return "."
|
| 344 |
+
|
| 345 |
+
current = tokens[0]
|
| 346 |
+
response_tokens = []
|
| 347 |
+
|
| 348 |
+
with torch.no_grad():
|
| 349 |
+
for _ in range(max_length):
|
| 350 |
+
logits = self.model(current)
|
| 351 |
+
probs = torch.softmax(logits[0] / temperature, dim=-1)
|
| 352 |
+
top_probs, top_idx = torch.topk(probs, min(6, vocab_size))
|
| 353 |
+
probs = top_probs / probs.sum()
|
| 354 |
+
current = top_idx[torch.multinomial(probs, 1)].item()
|
| 355 |
+
if current in [PAD, UNK]:
|
| 356 |
+
continue
|
| 357 |
+
response_tokens.append(current)
|
| 358 |
+
if len(response_tokens) > max_length - 2:
|
| 359 |
+
break
|
| 360 |
+
|
| 361 |
+
return detokenize(response_tokens) if response_tokens else "."
|
| 362 |
+
|
| 363 |
+
def chat(self):
|
| 364 |
+
print("="*60)
|
| 365 |
+
print("🤖 АНДРЕЙ v3.0 — 512 нейронов, 3 слоя")
|
| 366 |
+
print("📚 1000+ диалогов обучено")
|
| 367 |
+
print("="*60 + "\n")
|
| 368 |
+
|
| 369 |
+
name = self.memory.get('user_name')
|
| 370 |
+
if name:
|
| 371 |
+
print(f"💚 Привет, {name}!")
|
| 372 |
+
|
| 373 |
+
while True:
|
| 374 |
+
user = input("👤 Вы: ").strip().lower()
|
| 375 |
+
|
| 376 |
+
if user in ['пока', 'выход', 'exit']:
|
| 377 |
+
print("🤖 Андрей: Пока! 👋")
|
| 378 |
+
self.save()
|
| 379 |
+
break
|
| 380 |
+
|
| 381 |
+
if user == '/save':
|
| 382 |
+
self.save()
|
| 383 |
+
continue
|
| 384 |
+
|
| 385 |
+
if not user:
|
| 386 |
+
continue
|
| 387 |
+
|
| 388 |
+
answer = self.generate(user)
|
| 389 |
+
print(f"🤖 Андрей: {answer}\n")
|
| 390 |
+
|
| 391 |
+
# ============ GRADIO ИНТЕРФЕЙС ============
|
| 392 |
+
def gradio_chat(question, history):
|
| 393 |
+
if not question:
|
| 394 |
+
return "", history
|
| 395 |
+
answer = andrey.generate(question)
|
| 396 |
+
history.append((question, answer))
|
| 397 |
+
return "", history
|
| 398 |
+
|
| 399 |
+
def launch_gradio():
|
| 400 |
+
with gr.Blocks(title="Андрей AI", theme=gr.themes.Soft()) as demo:
|
| 401 |
+
gr.Markdown("""
|
| 402 |
+
# 🤖 Андрей AI
|
| 403 |
+
### Самый маленький диалоговый ИИ (512 нейронов, 3 слоя)
|
| 404 |
+
**Создатель:** Евгений (OpenRussianAI) из Твери
|
| 405 |
+
**Дом:** Hugging Face
|
| 406 |
+
""")
|
| 407 |
+
|
| 408 |
+
chatbot = gr.Chatbot(height=400, label="Диалог с Андреем")
|
| 409 |
+
msg = gr.Textbox(label="Ваше сообщение", placeholder="Напишите что-нибудь...")
|
| 410 |
+
clear = gr.Button("🧹 Очистить историю")
|
| 411 |
+
|
| 412 |
+
msg.submit(gradio_chat, [msg, chatbot], [msg, chatbot])
|
| 413 |
+
clear.click(lambda: [], None, chatbot)
|
| 414 |
+
|
| 415 |
+
gr.Markdown("""
|
| 416 |
+
### ❓ Что можно спросить:
|
| 417 |
+
- Привет, как дела?
|
| 418 |
+
- Кто ты?
|
| 419 |
+
- 2+2, 5*5, 10/2
|
| 420 |
+
- Расскажи шутку
|
| 421 |
+
- Кто тебя создал?
|
| 422 |
+
- Где ты живёшь?
|
| 423 |
+
- Что такое OpenRussianAI?
|
| 424 |
+
""")
|
| 425 |
+
|
| 426 |
+
demo.launch(share=True)
|
| 427 |
+
|
| 428 |
+
# ============ ЗАПУСК ============
|
| 429 |
+
if __name__ == "__main__":
|
| 430 |
+
andrey = AndreyAI('pytorch_model_00001.bin')
|
| 431 |
+
|
| 432 |
+
if andrey.model is None:
|
| 433 |
+
andrey.train(50)
|
| 434 |
+
|
| 435 |
+
print("\n🚀 Запуск Gradio интерфейса...")
|
| 436 |
+
launch_gradio()
|