import threading import time import asyncio import os import json import gradio as gr from PIL import Image from icrawler.builtin import BingImageCrawler from telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters from huggingface_hub import InferenceClient # --- الإعدادات والمتغيرات العالمية --- LOGS = ["🤖 بدء تشغيل نظام التدريب الذكي مع ميزة الذاكرة الدائمة..."] DATASET_DIR = "agent_dataset" MEMORY_FILE = "bot_memory.json" # متغيرات العقل والذاكرة الافتراضية (سيتم تحديثها تلقائياً إذا وجد ملف الحفظ) CURRENT_KEYWORD = "لا يوجد" TRAINING_STEP = 0 MAX_TRAINING_STEPS = 10 IS_TRAINING_COMPLETE = False LEARNED_FEATURES = "ولاشيء بعد" CURRENT_STATUS = "خامل - بانتظار تحديد الستايل وبدء التدريب" if not os.path.exists(DATASET_DIR): os.makedirs(DATASET_DIR) # --- 💾 دالات إدارة الذاكرة الدائمة (حفظ واسترجاع) --- def save_memory_to_space(): """حفظ حالة البوت الحالية داخل ملف JSON في السبيس""" try: memory_data = { "current_keyword": CURRENT_KEYWORD, "training_step": TRAINING_STEP, "is_training_complete": IS_TRAINING_COMPLETE, "learned_features": LEARNED_FEATURES } with open(MEMORY_FILE, "w", encoding="utf-8") as f: json.dump(memory_data, f, ensure_ascii=False, indent=4) except Exception as e: LOGS.append(f"⚠️ فشل حفظ الذاكرة في الملف: {str(e)}") def load_memory_from_space(): """استرجاع حالة البوت وعقله من ملف الـ JSON عند الإقلاع""" global CURRENT_KEYWORD, TRAINING_STEP, IS_TRAINING_COMPLETE, LEARNED_FEATURES, CURRENT_STATUS if os.path.exists(MEMORY_FILE): try: with open(MEMORY_FILE, "r", encoding="utf-8") as f: memory_data = json.load(f) CURRENT_KEYWORD = memory_data.get("current_keyword", "لا يوجد") TRAINING_STEP = memory_data.get("training_step", 0) IS_TRAINING_COMPLETE = memory_data.get("is_training_complete", False) LEARNED_FEATURES = memory_data.get("learned_features", "ولاشيء بعد") if IS_TRAINING_COMPLETE: CURRENT_STATUS = f"✅ مسترجع من الذاكرة: اكتمل التدريب على {CURRENT_KEYWORD}" elif CURRENT_KEYWORD != "لا يوجد": CURRENT_STATUS = f"🔄 مسترجع من الذاكرة: جاهز لمتابعة تدريب {CURRENT_KEYWORD} ({TRAINING_STEP}/{MAX_TRAINING_STEPS})" else: CURRENT_STATUS = "خامل - بانتظار تحديد الستايل وبدء التدريب" LOGS.append(f"🧠 [الذاكرة الدائمة]: تم استرجاع عقلك بنجاح! الستايل المحفوظ هو: ({CURRENT_KEYWORD})") except Exception as e: LOGS.append(f"⚠️ خطأ أثناء قراءة ملف الذاكرة المحفوظة: {str(e)}") else: LOGS.append("ℹ️ لم يتم العثور على ملف ذاكرة سابق، البوت يبدأ الآن بعقل نظيف.") # استدعاء دالة التحميل فوراً عند تشغيل السيرفر لاستعادة البيانات السابقة load_memory_from_space() # استخدام السيرفرات السحابية للرسم السريع (موديل DreamShaper المخصص للأنمي والفن) MODEL_ID = "Lykon/dreamshaper-8" client = InferenceClient(model=MODEL_ID) pause_event = threading.Event() pause_event.set() # --- 🎨 دالة الرسم الذكية (تدمج الستايل المدرب تلقائياً مع طلبك) --- def generate_image_logic(prompt): global CURRENT_STATUS pause_event.clear() # إيقاف مؤقت للتدريب أثناء الرسم لحماية الموارد old_status = CURRENT_STATUS CURRENT_STATUS = "🎨 جاري توليد الصورة بالستايل الخاص بك..." # دمج الستايل الذي تدرب عليه البوت والمخزن بالذاكرة مع وصفك if CURRENT_KEYWORD != "لا يوجد": final_prompt = f"{prompt}, in {CURRENT_KEYWORD} style, highly detailed, perfect masterpiece" else: final_prompt = f"{prompt}, highly detailed, perfect masterpiece" LOGS.append(f"🎨 أمر رسم نشط للوصف المدمج: ({final_prompt})") try: image = client.text_to_image(final_prompt) output_path = "bot_output.png" image.save(output_path) LOGS.append("✅ تم إنتاج الصورة بنجاح بالستايل المطلوب!") return output_path except Exception as e: LOGS.append(f"❌ خطأ بالرسم: {str(e)}") return None finally: CURRENT_STATUS = old_status pause_event.set() # --- 🧠 حلقة التدريب والتحليل التفصيلي للستايل --- def continuous_learning_loop(): global CURRENT_STATUS, TRAINING_STEP, IS_TRAINING_COMPLETE, LEARNED_FEATURES feature_steps = [ "ملامح الوجه وتناسق العينين (Face Anatomy)", "الخطوط الأساسية والـ Outlines ورسم الهياكل", "توزيع الألوان ودرجات الظل والنور (Color Palette)", "المؤثرات البصرية والخلفيات العمق الضوئي", "ستايل ضربات الفرشاة والتكستشر (Textures)", "تعابير الوجه وحركة الجسد الكرتونية", "صقل الإضاءة المحيطية وتأثير النيون (Lighting)", "تفاصيل اليدين والملابس والإكسسوارات", "دمج العناصر الأمامية مع عزل الخلفية", "صقل الصورة النهائي ورفع الدقة الفنية (Final Rendering)" ] while True: pause_event.wait() if IS_TRAINING_COMPLETE or CURRENT_KEYWORD == "لا يوجد": time.sleep(2) continue CURRENT_STATUS = f"🏋️ جاري التدريب المكثف على ستايل: {CURRENT_KEYWORD} (خطوة {TRAINING_STEP + 1}/{MAX_TRAINING_STEPS})" try: # 1. سحب صورة لتحليلها crawler = BingImageCrawler(storage={'root_dir': DATASET_DIR}) crawler.crawl(keyword=CURRENT_KEYWORD, max_num=1, overwrite=False) # 2. استخراج الميزة الحالية التي يتعلمها البوت current_feature = feature_steps[TRAINING_STEP % len(feature_steps)] LEARNED_FEATURES = f"🔄 يتعلم الآن: {current_feature}" LOGS.append(f"🧠 [تدريب]: تم هضم ميزة جديدة -> {current_feature}") TRAINING_STEP += 1 # 3. حفظ التقدم والخطوة الحالية فوراً في ملف الذاكرة لضمان عدم ضياعها save_memory_to_space() # تحقق من الوصول للحد النهائي للتدريب if TRAINING_STEP >= MAX_TRAINING_STEPS: IS_TRAINING_COMPLETE = True CURRENT_STATUS = f"✅ اكتمل التدريب بنجاح 100% على ستايل: {CURRENT_KEYWORD}" LEARNED_FEATURES = "🏆 تم تعلم الستايل بالكامل وحفظه بذاكرة السبيس الدائمة!" LOGS.append(f"🎉 [مبارك]: البوت أصبح خبيراً الآن وتم تجميد الذاكرة بنجاح.") save_memory_to_space() # حفظ نهائي بعد الاكتمال except Exception as e: LOGS.append(f"⚠️ تنبيه بالتدريب: {str(e)}") time.sleep(10) learning_thread = threading.Thread(target=continuous_learning_loop, daemon=True) learning_thread.start() # --- 🕹️ دالة بدء تدريب جديد من واجهة Gradio --- def start_new_training(style_name): global CURRENT_KEYWORD, TRAINING_STEP, IS_TRAINING_COMPLETE, LEARNED_FEATURES, CURRENT_STATUS if not style_name.strip(): return "❌ يرجى كتابة اسم الستايل أولاً", "لا شيء" CURRENT_KEYWORD = style_name TRAINING_STEP = 0 IS_TRAINING_COMPLETE = False LEARNED_FEATURES = "⏳ جاري بدء الدورة الأولى وحفظ حجر الأساس في الذاكرة..." CURRENT_STATUS = f"🏋️ جاري بدء تدريب الستايل: {style_name}" LOGS.append(f"🚀 [إشارة تحكم]: أطلقت تدريباً لستايل جديد: {style_name}") # حفظ الحالة الجديدة فوراً بالملف save_memory_to_space() return CURRENT_STATUS, LEARNED_FEATURES # --- 🤖 إعدادات بوت التليجرام --- async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): await update.message.reply_text( f"مرحباً بك في بوت الرسم الذكي ذو الذاكرة الدائمة! 🧠💾\n\n" f"• الستايل المسترجع حالياً: **{CURRENT_KEYWORD}**\n" f"• حالة التدريب: {CURRENT_STATUS}\n\n" f"اكتب لي أي وصف بالإنجليزية، وسأرسمه لك مدموجاً بالستايل المحفوظ فوراً!" ) async def draw_command(update: Update, context: ContextTypes.DEFAULT_TYPE): prompt = update.message.text await update.message.reply_text("🎨 أمرك مطاع! تم تجميد التدريب مؤقتاً.. جاري الرسم واستدعاء الذاكرة الحالية...") image_path = generate_image_logic(prompt) if image_path and os.path.exists(image_path): await context.bot.send_photo(chat_id=update.effective_chat.id, photo=open(image_path, 'rb')) await update.message.reply_text("✅ تفضل النتيجة! تم استئناف وضع التدريب/الحفظ تلقائياً.") else: await update.message.reply_text("❌ واجهت السيرفرات ضغطاً، يرجى إعادة المحاولة.") def run_telegram_bot(): token = os.getenv("TELEGRAM_TOKEN") if not token: return application = ApplicationBuilder().token(token).build() application.add_handler(CommandHandler('start', start)) application.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), draw_command)) application.run_polling(stop_signals=None) telegram_thread = threading.Thread(target=lambda: asyncio.run(run_telegram_bot()), daemon=True) telegram_thread.start() # --- 🖥️ واجهة التحكم الرسومية (Gradio) --- def get_ui_updates(): return CURRENT_STATUS, LEARNED_FEATURES, "\n".join(LOGS[-12:]) with gr.Blocks() as demo: gr.Markdown("# 🚀 مركز الإدارة والتدريب الذكي لـ Catbot (نسخة الذاكرة الدائمة 💾)") with gr.Row(): style_input = gr.Textbox(label="✍️ أدخل الستايل الجديد الذي تريد تدريب البوت عليه (بالإنجليزية)", placeholder="مثال: neon anime cyberpunk, pixel art, oily classic portrait") start_btn = gr.Button("🚀 ابدأ تدريب هذا الستايل فوراً") with gr.Row(): status_box = gr.Textbox(label="📊 حالة السيرفر والتدريب المسترجعة") feature_box = gr.Textbox(label="🧠 تفاصيل الجزء الذي يتعلمه الذكاء الاصطناعي الآن") logs_box = gr.Code(label="📜 سجل الأحداث والعمليات المباشر (Logs)", language="markdown") start_btn.click(fn=start_new_training, inputs=style_input, outputs=[status_box, feature_box]) demo.load(fn=get_ui_updates, outputs=[status_box, feature_box, logs_box]) timer = gr.Timer(3) timer.tick(fn=get_ui_updates, outputs=[status_box, feature_box, logs_box]) demo.launch()