Spaces:
Running
Running
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 |