import gradio as gr import torch import time from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline print("🚀 ЗАГРУЖАЮ ОПТИМИЗИРОВАННУЮ СИСТЕМУ...") # ================== ИСПОЛЬЗУЕМ ТОЛЬКО TINYLLAMA ================== # Она быстрая, уже работает, занимает мало памяти MODEL_NAME = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" # Глобальные переменные для кэша _tokenizer = None _model = None _translator = None def load_system(): """Загружаем только одну модель - TinyLlama""" global _tokenizer, _model, _translator print("📦 Загружаю TinyLlama (самая быстрая для CPU)...") try: # Токенизатор _tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) _tokenizer.pad_token = _tokenizer.eos_token # Модель с оптимизациями для CPU _model = AutoModelForCausalLM.from_pretrained( MODEL_NAME, torch_dtype=torch.float32, # Используем float32 для CPU device_map="auto", low_cpu_mem_usage=True, offload_folder="./offload" # Выгружаем на диск если не хватает RAM ) print("✅ TinyLlama загружена и оптимизирована для CPU!") # Переводчик print("🌐 Загружаю переводчик...") _translator = pipeline( "translation_ru_to_en", model="Helsinki-NLP/opus-mt-ru-en", device="cpu" ) print("✅ Переводчик готов!") return True except Exception as e: print(f"❌ Ошибка загрузки: {e}") return False # ================== ПРАВИЛЬНЫЕ ПРОМТ-ШАБЛОНЫ ================== def get_enhancement_prompt(user_input: str) -> str: """Создаем ПРАВИЛЬНЫЙ промт для улучшения, а не для рассказа""" return f"""<|system|> Ты помощник для создания промтов к AI-генератору изображений Dreamlike Photoreal 2.0. ТВОЯ ЗАДАЧА: Взять короткое описание и добавить КОНКРЕТНЫЕ детали для фотореалистичной генерации. ДОБАВЬ: 1. Описание внешности (если есть персонаж) 2. Детали окружения 3. Освещение и время суток 4. Атмосферу и настроение 5. Стиль изображения НЕ пиши рассказ, НЕ добавляй сюжет. Только описание для генератора изображений. Примеры правильных улучшений: • "девушка в лесу" → "Молодая девушка с рыжими волосами в белом платье стоит в магическом лесу на закате, золотые лучи солнца пробиваются сквозь листву, атмосферное освещение, фотореалистично, детализированно" • "город ночью" → "Футуристический город ночью с неоновыми вывесками, мокрые улицы отражают свет, киберпанк стиль, детализированная архитектура, фотореалистично" <|user|> Улучши это описание для генерации фотореалистичного изображения: "{user_input}" <|assistant|> Улучшенное описание:""" # ================== БЫСТРАЯ ГЕНЕРАЦИЯ ================== def enhance_prompt_fast(user_input: str) -> str: """Быстро улучшаем промт с TinyLlama""" if _model is None or _tokenizer is None: return user_input + " [система не загружена]" try: # Создаем правильный промт system_prompt = get_enhancement_prompt(user_input) # Токенизация (ограничиваем длину) inputs = _tokenizer( system_prompt, return_tensors="pt", max_length=256, truncation=True, padding=True ) # Быстрая генерация с оптимизированными параметрами with torch.no_grad(): outputs = _model.generate( **inputs, max_new_tokens=120, # Не больше 120 новых токенов temperature=0.8, do_sample=True, top_p=0.9, repetition_penalty=1.1, pad_token_id=_tokenizer.eos_token_id, eos_token_id=_tokenizer.eos_token_id, no_repeat_ngram_size=3 # Избегаем повторений ) # Декодируем response = _tokenizer.decode(outputs[0], skip_special_tokens=True) # Извлекаем только улучшенную часть if "Улучшенное описание:" in response: enhanced = response.split("Улучшенное описание:")[-1].strip() else: # Fallback: удаляем системный промт enhanced = response.replace(system_prompt, "").strip() # Очищаем от метаданных for marker in ["<|endoftext|>", "", "<|assistant|>", "<|user|>", "<|system|>"]: enhanced = enhanced.split(marker)[0].strip() # Если результат слишком короткий, добавляем базовые улучшения if len(enhanced.split()) < 5: enhanced = f"{user_input}, фотореалистично, высокое качество, детализированно, красивое освещение" return enhanced[:400] # Ограничиваем длину except Exception as e: print(f"Ошибка генерации: {e}") return f"{user_input}, фотореалистично, высокое качество, детализированно" def generate_negative_prompt_smart(english_prompt: str) -> str: """Умный негативный промт""" base = [ "blurry", "ugly", "deformed", "bad anatomy", "bad proportions", "extra limbs", "mutated hands", "poorly drawn hands", "text", "watermark", "signature", "worst quality", "low quality", "jpeg artifacts" ] prompt_lower = english_prompt.lower() # Добавляем контекстные исключения if any(word in prompt_lower for word in ["realistic", "photoreal", "photo"]): base.extend(["cartoon", "anime", "painting", "drawing", "illustration", "3d render"]) if any(word in prompt_lower for word in ["bright", "light", "sun"]): base.extend(["dark", "dull", "underexposed", "gloomy"]) if any(word in prompt_lower for word in ["portrait", "face", "person"]): base.extend(["asymmetric eyes", "cloned face", "malformed limbs"]) # Убираем дубликаты unique = [] for term in base: if term not in unique: unique.append(term) return ", ".join(unique) def process_pipeline(user_input: str): """Полный пайплайн обработки""" start_time = time.time() if not user_input.strip(): return "Введите промт", "", "", "⏳ Введите промт" print(f"⚡ Обработка: {user_input}") # 1. Улучшаем промт (максимум 5 секунд) gen_start = time.time() enhanced_ru = enhance_prompt_fast(user_input) gen_time = time.time() - gen_start # 2. Переводим trans_start = time.time() try: if _translator: translated = _translator(enhanced_ru[:300])[0]['translation_text'] else: translated = enhanced_ru except: translated = enhanced_ru trans_time = time.time() - trans_start # 3. Улучшаем английский для Dreamlike dreamlike_keywords = ", photorealistic, high quality, detailed, 8K, professional photography" if "photorealistic" not in translated.lower(): translated += dreamlike_keywords # 4. Негативный промт negative_start = time.time() negative_en = generate_negative_prompt_smart(translated) negative_time = time.time() - negative_start # 5. Статистика total_time = time.time() - start_time info = f""" ⚡ БЫСТРАЯ ОБРАБОТКА: • Генерация: {gen_time:.1f} сек • Перевод: {trans_time:.1f} сек • Негативный промт: {negative_time:.1f} сек • Всего: {total_time:.1f} сек 📊 СТАТИСТИКА: • Модель: TinyLlama-1.1B (оптимизирована для CPU) • Длина промта: {len(translated.split())} слов • Статус: ✅ Готово к использованию в Dreamlike """ return enhanced_ru, translated, negative_en, info.strip() # ================== ПРОСТОЙ ИНТЕРФЕЙС ================== with gr.Blocks(title="AI Улучшитель промтов для Dreamlike", theme=gr.themes.Soft()) as demo: # Заголовок gr.Markdown(""" # 🚀 УЛЬТРА-БЫСТРЫЙ AI УЛУЧШИТЕЛЬ ПРОМТОВ ### Оптимизирован для CPU • TinyLlama • Мгновенная обработка """) # Статус загрузки status = gr.Textbox( label="🔄 Статус системы", value="Загружаю систему...", interactive=False ) # Основной интерфейс with gr.Column(visible=False) as main_ui: # Ввод input_prompt = gr.Textbox( label="🎯 Введите промт на русском", placeholder="Пример: девушка в магическом лесу на закате", lines=2 ) # Кнопка process_btn = gr.Button("⚡ УЛУЧШИТЬ ПРОМТ", variant="primary", size="lg") # Результаты gr.Markdown("### 📝 УЛУЧШЕННЫЙ ПРОМТ (русский)") output_ru = gr.Textbox( label="", lines=3, interactive=True ) gr.Markdown("### 🌐 ДЛЯ DREAMLIKE (английский)") with gr.Row(): output_en = gr.Textbox( label="🎨 Основной промт", lines=3, interactive=True ) output_neg = gr.Textbox( label="🚫 Negative Prompt", lines=3, interactive=True ) # Информация output_info = gr.Textbox( label="📊 СТАТИСТИКА", lines=4, interactive=False ) # Примеры gr.Markdown("### 🧪 БЫСТРЫЕ ПРИМЕРЫ") examples = gr.Examples( examples=[ ["девушка в магическом лесу на закате"], ["киберпанк улица ночью с неоновыми вывесками"], ["космонавт играет на гитаре на луне"], ["кошка в шляпе читает газету в кафе"], ["дракон на вершине горы"] ], inputs=[input_prompt], outputs=[output_ru, output_en, output_neg, output_info], fn=process_pipeline, label="Кликните для теста:" ) # Обработчики def process_and_update(prompt): return process_pipeline(prompt) process_btn.click( fn=process_and_update, inputs=[input_prompt], outputs=[output_ru, output_en, output_neg, output_info] ) input_prompt.submit( fn=process_and_update, inputs=[input_prompt], outputs=[output_ru, output_en, output_neg, output_info] ) # Функция инициализации def initialize_system(): if load_system(): return "✅ СИСТЕМА ГОТОВА! TinyLlama загружена и оптимизирована.\n⚡ Введите промт и нажмите кнопку.", gr.update(visible=True) else: return "❌ Ошибка загрузки. Попробуйте перезапустить Space.", gr.update(visible=False) # Загружаем при старте demo.load( fn=initialize_system, outputs=[status, main_ui] ) # ================== ЗАПУСК ================== if __name__ == "__main__": demo.launch( server_name="0.0.0.0", server_port=7860 )