Spaces:
Running
Running
import numpy as np | |
from transformers import pipeline | |
import torch | |
import logging | |
import re | |
from sklearn.feature_extraction.text import CountVectorizer | |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
class QualityScorer: | |
def __init__(self, quality_pipeline=None): | |
""" | |
Metin kalitesi değerlendirme sınıfını başlatır. | |
Args: | |
quality_pipeline: Metin özetleme pipeline'ı | |
""" | |
self.pipeline = quality_pipeline | |
self.device = "cuda" if torch.cuda.is_available() else "cpu" | |
# Temel kalite ölçütleri için yardımcı araçlar | |
self.vectorizer = CountVectorizer(max_features=5000) | |
# Türkçeye özgü doldurma (filler) kelimeleri | |
self.turkish_filler_words = [ | |
'yani', 'işte', 'şey', 'falan', 'filan', 'hani', 'mesela', 'aslında', | |
'ya', 'ki', 'de', 'da', 'çok', 'ama', 'fakat', 'lakin', 'ancak', | |
'gerçekten', 'kesinlikle', 'tabii', 'tabi', 'şimdi', 'sonra', 'önce' | |
] | |
def score_text(self, text): | |
""" | |
Metin için kalite skoru hesaplar. | |
Args: | |
text: Değerlendirilecek metin | |
Returns: | |
float: 0 ile 1 arasında kalite skoru (1 = yüksek kalite) | |
""" | |
if not text or len(text.strip()) == 0: | |
return 0.0, {} | |
# Metni temizle | |
text = text.strip() | |
# Çeşitli metin özelliklerini değerlendirelim | |
features = {} | |
# 1. Uzunluk puanı - Çok kısa veya çok uzun metinler düşük puan alır | |
length = len(text.split()) | |
if length < 3: | |
features['length_score'] = 0.1 | |
elif length < 5: | |
features['length_score'] = 0.2 | |
elif length < 10: | |
features['length_score'] = 0.4 | |
elif length < 20: | |
features['length_score'] = 0.6 | |
elif length < 100: | |
features['length_score'] = 0.8 | |
elif length < 500: | |
features['length_score'] = 1.0 | |
elif length < 1000: | |
features['length_score'] = 0.8 | |
else: | |
features['length_score'] = 0.6 | |
# 2. Gramer ve yazım denetimi (Türkçe için uyarlanmış) | |
# Türkçede noktalama işaretleri ve büyük harf kullanımı | |
sentences = re.split(r'[.!?]+', text) | |
sentences = [s.strip() for s in sentences if s.strip()] | |
if not sentences: | |
features['grammar_score'] = 0.0 | |
else: | |
# Cümlelerin büyük harfle başlayıp başlamadığını kontrol et | |
correct_caps = sum(1 for s in sentences if s and s[0].isupper()) | |
caps_ratio = correct_caps / len(sentences) if sentences else 0 | |
# Noktalama işaretlerinin varlığını kontrol et | |
punct_count = len(re.findall(r'[.!?,;:]', text)) | |
expected_punct = max(1, len(sentences) - 1) # Beklenen minimum noktalama | |
punct_ratio = min(1.0, punct_count / expected_punct) if expected_punct > 0 else 0 | |
# Türkçe'ye özgü yaygın yazım hatalarını kontrol et | |
common_errors = [ | |
('de da', 'de/da ayrı yazılmalı'), | |
('ki', 'ki bağlacı ayrı yazılmalı'), | |
('misin', 'soru eki ayrı yazılmalı'), | |
('geldimi', 'soru eki ayrı yazılmalı'), | |
('bişey', 'bir şey ayrı yazılmalı'), | |
('herşey', 'her şey ayrı yazılmalı'), | |
('hiçbirşey', 'hiçbir şey ayrı yazılmalı') | |
] | |
error_count = sum(1 for error, _ in common_errors if error in text.lower()) | |
error_ratio = 1.0 - min(1.0, error_count / (len(text.split()) / 10 + 1)) | |
# Gramer puanını hesapla | |
features['grammar_score'] = (caps_ratio * 0.4 + punct_ratio * 0.3 + error_ratio * 0.3) | |
# 3. Kelime çeşitliliği (Türkçe için uyarlanmış) | |
words = re.findall(r'\b\w+\b', text.lower()) | |
unique_words = set(words) | |
if not words: | |
features['diversity_score'] = 0.0 | |
else: | |
# Türkçe metinler için çeşitlilik oranını ayarla | |
diversity_ratio = len(unique_words) / len(words) | |
# Türkçe'nin çekimli yapısı nedeniyle daha yüksek bir baz çeşitlilik beklenir | |
features['diversity_score'] = min(1.0, diversity_ratio * 1.2) | |
# 4. Özetlenebilirlik puanı - eğer pipeline varsa | |
if self.pipeline and len(text.split()) > 20: | |
try: | |
# Pipeline özetleme mi yoksa çeviri mi ona göre işle | |
if hasattr(self.pipeline, 'task') and self.pipeline.task == 'translation': | |
# Çeviri pipeline'ı, bu durumda çevirinin kalitesine bakma | |
translated = self.pipeline(text, max_length=100)[0]['translation_text'] | |
features['summary_score'] = 0.7 # Varsayılan olarak iyi bir puan | |
else: | |
# Özetleme pipeline'ı | |
max_length = min(128, max(30, len(text.split()) // 4)) | |
summary = self.pipeline(text, max_length=max_length, min_length=10, do_sample=False)[0][ | |
'generated_text'] | |
# Özet ve orijinal metin arasındaki benzerliğe bakarak puan ver | |
summary_len = len(summary.split()) | |
orig_len = len(text.split()) | |
compression_ratio = summary_len / orig_len if orig_len > 0 else 0 | |
if compression_ratio > 0.8 or compression_ratio < 0.05: | |
features['summary_score'] = 0.3 | |
elif compression_ratio > 0.6 or compression_ratio < 0.1: | |
features['summary_score'] = 0.6 | |
else: | |
features['summary_score'] = 0.9 | |
except Exception as e: | |
logging.warning(f"Error during summarization: {str(e)}") | |
features['summary_score'] = 0.5 | |
else: | |
features['summary_score'] = 0.5 | |
# 5. Türkçe doldurma kelimeleri (filler words) | |
filler_count = sum(1 for word in words if word.lower() in self.turkish_filler_words) | |
if not words: | |
features['filler_score'] = 1.0 | |
else: | |
filler_ratio = filler_count / len(words) | |
# Türkçede bazı doldurma kelimeleri doğal olabilir, bu yüzden daha toleranslı davran | |
features['filler_score'] = 1.0 - min(1.0, filler_ratio * 3) | |
# Puanları birleştir - farklı puanları ağırlıklandırarak | |
weights = { | |
'length_score': 0.15, | |
'grammar_score': 0.3, # Türkçe için gramere daha fazla ağırlık | |
'diversity_score': 0.25, | |
'summary_score': 0.2, | |
'filler_score': 0.1 | |
} | |
final_score = sum(features[key] * weights[key] for key in weights.keys()) | |
# Puanı 0-1 aralığına normalize et | |
final_score = max(0.0, min(1.0, final_score)) | |
return final_score, features | |
def batch_score(self, texts, batch_size=8): | |
""" | |
Bir metin listesi için toplu kalite skoru hesaplar. | |
Args: | |
texts: Değerlendirilecek metin listesi | |
batch_size: İşlenecek grup boyutu | |
Returns: | |
list: Kalite skorları listesi | |
""" | |
results = [] | |
feature_results = [] | |
for i in range(0, len(texts), batch_size): | |
batch_texts = texts[i:i + batch_size] | |
batch_results = [] | |
batch_features = [] | |
for text in batch_texts: | |
score, features = self.score_text(text) | |
batch_results.append(score) | |
batch_features.append(features) | |
results.extend(batch_results) | |
feature_results.extend(batch_features) | |
return results, feature_results |