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