55 lines
2.5 KiB
Python
55 lines
2.5 KiB
Python
"""
|
|
Contextual negation and scope resolution engine.
|
|
"""
|
|
|
|
import re
|
|
from typing import Dict, Any, Tuple
|
|
|
|
|
|
# Family relations
|
|
FAMILY_RELATIONS = [
|
|
("father", "father"), ("dad", "father"), ("appa", "father"), ("அப்பா", "father"), ("पिता", "father"), ("नाना", "grandfather"),
|
|
("mother", "mother"), ("mom", "mother"), ("amma", "mother"), ("அம்மா", "mother"), ("माँ", "mother"), ("माता", "mother"),
|
|
("brother", "brother"), ("annaa", "brother"), ("தம்பி", "brother"), ("अண்ணன்", "brother"), ("भाई", "brother"),
|
|
("sister", "sister"), ("akka", "sister"), ("அக்கா", "sister"), ("தங்கை", "sister"), ("बहन", "sister"),
|
|
("parent", "parent"), ("grand-father", "grandfather"), ("grandfather", "grandfather"), ("grandmother", "grandmother"),
|
|
]
|
|
|
|
# Negation indicators
|
|
NEGATION_PHRASES = [
|
|
"don't have", "do not have", "no history of", "no symptoms", "no allergies", "no allergy", "no medicine",
|
|
"no medications", "don't take", "do not take", "never had", "without", "denies", "absent",
|
|
"இல்லை", "எதுவும் இல்லை", "இல்லவே இல்லை", "மாத்திரை எதுவும் இல்லை", "நோயும் இல்லை",
|
|
"नहीं है", "कोई बीमारी नहीं", "कोई एलर्जी नहीं", "कोई दवा नहीं",
|
|
"లేవు", "ఏమీ లేదు", "ఇబ్బంది లేదు",
|
|
"ಇಲ್ಲ", "ಯಾವುದೇ ಇಲ್ಲ",
|
|
]
|
|
|
|
|
|
def is_negated(text: str) -> bool:
|
|
"""Returns True if the text expresses explicit negation."""
|
|
if not text:
|
|
return False
|
|
msg_lower = text.lower().strip()
|
|
if msg_lower in ["no", "none", "nothing", "no more", "nil", "illness none", "nkda"]:
|
|
return True
|
|
return any(neg in msg_lower for neg in NEGATION_PHRASES)
|
|
|
|
|
|
def extract_family_subject(text: str) -> Tuple[bool, str, str]:
|
|
"""
|
|
Checks if text refers to family member rather than the patient.
|
|
Returns: (is_family_history, relation, condition_text)
|
|
"""
|
|
if not text:
|
|
return False, "", text
|
|
|
|
msg_lower = text.lower().strip()
|
|
for rel_kw, rel_canonical in FAMILY_RELATIONS:
|
|
pattern = rf"\b{re.escape(rel_kw)}\b"
|
|
if re.search(pattern, msg_lower) or rel_kw in text:
|
|
# Check if patient explicitly negates disease for self in same turn
|
|
return True, rel_canonical, text
|
|
|
|
return False, "", text
|