File size: 7,047 Bytes
b91289f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import re
import difflib
from typing import Dict, List, Tuple, Any
import spacy
from fuzzywuzzy import fuzz
from medical_terms import load_turkish_medical_terms  # .medical_terms -> medical_terms

# SpaCy modelini yükle (Türkçe model kurulu olmalı)
# pip install https://github.com/explosion/spacy-models/releases/download/tr_core_news_md-3.2.0/tr_core_news_md-3.2.0.tar.gz
try:
    nlp = spacy.load("tr_core_news_md")
except:
    # Eğer model yüklü değilse
    print("Türkçe SpaCy modeli yüklü değil. Yüklemek için: pip install https://github.com/explosion/spacy-models/releases/download/tr_core_news_md-3.2.0/tr_core_news_md-3.2.0.tar.gz")
    nlp = spacy.blank("tr")

try:
    import python_Levenshtein  # Opsiyonel hızlandırma
except ImportError:
    pass  # Olmasa da çalışır

class MedicalTermCorrector:
    def __init__(self, medical_terms: Dict[str, str], threshold: int = 85):
        """

        Tıbbi terimleri düzeltmek için gelişmiş bir düzeltici

        

        Args:

            medical_terms: Tıbbi terimler sözlüğü {yanlış_terim: doğru_terim}

            threshold: Bulanık eşleşme için eşik değeri (0-100)

        """
        self.medical_terms = medical_terms
        self.threshold = threshold
        
        # Terimler için regex kalıpları oluştur
        self.regex_patterns = self._build_regex_patterns()
        
        # Terim varyasyonları için indeks oluştur
        self.term_variations = self._build_term_variations()
        
    def _build_regex_patterns(self) -> Dict[str, re.Pattern]:
        """Tıbbi terimler için regex kalıpları oluşturur"""
        patterns = {}
        for term in self.medical_terms.keys():
            # Basit varyasyon kalıpları: boşluk, tire, kesme işareti varyasyonları
            pattern_str = term.replace(" ", r"\s*")
            pattern_str = pattern_str.replace("-", r"[-\s]?")
            # Türkçe karakter varyasyonları
            pattern_str = re.sub(r'i', r'[iIıİ]', pattern_str)
            pattern_str = re.sub(r'ü', r'[üÜuU]', pattern_str)
            pattern_str = re.sub(r'ö', r'[öÖoO]', pattern_str)
            pattern_str = re.sub(r'ç', r'[çÇcC]', pattern_str)
            pattern_str = re.sub(r'ş', r'[şŞsS]', pattern_str)
            pattern_str = re.sub(r'ğ', r'[ğĞgG]', pattern_str)
            # Daha fazla esneklik için kelime sınırları
            pattern = re.compile(r'\b' + pattern_str + r'\b', re.IGNORECASE)
            patterns[term] = pattern
        return patterns
    
    def _build_term_variations(self) -> Dict[str, List[str]]:
        """Olası terim varyasyonları oluşturur"""
        variations = {}
        for term in self.medical_terms.keys():
            term_vars = [term]
            # Boşluk/tire varyasyonları
            if " " in term:
                term_vars.append(term.replace(" ", "-"))
                term_vars.append(term.replace(" ", ""))
            if "-" in term:
                term_vars.append(term.replace("-", " "))
                term_vars.append(term.replace("-", ""))
            
            # Küçük/büyük harf varyasyonları
            term_vars.append(term.lower())
            term_vars.append(term.upper())
            term_vars.append(term.capitalize())
            
            variations[term] = list(set(term_vars))  # Benzersiz varyasyonlar
        return variations
    
    def find_term_candidates(self, text: str) -> List[Tuple[str, str, float]]:
        """

        Metindeki olası tıbbi terim adaylarını bulur

        

        Returns:

            [(bulunan_terim, doğru_terim, benzerlik_skoru)]

        """
        candidates = []
        
        # 1. Regex ile kesin eşleşmeleri bul
        for term, pattern in self.regex_patterns.items():
            matches = pattern.finditer(text)
            for match in matches:
                correct_term = self.medical_terms[term]
                candidates.append((match.group(), correct_term, 100))
        
        # 2. NLP analizi ile tıbbi terimleri bul
        doc = nlp(text)
        for ent in doc.ents:
            # Eğer varlık sağlık ile ilgiliyse veya sınıflandırılamadıysa
            if ent.label_ in ["DISEASE", "BODY", "CHEMICAL", "MISC", ""]:
                ent_text = ent.text.lower()
                best_match = None
                best_score = 0
                
                # Sözlükteki terimlerle karşılaştır
                for term, correct_term in self.medical_terms.items():
                    # Ana terim ve varyasyonlarla karşılaştır
                    for term_var in self.term_variations.get(term, [term]):
                        score = fuzz.ratio(ent_text, term_var.lower())
                        if score > best_score and score >= self.threshold:
                            best_score = score
                            best_match = correct_term
                
                if best_match:
                    candidates.append((ent.text, best_match, best_score))
        
        # Eğer SpaCy modeli basit ise farklı bir yol izleyelim
        if isinstance(nlp, spacy.blank):
            # Basit kelime tabanlı analiz yap
            words = text.split()
            for word in words:
                # SpaCy'ye güvenmeden basit tıbbi terim kontrolü
                for term, correct_term in self.medical_terms.items():
                    score = fuzz.ratio(word.lower(), term.lower())
                    if score >= self.threshold:
                        candidates.append((word, correct_term, score))
        
        # Tekrarlananları kaldır, en yüksek skorları tut
        unique_candidates = {}
        for found, correct, score in candidates:
            if found not in unique_candidates or score > unique_candidates[found][1]:
                unique_candidates[found] = (correct, score)
        
        return [(found, correct, score) for found, (correct, score) in unique_candidates.items()]
    
    def correct_text(self, text: str) -> str:
        """Metindeki tıbbi terimleri düzeltir"""
        # Terim adaylarını bul
        candidates = self.find_term_candidates(text)
        
        # En uzun terimlerden başlayarak değiştir (kısa terimlerin parçası olan uzun terimleri önceliklendir)
        candidates.sort(key=lambda x: len(x[0]), reverse=True)
        
        corrected_text = text
        for found, correct, score in candidates:
            # Eşleşme %100 değilse, orijinal metinde tam olarak nerede olduğunu bul
            if score < 100:
                # Kelimenin sınırlarını koru
                corrected_text = re.sub(r'\b' + re.escape(found) + r'\b', correct, corrected_text)
            else:
                # Tam eşleşme durumu
                corrected_text = corrected_text.replace(found, correct)
                
        return corrected_text