import os import json import time import uuid from datetime import datetime from typing import List, Dict, Optional, Generator, Tuple, Any from dataclasses import dataclass, asdict from functools import lru_cache import gradio as gr import requests from dotenv import load_dotenv from ollama import Client import markdown import bleach # تحميل المتغيرات البيئية load_dotenv() # ==================== معلومات التطبيق ==================== APP_NAME = "🧞 Genisi - المساعد الذكي" APP_VERSION = "3.0.1" # تحديث الإصدار CREATOR = "AnesNT" MODEL_NAME = "gpt-oss:20b" HF_SPACE = "AnesNT/Genisi-v3" # ==================== الإعدادات ==================== OLLAMA_HOST = os.getenv("OLLAMA_HOST", "https://ollama.com") MAX_HISTORY = int(os.getenv("MAX_HISTORY", "50")) TEMPERATURE = float(os.getenv("TEMPERATURE", "0.8")) MAX_TOKENS = int(os.getenv("MAX_TOKENS", "2048")) # ==================== عميل Ollama ==================== class GenisiModel: """فئة Genisi للتعامل مع GPT-OSS 20B""" def __init__(self): self.model = MODEL_NAME self.fallback_model = "llama2:13b" self.client = None self.initialize() def initialize(self): """تهيئة الاتصال بـ Ollama""" try: self.client = Client(host=OLLAMA_HOST) print(f"✅ تم تهيئة Genisi باستخدام {self.model}") except Exception as e: print(f"⚠️ تحذير: {e}") self.client = None def generate(self, prompt: str, system_prompt: Optional[str] = None, temperature: float = TEMPERATURE, max_tokens: int = MAX_TOKENS) -> str: """توليد رد من النموذج""" if not self.client: return "⚠️ عذراً، النموذج غير متاح حالياً. الرجاء المحاولة لاحقاً." try: # تحضير الرسائل messages = [] if system_prompt: messages.append({ 'role': 'system', 'content': system_prompt }) messages.append({ 'role': 'user', 'content': prompt }) # إعدادات التوليد options = { "temperature": temperature, "num_predict": max_tokens, "top_p": 0.9, "top_k": 40, "repeat_penalty": 1.1 } # محاولة استخدام النموذج الرئيسي try: response = self.client.chat( model=self.model, messages=messages, options=options ) except Exception as e: print(f"⚠️ استخدام النموذج الاحتياطي: {e}") response = self.client.chat( model=self.fallback_model, messages=messages, options=options ) # استخراج الرد if response and 'message' in response: return response['message']['content'] else: return "عذراً، لم أتمكن من توليد رد." except Exception as e: error_msg = f"❌ خطأ: {str(e)}" print(error_msg) return error_msg # ==================== إدارة المحادثات ==================== class ChatHistory: """إدارة سجل المحادثات""" def __init__(self): self.history = [] self.history_file = "chat_history.json" self.load() def load(self): """تحميل سجل المحادثات""" try: if os.path.exists(self.history_file): with open(self.history_file, 'r', encoding='utf-8') as f: self.history = json.load(f) except Exception as e: print(f"⚠️ خطأ في تحميل التاريخ: {e}") self.history = [] def save(self): """حفظ سجل المحادثات""" try: # الاحتفاظ بآخر 50 محادثة فقط if len(self.history) > MAX_HISTORY: self.history = self.history[-MAX_HISTORY:] with open(self.history_file, 'w', encoding='utf-8') as f: json.dump(self.history, f, ensure_ascii=False, indent=2) except Exception as e: print(f"⚠️ خطأ في حفظ التاريخ: {e}") def add(self, user_message: str, bot_response: str): """إضافة محادثة جديدة""" self.history.append({ 'timestamp': datetime.now().isoformat(), 'user': user_message, 'bot': bot_response, 'model': MODEL_NAME }) self.save() def get_recent(self, count: int = 5) -> List[Dict]: """الحصول على آخر المحادثات""" return self.history[-count:] def get_system_prompt() -> str: """الحصول على رسالة النظام""" return f"""أنت Genisi، مساعد ذكي تم تطويره بواسطة AnesNT. أنت تستخدم نموذج {MODEL_NAME} القوي. تحدث باللغة العربية الفصحى دائماً. كن مفيداً ومحترماً في ردودك. قدم إجابات دقيقة ومفصلة.""" # ==================== إنشاء النماذج ==================== model = GenisiModel() chat_history = ChatHistory() # ==================== دوال التفاعل ==================== def respond(message: str, history: List[List[str]]) -> Tuple[str, List[List[str]]]: """دالة الرد على الرسائل""" if not message or not message.strip(): return "", history # إضافة رسالة المستخدم history.append([message, None]) try: # توليد الرد response = model.generate( prompt=message, system_prompt=get_system_prompt(), temperature=TEMPERATURE ) # تحديث الرد history[-1][1] = response # حفظ المحادثة chat_history.add(message, response) except Exception as e: history[-1][1] = f"❌ خطأ: {str(e)}" return "", history def clear_chat() -> List: """مسح المحادثة""" return [] def get_stats() -> str: """الحصول على إحصائيات""" stats = f"""### 📊 إحصائيات Genisi - **النموذج**: {MODEL_NAME} - **عدد المحادثات**: {len(chat_history.history)} - **آخر تحديث**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - **المطور**: {CREATOR} - **الإصدار**: {APP_VERSION} """ return stats def set_example(example: str) -> str: """تعيين مثال للسؤال""" return example # ==================== واجهة Gradio 6.0 ==================== # تخصيص شكل Gradio - متوافق مع الإصدار 6.0 custom_css = """ /* تنسيقات عامة */ .gradio-container { max-width: 1200px !important; margin: auto !important; direction: rtl !important; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important; } /* تنسيق العنوان */ .title-container { text-align: center; margin-bottom: 30px; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; color: white; } .title-container h1 { font-size: 3em; margin-bottom: 10px; text-shadow: 2px 2px 4px rgba(0,0,0,0.2); } .title-container p { font-size: 1.2em; opacity: 0.9; } /* تنسيق الأزرار */ button { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; border: none !important; color: white !important; transition: transform 0.2s !important; } button:hover { transform: scale(1.02) !important; } /* تنسيق مربع النص */ textarea { border-radius: 10px !important; border: 2px solid #e0e0e0 !important; font-size: 16px !important; padding: 10px !important; } /* تنسيق المحادثة */ .chat-message { border-radius: 15px !important; margin: 10px 0 !important; padding: 10px 15px !important; } .user-message { background-color: #667eea !important; color: white !important; } .bot-message { background-color: #f0f0f0 !important; color: #333 !important; } /* تنسيق التذييل */ .footer { text-align: center; margin-top: 30px; padding: 20px; color: #666; border-top: 1px solid #e0e0e0; } .footer a { color: #667eea; text-decoration: none; } .footer a:hover { text-decoration: underline; } """ # إنشاء واجهة Gradio - متوافقة مع الإصدار 6.0 with gr.Blocks() as demo: # العنوان gr.HTML(f"""
{APP_NAME} - المدعوم بـ {MODEL_NAME}
تم التطوير بواسطة {CREATOR}