VoiceToWrite / advanced_term_correction.py
Seicas's picture
Upload advanced_term_correction.py
b91289f verified
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