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