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