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