Files
aionboarding/ai-patient-onboarding/app/ai/extraction/allergy_extractor.py
T

57 lines
2.4 KiB
Python

"""
Allergy extraction engine distinguishing drug/food allergies from side effects.
"""
import re
from typing import Dict, Any, List, Optional, Union
ALLERGEN_PATTERNS = [
(r"(penicillin)", "Penicillin"),
(r"(sulfa)", "Sulfa drugs"),
(r"(aspirin)", "Aspirin"),
(r"(dust)", "Dust allergy"),
(r"(peanuts)", "Peanuts"),
(r"(milk|dairy)", "Milk / Dairy"),
]
def extract_allergies(
message: str,
normalized_msg: str,
last_ai_message: Optional[str] = None
) -> Optional[Union[List[Dict[str, Any]], Dict[str, Any]]]:
"""
Extracts structured allergies or confirmed_none container.
"""
msg_lower = normalized_msg.lower()
# Check for explicit negation of allergies
neg_phrases = [
"no allergies", "no allergy", "no drug allergy", "no food allergy", "not allergic",
"nkda", "no allergic reaction", "அலர்ஜி எதுவும் இல்லை", "எந்த அலர்ஜியும் இல்லை",
"कोई एलर्जी नहीं", "कोई समस्या नहीं", "ఏ అలర్జీ లేదు", "ಯಾವ ಅಲರ್ಜಿ ಇಲ್ಲ"
]
if any(neg in msg_lower for neg in neg_phrases):
return {"status": "confirmed_none", "items": []}
allergies: List[Dict[str, Any]] = []
has_allergen = any(re.search(pat, msg_lower) for pat, _ in ALLERGEN_PATTERNS)
has_alg_indicator = any(k in msg_lower or k in message for k in ["allergic", "allergy", "அலர்ஜி", "ஒவ்வாமை", "एलर्जी", "rash", "reaction", "side effect", "தடிப்பு", "எடுத்தா"])
# Side effect distinction: "Paracetamol didn't reduce fever" is NOT an allergy
if "didn't reduce" in msg_lower or "didn't work" in msg_lower or "no effect" in msg_lower:
return None
if has_allergen or has_alg_indicator:
for pat, allergen in ALLERGEN_PATTERNS:
if re.search(pat, msg_lower):
alg_obj: Dict[str, Any] = {"name": allergen}
if "rash" in msg_lower or "தடிப்பு" in message or "खुजली" in message:
alg_obj["reaction"] = "Rash / Skin reaction"
allergies.append(alg_obj)
if not allergies and has_alg_indicator:
allergies.append({"name": "Reported allergy", "type": "unspecified"})
return allergies if allergies else None