import torch import torch.nn as nn import numpy as np import random import os import io import http.server import socketserver from PIL import Image, ImageDraw, ImageFont import json # ============================================================ # 1. НЕЙРОСЕТЬ # ============================================================ class AndreyNN(nn.Module): def __init__(self, vocab_size): super().__init__() self.fc1 = nn.Linear(vocab_size, 128) self.fc2 = nn.Linear(128, 128) self.fc3 = nn.Linear(128, 64) self.fc4 = nn.Linear(64, 32) self.fc5 = nn.Linear(32, vocab_size) self.relu = nn.ReLU() self.dropout = nn.Dropout(0.2) self.softmax = nn.Softmax(dim=1) def forward(self, x): x = self.relu(self.fc1(x)) x = self.dropout(x) x = self.relu(self.fc2(x)) x = self.dropout(x) x = self.relu(self.fc3(x)) x = self.dropout(x) x = self.relu(self.fc4(x)) x = self.softmax(self.fc5(x)) return x # ============================================================ # 2. ЗАГРУЗЧИК # ============================================================ class AndreyWorldLoader: def __init__(self, model_path='andrey_world_model.pt', device='cpu'): self.device = torch.device(device) if not os.path.exists(model_path): raise FileNotFoundError(f"Файл {model_path} не найден!") checkpoint = torch.load(model_path, map_location='cpu') self.vocab = checkpoint['vocab'] self.word_to_idx = checkpoint['word_to_idx'] self.idx_to_word = checkpoint['idx_to_word'] self.vocab_size = checkpoint['vocab_size'] self.is_trained = checkpoint['is_trained'] self.model = AndreyNN(self.vocab_size).to(self.device) self.model.load_state_dict(checkpoint['model_state']) self.model.eval() self.themes = ['свет', 'тьма', 'вода', 'огонь', 'ветер', 'земля'] self.colors = ['золотой', 'синий', 'зелёный', 'розовый', 'фиолетовый', 'голубой'] self.creatures = ['существа', 'птицы', 'змеи', 'великаны', 'духи', 'кони'] self.places = ['долина', 'гора', 'лес', 'пустыня', 'океан', 'небо'] print(f"[ГОТОВО] Модель загружена! Словарь: {self.vocab_size} слов") def generate_word(self, context=None): x = np.zeros(self.vocab_size) if context: for word in context: if word in self.word_to_idx: x[self.word_to_idx[word]] = 1 if np.sum(x) == 0: x[np.random.randint(0, self.vocab_size)] = 1 x_tensor = torch.tensor(x, dtype=torch.float32).to(self.device).unsqueeze(0) with torch.no_grad(): output = self.model(x_tensor) probs = output.cpu().numpy()[0] probs = probs / np.sum(probs) idx = np.random.choice(self.vocab_size, p=probs) return self.idx_to_word[idx] def generate_world(self): theme = self.generate_word(['мир', 'из']) color = self.generate_word(['цвет', 'как']) creature = self.generate_word(['существо', 'живёт']) place = self.generate_word(['место', 'где']) if theme not in self.themes: theme = random.choice(self.themes) if color not in self.colors: color = random.choice(self.colors) if creature not in self.creatures: creature = random.choice(self.creatures) if place not in self.places: place = random.choice(self.places) prefixes = ["Великий", "Тихий", "Золотой", "Древний", "Светлый", "Тёмный"] name = f"{random.choice(prefixes)} {place.capitalize()}" desc_parts = [ f"Мир, где всё состоит из {theme}.", f"Здесь {creature} охраняют {place}.", f"{color.capitalize()} {place} наполнен {theme}.", f"{creature} танцуют в {place}." ] description = ' '.join(random.sample(desc_parts, 2)) return { 'name': name, 'description': description, 'theme': theme, 'color': color, 'creature': creature, 'place': place } # ============================================================ # 3. ГЕНЕРАЦИЯ КАРТИНКИ МИРА # ============================================================ def generate_world_image(world_data, size=(640, 480)): img = Image.new('RGB', size, color=(20, 20, 40)) draw = ImageDraw.Draw(img) colors = { 'свет': (255, 240, 200), 'тьма': (30, 30, 60), 'вода': (0, 100, 200), 'огонь': (255, 100, 50), 'ветер': (180, 200, 220), 'земля': (120, 80, 40) } base_color = colors.get(world_data.get('theme', 'свет'), (50, 50, 80)) for y in range(size[1]): r = int(base_color[0] * (0.5 + 0.5 * y / size[1])) g = int(base_color[1] * (0.5 + 0.5 * y / size[1])) b = int(base_color[2] * (0.5 + 0.5 * y / size[1])) draw.line([(0, y), (size[0], y)], fill=(r, g, b)) ground_y = int(size[1] * 0.6) draw.rectangle([(0, ground_y), (size[0], size[1])], fill=(60, 40, 20)) for _ in range(30): x = random.randint(0, size[0]) y = random.randint(ground_y, size[1]) h = random.randint(5, 15) draw.line([(x, y), (x + random.randint(-3, 3), y - h)], fill=(50, 150, 50), width=1) for _ in range(random.randint(3, 5)): cx = random.randint(100, size[0] - 100) cy = ground_y - random.randint(30, 100) r = random.randint(60, 150) draw.ellipse([(cx - r, cy - r), (cx + r, cy + r)], fill=(100, 80, 60)) sx = random.randint(50, 200) sy = random.randint(30, 100) draw.ellipse([(sx - 30, sy - 30), (sx + 30, sy + 30)], fill=(255, 200, 100)) if world_data.get('theme') == 'тьма': for _ in range(50): sx2 = random.randint(0, size[0]) sy2 = random.randint(0, ground_y) br = random.randint(1, 3) draw.ellipse([(sx2 - br, sy2 - br), (sx2 + br, sy2 + br)], fill=(255, 255, 200)) for _ in range(random.randint(8, 15)): tx = random.randint(0, size[0]) ty = ground_y + random.randint(0, 30) draw.rectangle([(tx - 3, ty - 20), (tx + 3, ty)], fill=(80, 50, 30)) cr = random.randint(15, 30) draw.ellipse([(tx - cr, ty - 20 - cr), (tx + cr, ty - 20 + cr)], fill=(40, 140, 40)) for _ in range(random.randint(3, 6)): ox = random.randint(0, size[0]) oy = random.randint(20, ground_y - 50) ow = random.randint(60, 120) oh = random.randint(20, 40) draw.ellipse([(ox, oy), (ox + ow, oy + oh)], fill=(200, 200, 220, 100)) try: font = ImageFont.load_default() draw.text((20, 20), f"🌍 {world_data.get('name', '')}", fill=(255, 255, 255), font=font) draw.text((20, 50), f"🏷️ {world_data.get('theme', '')} | {world_data.get('color', '')}", fill=(200, 200, 200), font=font) draw.text((20, 80), f"🦄 {world_data.get('description', '')[:50]}...", fill=(180, 180, 180), font=font) except: pass draw.rectangle([(0, 0), (size[0]-1, size[1]-1)], outline=(100, 100, 150), width=2) return img # ============================================================ # 4. HTTP-СЕРВЕР # ============================================================ # Загружаем модель loader = AndreyWorldLoader('andrey_world_model.pt') class WorldHandler(http.server.BaseHTTPRequestHandler): def log_message(self, format, *args): pass def do_GET(self): if self.path == '/': # Генерируем мир world = loader.generate_world() img = generate_world_image(world) # Сохраняем в буфер buffer = io.BytesIO() img.save(buffer, format='PNG') img_data = buffer.getvalue() # Страница html = f'''
{world.get('description', '')}