69 lines
3.5 KiB
Python
69 lines
3.5 KiB
Python
"""
|
|
Medication extraction engine supporting structured dosage, frequency, and confirmed_none status.
|
|
"""
|
|
|
|
import re
|
|
from typing import Dict, Any, List, Optional, Union
|
|
|
|
KNOWN_MED_PATTERNS = [
|
|
(r"(metformin(?:\s+\d+\s*mg)?(?:\s+twice\s+a\s+day)?)", "Metformin"),
|
|
(r"(paracetamol(?:\s+\d+\s*mg)?)", "Paracetamol"),
|
|
(r"(dolo(?:\s*650)?)", "Dolo 650 (Paracetamol)"),
|
|
(r"(pantocid|pan-d|pan 40|omez|omeprazole)", "Pantoprazole / Antacid"),
|
|
(r"(telmisartan|telma\s*\d+)", "Telmisartan (BP)"),
|
|
(r"(amlodipine|amlong\s*\d+)", "Amlodipine (BP)"),
|
|
(r"((?:bp|பிபி|blood\s*pressure)\s*(?:மாத்திரை|medicine|tablet|tablets|மருந்து))", "BP Medication"),
|
|
(r"((?:sugar|சுகர்|சர்க்கரை)\s*(?:மாத்திரை|medicine|tablet|tablets|மருந்து))", "Diabetes Medication"),
|
|
(r"((?:thyroid|தைராய்டு)\s*(?:மாத்திரை|medicine|tablet|tablets|மருந்து))", "Thyroid Medication"),
|
|
]
|
|
|
|
|
|
def extract_medications(
|
|
message: str,
|
|
normalized_msg: str,
|
|
last_ai_message: Optional[str] = None,
|
|
is_allergy_utterance: bool = False
|
|
) -> Optional[Union[List[Dict[str, Any]], Dict[str, Any]]]:
|
|
"""
|
|
Extracts structured medications or confirmed_none container.
|
|
"""
|
|
msg_lower = normalized_msg.lower()
|
|
|
|
# Check for explicit negation of medicines
|
|
neg_phrases = [
|
|
"no medicines", "no medication", "don't take any medicine", "don't take medicines",
|
|
"no tablets", "not taking any medicine", "no daily medicines", "no regular medicines",
|
|
"மாத்திரை எதுவும் இல்லை", "எந்த மாத்திரையும் சாப்பிடல", "மருந்து எதுவும் இல்லை",
|
|
"कोई दवा नहीं", "दवाई नहीं लेते", "दवा नहीं लेता", "ఏ మందులు లేవు", "ಯಾವ ಮಾತ್ರೆ ಇಲ್ಲ"
|
|
]
|
|
if any(neg in msg_lower for neg in neg_phrases):
|
|
return {"status": "confirmed_none", "items": []}
|
|
|
|
meds: List[Dict[str, Any]] = []
|
|
|
|
# Known medicine matchers
|
|
for pat, med_label in KNOWN_MED_PATTERNS:
|
|
m_match = re.search(pat, msg_lower)
|
|
if m_match:
|
|
matched_str = m_match.group(1).strip()
|
|
med_obj: Dict[str, Any] = {"name": med_label}
|
|
|
|
dosage_m = re.search(r"(\d+\s*mg|\d+\s*ml)", matched_str)
|
|
if dosage_m:
|
|
med_obj["dosage"] = dosage_m.group(1).strip()
|
|
|
|
freq_m = re.search(r"(twice\s+a\s+day|once\s+a\s+day|\d+\s+times\s+a\s+day|daily|twice)", matched_str)
|
|
if freq_m:
|
|
med_obj["frequency"] = freq_m.group(1).strip()
|
|
|
|
if not any(x.get("name") == med_obj["name"] for x in meds):
|
|
meds.append(med_obj)
|
|
|
|
# Generic medicine indicator matchers (only if not an allergy utterance)
|
|
if not meds and not is_allergy_utterance:
|
|
generic_pat = r"(tablets|goli|mathirai|மாத்திரை|மருந்து|दवाई|दवा|మాత్రలు|ಮಾತ್ರೆಗಳು)"
|
|
if re.search(generic_pat, msg_lower) and any(verb in msg_lower for verb in ["take", "taking", "சாப்பிடுறேன்", "சாப்பிட்டேன்", "வாங்குறேன்", "लेता", "लेती", "వాడుతున్నాను"]):
|
|
meds.append({"name": "Unspecified medication"})
|
|
|
|
return meds if meds else None
|