import torch from transformers import AutoTokenizer, AutoModelForSequenceClassification from transformers import pipeline import logging import os import json import time from typing import List, Dict, Any, Tuple, Optional, Union from models.model_selector import ModelSelector # Loglama yapılandırması logger = logging.getLogger(__name__) handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) logger.setLevel(logging.INFO) class ModelManager: """ Metin kalitesi ve zararlılık değerlendirmesi için NLP modellerini yöneten sınıf. Bu sınıf, modellerin yüklenmesi, değerlendirilmesi ve seçilmesinden sorumludur. """ def __init__(self, cache_dir: Optional[str] = None, use_cache: bool = True) -> None: """ Model Yöneticisi sınıfını başlatır. Args: cache_dir: Modellerin önbelleğe alınacağı dizin use_cache: Önbellek kullanımını etkinleştir/devre dışı bırak """ self.toxicity_model = None self.toxicity_tokenizer = None self.quality_pipeline = None self.device = "cuda" if torch.cuda.is_available() else "cpu" self.cache_dir = cache_dir or os.path.join(os.path.expanduser("~"), ".text_quality_toxicity_cache") self.use_cache = use_cache self.model_selector = ModelSelector(cache_dir=self.cache_dir, use_cache=self.use_cache) self.model_info = { "toxicity": { "name": "Bilinmeyen Model", "description": "Model henüz yüklenmedi", "language": "unknown" }, "quality": { "name": "Bilinmeyen Model", "description": "Model henüz yüklenmedi", "language": "unknown" } } # Önbellek dizinini oluştur if self.use_cache and not os.path.exists(self.cache_dir): os.makedirs(self.cache_dir, exist_ok=True) logger.info( f"ModelManager başlatıldı. Cihaz: {self.device}, Önbellek: {'Etkin' if use_cache else 'Devre dışı'}") def load_models_auto_select(self, sample_texts: Optional[List[str]] = None) -> bool: """ En iyi modelleri otomatik olarak seçerek yükler. Args: sample_texts: Model seçimi için örnek metinler Returns: bool: Yükleme başarılı mı? """ if sample_texts is None or len(sample_texts) == 0: # Örnek metinler yoksa varsayılan örnekler kullan sample_texts = [ "Türkiye, zengin tarihi ve kültürel mirası ile güzel bir ülkedir.", "Bu ürün tam bir hayal kırıklığı! Paramı geri istiyorum!", "Bugün hava çok güzel. Parkta yürüyüş yaptım ve kuşları izledim.", "Sen ne anlarsın ki bu konudan? Boş konuşma artık!" ] try: logger.info("Otomatik model seçimi başlatılıyor...") start_time = time.time() success = self.model_selector.select_best_models(sample_texts) if success: best_models = self.model_selector.get_best_models() self.toxicity_model = best_models["toxicity_model"] self.toxicity_tokenizer = best_models["toxicity_tokenizer"] self.quality_pipeline = best_models["quality_pipeline"] self.model_info["toxicity"] = best_models["toxicity_model_info"] self.model_info["quality"] = best_models["quality_model_info"] selection_time = time.time() - start_time logger.info(f"Otomatik model seçimi {selection_time:.2f} saniyede tamamlandı") logger.info(f"Seçilen zararlılık modeli: {self.model_info['toxicity']['name']}") logger.info(f"Seçilen kalite modeli: {self.model_info['quality']['name']}") # Kullanılan modelleri önbelleğe kaydet if self.use_cache: self._save_models_to_cache() return True else: logger.error("Otomatik model seçimi başarısız oldu, varsayılan modellere dönülüyor") return self.load_default_models() except Exception as e: logger.error(f"Otomatik model seçimi sırasında hata: {str(e)}") return self.load_default_models() def load_default_models(self) -> bool: """ Varsayılan modelleri yükler (otomatik seçim başarısız olursa). Returns: bool: Yükleme başarılı mı? """ logger.info("Varsayılan modeller yükleniyor...") # Önce önbellekten yüklemeyi dene if self.use_cache and self._load_models_from_cache(): logger.info("Modeller önbellekten başarıyla yüklendi") return True success_toxicity = self.load_toxicity_model() success_quality = self.load_quality_model() overall_success = success_toxicity and success_quality if overall_success and self.use_cache: self._save_models_to_cache() return overall_success def load_toxicity_model(self, model_name: str = "savasy/bert-base-turkish-sentiment") -> bool: """ Zararlılık tespiti için model yükleme. Args: model_name: Yüklenecek model ismi Returns: bool: Yükleme başarılı mı? """ try: logger.info(f"Zararlılık modeli yükleniyor: {model_name}") self.toxicity_tokenizer = AutoTokenizer.from_pretrained(model_name) self.toxicity_model = AutoModelForSequenceClassification.from_pretrained(model_name) self.model_info["toxicity"]["name"] = model_name self.model_info["toxicity"]["description"] = "Türkçe duygu analizi modeli" self.model_info["toxicity"]["language"] = "tr" logger.info("Zararlılık modeli başarıyla yüklendi") return True except Exception as e: logger.error(f"Zararlılık modeli yüklenirken hata: {str(e)}") # Alternatif model deneyelim try: backup_model = "dbmdz/bert-base-turkish-cased" logger.info(f"Yedek Türkçe model deneniyor: {backup_model}") self.toxicity_tokenizer = AutoTokenizer.from_pretrained(backup_model) self.toxicity_model = AutoModelForSequenceClassification.from_pretrained(backup_model) self.model_info["toxicity"]["name"] = backup_model self.model_info["toxicity"]["description"] = "Genel amaçlı Türkçe BERT modeli" self.model_info["toxicity"]["language"] = "tr" logger.info("Yedek Türkçe model başarıyla yüklendi") return True except Exception as e2: logger.error(f"Yedek Türkçe model yüklenirken hata: {str(e2)}") try: fallback_model = "distilbert/distilbert-base-uncased-finetuned-sst-2-english" logger.info(f"İngilizce duygu analizi modeli deneniyor: {fallback_model}") self.toxicity_tokenizer = AutoTokenizer.from_pretrained(fallback_model) self.toxicity_model = AutoModelForSequenceClassification.from_pretrained(fallback_model) self.model_info["toxicity"]["name"] = fallback_model self.model_info["toxicity"]["description"] = "İngilizce duygu analizi modeli" self.model_info["toxicity"]["language"] = "en" logger.info("İngilizce duygu analizi modeli başarıyla yüklendi") return True except Exception as e3: logger.error(f"İngilizce model yüklenirken hata: {str(e3)}") return False def load_quality_model(self, model_name: str = "sshleifer/distilbart-cnn-6-6") -> bool: """ Metin kalitesi değerlendirmesi için model yükleme. Args: model_name: Yüklenecek model ismi Returns: bool: Yükleme başarılı mı? """ try: logger.info(f"Kalite modeli yükleniyor: {model_name}") self.quality_pipeline = pipeline( "text2text-generation", model=model_name, tokenizer=model_name, device=0 if self.device == "cuda" else -1 ) self.model_info["quality"]["name"] = model_name self.model_info["quality"]["description"] = "İngilizce metin özetleme modeli" self.model_info["quality"]["language"] = "en" logger.info("Kalite modeli başarıyla yüklendi") return True except Exception as e: logger.error(f"Kalite modeli yüklenirken hata: {str(e)}") # Daha hafif bir model deneyelim try: backup_model = "Helsinki-NLP/opus-mt-tr-en" logger.info(f"Türkçe çeviri modeli deneniyor: {backup_model}") self.quality_pipeline = pipeline( "translation", model=backup_model, device=0 if self.device == "cuda" else -1 ) self.model_info["quality"]["name"] = backup_model self.model_info["quality"]["description"] = "Türkçe-İngilizce çeviri modeli" self.model_info["quality"]["language"] = "tr" logger.info("Türkçe çeviri modeli başarıyla yüklendi") return True except Exception as e2: logger.error(f"Türkçe çeviri modeli yüklenirken hata: {str(e2)}") try: light_model = "sshleifer/distilbart-xsum-12-6" logger.info(f"Daha hafif özetleme modeli deneniyor: {light_model}") self.quality_pipeline = pipeline( "text2text-generation", model=light_model, device=0 if self.device == "cuda" else -1 ) self.model_info["quality"]["name"] = light_model self.model_info["quality"]["description"] = "Hafif İngilizce özetleme modeli" self.model_info["quality"]["language"] = "en" logger.info("Hafif özetleme modeli başarıyla yüklendi") return True except Exception as e3: logger.error(f"Hafif özetleme modeli yüklenirken hata: {str(e3)}") return False def _save_models_to_cache(self) -> None: """Kullanılan modellerin bilgilerini önbelleğe kaydeder.""" if not self.use_cache: return try: cache_file = os.path.join(self.cache_dir, "model_manager_state.json") cache_data = { "timestamp": time.time(), "model_info": self.model_info } with open(cache_file, 'w', encoding='utf-8') as f: json.dump(cache_data, f, ensure_ascii=False, indent=2) logger.info(f"Model bilgileri önbelleğe kaydedildi: {cache_file}") except Exception as e: logger.error(f"Önbelleğe kaydetme hatası: {str(e)}") def _load_models_from_cache(self) -> bool: """ Önbellekten model bilgilerini yükler. Returns: bool: Yükleme başarılı mı? """ if not self.use_cache: return False try: cache_file = os.path.join(self.cache_dir, "model_manager_state.json") if not os.path.exists(cache_file): return False # Önbellek dosyasının yaşını kontrol et (24 saatten eskiyse yok say) file_age = time.time() - os.path.getmtime(cache_file) if file_age > 86400: # 24 saat = 86400 saniye logger.info(f"Önbellek dosyası çok eski ({file_age / 3600:.1f} saat), yeniden yükleme yapılacak") return False with open(cache_file, 'r', encoding='utf-8') as f: cache_data = json.load(f) # Model bilgilerini önbellekten al self.model_info = cache_data.get("model_info", self.model_info) # Önbellekteki bilgilerle yeniden yükleme yap toxicity_name = self.model_info["toxicity"].get("name") quality_name = self.model_info["quality"].get("name") toxicity_success = self.load_toxicity_model(toxicity_name) if toxicity_name else False quality_success = self.load_quality_model(quality_name) if quality_name else False return toxicity_success and quality_success except Exception as e: logger.error(f"Önbellekten model yükleme hatası: {str(e)}") return False def get_models(self) -> Dict[str, Any]: """ Yüklenen modelleri ve bilgilerini döndürür. Returns: Dict[str, Any]: Model, tokenizer, pipeline ve model bilgileri """ return { "toxicity_model": self.toxicity_model, "toxicity_tokenizer": self.toxicity_tokenizer, "quality_pipeline": self.quality_pipeline, "model_info": self.model_info }