""" 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