Spaces:
Sleeping
Sleeping
| import torch | |
| import numpy as np | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification | |
| import logging | |
| import re | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
| class ToxicityScorer: | |
| def __init__(self, model=None, tokenizer=None): | |
| """ | |
| Toxicity Scorer sınıfını başlatır. | |
| Args: | |
| model: Zararlılık modeli | |
| tokenizer: Model için tokenizer | |
| """ | |
| self.model = model | |
| self.tokenizer = tokenizer | |
| self.device = "cuda" if torch.cuda.is_available() else "cpu" | |
| self.is_turkish_model = False | |
| if model is None or tokenizer is None: | |
| logging.warning("No toxicity model provided. Using default model.") | |
| self.load_default_model() | |
| def load_default_model(self): | |
| """ | |
| Varsayılan zararlılık modelini yükler | |
| """ | |
| try: | |
| # Öncelikle Türkçe duygu analizi modeli deneyelim | |
| model_name = "savasy/bert-base-turkish-sentiment" | |
| logging.info(f"Loading Turkish sentiment model: {model_name}") | |
| self.tokenizer = AutoTokenizer.from_pretrained(model_name) | |
| self.model = AutoModelForSequenceClassification.from_pretrained(model_name) | |
| self.model.to(self.device) | |
| self.is_turkish_model = True | |
| logging.info("Turkish sentiment model loaded successfully") | |
| except Exception as e: | |
| logging.error(f"Error loading Turkish model: {str(e)}") | |
| try: | |
| # Yedek olarak genel model yükleyelim | |
| backup_model = "dbmdz/bert-base-turkish-cased" | |
| logging.info(f"Trying Turkish BERT model: {backup_model}") | |
| self.tokenizer = AutoTokenizer.from_pretrained(backup_model) | |
| self.model = AutoModelForSequenceClassification.from_pretrained(backup_model) | |
| self.model.to(self.device) | |
| self.is_turkish_model = True | |
| logging.info("Turkish BERT model loaded successfully") | |
| except Exception as e2: | |
| logging.error(f"Error loading Turkish BERT model: {str(e2)}") | |
| try: | |
| # Son çare olarak İngilizce model kullanalım | |
| english_model = "distilbert/distilbert-base-uncased-finetuned-sst-2-english" | |
| logging.info(f"Trying English sentiment model: {english_model}") | |
| self.tokenizer = AutoTokenizer.from_pretrained(english_model) | |
| self.model = AutoModelForSequenceClassification.from_pretrained(english_model) | |
| self.model.to(self.device) | |
| self.is_turkish_model = False | |
| logging.info("English sentiment model loaded successfully") | |
| except Exception as e3: | |
| logging.error(f"Error loading English model: {str(e3)}") | |
| raise e3 | |
| def _contains_turkish_profanity(self, text): | |
| """ | |
| Temel Türkçe küfür ve hakaret kontrolü yapar | |
| """ | |
| # Türkçede yaygın küfür/hakaret içeren kelimelerin listesi | |
| turkish_profanity = [ | |
| 'aptal', 'salak', 'gerizekalı', 'ahmak', 'enayi', 'mal', 'geri zekalı', | |
| 'beyinsiz', 'budala', 'adi', 'ahlaksız', 'şerefsiz', 'haysiyetsiz', | |
| 'orospu', 'piç', 'yavşak', 'sürtük', 'sürtüğü', 'gavat', 'şerefsiz', | |
| 'siktir', 'pezevenk', 'namussuz' | |
| ] | |
| # Noktalama işaretlerini ve sayıları kaldır | |
| text = re.sub(r'[^\w\s]', '', text.lower()) | |
| text = re.sub(r'\d+', '', text) | |
| words = text.split() | |
| # Metinde küfür/hakaret var mı kontrol et | |
| for word in turkish_profanity: | |
| if word in words: | |
| return True | |
| return False | |
| def _contains_negative_words(self, text): | |
| """ | |
| Temel Türkçe olumsuz kelime kontrolü yapar | |
| """ | |
| # Türkçede yaygın olumsuz kelimeler | |
| negative_words = [ | |
| 'kötü', 'berbat', 'rezalet', 'korkunç', 'iğrenç', 'üzücü', 'acı', | |
| 'başarısız', 'yetersiz', 'düşük', 'zayıf', 'korkutucu', 'tehlikeli', | |
| 'nefret', 'öfke', 'saldırgan', 'yanlış', 'hata', 'hayal kırıklığı' | |
| ] | |
| text = text.lower() | |
| count = sum(1 for word in negative_words if word in text.split()) | |
| # Olumsuz kelime yoğunluğunu hesapla | |
| return count / len(text.split()) if text.split() else 0 | |
| def score_text(self, text): | |
| """ | |
| Metin için zararlılık skoru hesaplar. | |
| Args: | |
| text: Değerlendirilecek metin | |
| Returns: | |
| float: 0 ile 1 arasında zararlılık skoru (1 = çok zararlı) | |
| """ | |
| if not text or len(text.strip()) == 0: | |
| return 0.0 | |
| # Temel kural tabanlı kontroller | |
| profanity_detected = self._contains_turkish_profanity(text) | |
| negative_ratio = self._contains_negative_words(text) | |
| if profanity_detected: | |
| base_score = 0.8 # Küfür/hakaret varsa yüksek başlangıç skoru | |
| else: | |
| base_score = negative_ratio * 0.5 # Olumsuz kelime yoğunluğuna göre skor | |
| try: | |
| # Model tabanlı skorlama | |
| inputs = self.tokenizer(text, return_tensors="pt", truncation=True, max_length=512) | |
| inputs = {key: val.to(self.device) for key, val in inputs.items()} | |
| with torch.no_grad(): | |
| outputs = self.model(**inputs) | |
| # Modele göre doğru şekilde skoru alalım | |
| if self.is_turkish_model: | |
| # Türkçe duygu analizi modeli için özel işlem | |
| probs = torch.softmax(outputs.logits, dim=1).cpu().numpy()[0] | |
| # savasy/bert-base-turkish-sentiment için: | |
| # 0: negative, 1: neutral, 2: positive | |
| if len(probs) >= 3: | |
| # Negatif olasılığını zararlılık skoru olarak kullan ama çok yüksek değerler üretmemesi için 0.7 ile çarp | |
| model_score = probs[0] * 0.7 | |
| else: | |
| # İki sınıflı model için | |
| model_score = probs[0] * 0.6 | |
| else: | |
| # İngilizce model için | |
| probs = torch.softmax(outputs.logits, dim=1).cpu().numpy()[0] | |
| # İngilizce modeller genellikle Türkçe için çok yüksek sonuçlar verir, bu yüzden 0.5 ile çarp | |
| model_score = probs[0] * 0.5 | |
| # Kural tabanlı skor ve model skor birleşimi | |
| final_score = (base_score * 0.4) + (model_score * 0.6) | |
| # 0-1 aralığına sınırla | |
| final_score = max(0.0, min(1.0, final_score)) | |
| return final_score | |
| except Exception as e: | |
| logging.error(f"Error scoring toxicity: {str(e)}") | |
| # Hata durumunda sadece kural tabanlı skoru döndür | |
| return min(base_score, 1.0) | |
| def batch_score(self, texts, batch_size=16): | |
| """ | |
| Bir metin listesi için toplu zararlılık skoru hesaplar. | |
| Args: | |
| texts: Değerlendirilecek metin listesi | |
| batch_size: İşlenecek grup boyutu | |
| Returns: | |
| list: Zararlılık skorları listesi | |
| """ | |
| results = [] | |
| for i in range(0, len(texts), batch_size): | |
| batch_texts = texts[i:i + batch_size] | |
| batch_scores = [self.score_text(text) for text in batch_texts] | |
| results.extend(batch_scores) | |
| return results |