File size: 7,968 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
189
190
191
192
193
194
195
196
197
198
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