Spaces:
Running
Running
File size: 7,630 Bytes
bd97f47 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
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 |