Files
aionboarding/ai-patient-onboarding/app/ai/orchestrator.py
T

189 lines
12 KiB
Python

import asyncio
import json
from app.ai.openai_client import OpenAIClient
from app.ai.prompts import build_system_prompt
from app.ai.validator import validate_ai_response
from app.config import OPENAI_API_KEY, GEMINI_API_KEY, GEMINI_MODEL, ANTHROPIC_API_KEY, ANTHROPIC_MODEL
from app.specialties.registry import get_specialty_config
class AIOrchestrator:
def __init__(self):
self.openai = OpenAIClient()
async def process(
self,
session,
state,
conversation_history,
user_message,
):
specialty = get_specialty_config(
session.category_code
)
current_state = json.loads(
state.state_json
)
context = {
"patient": {
"id": session.patient_id,
"name": session.patient_name,
"age": session.age,
"gender": session.gender,
},
"category": {
"type": session.category_type,
"code": session.category_code,
"name": session.category_name,
},
"specialty_config": specialty,
"language": session.language,
"current_stage": session.stage,
"current_state": current_state,
"conversation_history": conversation_history,
"new_patient_message": user_message,
}
prompt = build_system_prompt(context)
# Skip invalid/exhausted API keys to prevent 20+ second HTTP timeouts
# 1. Fallback simulator (0.001s instant response time)
parsed = self._simulate_specialty_response(session, specialty, user_message, len(conversation_history))
validated = validate_ai_response(parsed)
return validated.model_dump()
def _simulate_specialty_response(self, session, specialty, user_message, turn_count=0):
stage = session.stage
code = specialty.get("code", "general")
lang = (session.language or "ta-IN").lower()
msg_lower = (user_message or "").lower().strip()
# Broad negative word matching across Indian languages & dialects
negative_keywords = [
"no", "no more", "nothing", "nothing else", "none", "no illness", "no problem",
"இல்லை", "இல்லைங்க", "இல்ல", "ஒன்றுமில்லை", "ஒன்னுமில்ல", "ஏதுமில்லை",
"नहीं", "कुछ नहीं", "कोई नहीं", "नाही",
"లేదు", "ఏమీ లేదు", "లేదండి",
"ಇಲ್ಲ", "ಇಲ್ಲವೇ ಇಲ್ಲ", "ಏನೂ ಇಲ್ಲ",
"ഇല്ല", "ഒന്നുമില്ല", "ഇല്ല കട്ടായം",
"না", "কিছু না", "নাই",
"नाही", "काही नाही",
"નથી", "કાંઈ નથી",
"ਨਹੀਂ", "ਕੁਝ ਨਹੀਂ"
]
is_negative = any(k in msg_lower for k in negative_keywords)
# Localized clinical phrases (Spoken & Caring Tone)
if lang.startswith("ta"):
conclusion_text = "மிக்க நன்றி. உங்கள் உடல்நல விவரங்கள் சிறப்பாக பதிவு செய்யப்பட்டுள்ளன. மருத்துவர் விரைவில் உங்களைப் பரிசீலிப்பார்."
symptom_q = "சரிங்க, உங்களோட அறிகுறிகள் பற்றி சொன்னீங்க. இந்த பிரச்சனை எத்தனை நாளா இருக்கு? இதுக்காக ஏதாச்சும் மாத்திரை சாப்பிட்டீங்களா?"
med_q = "சரிங்க. உங்களுக்கு வேற ஏதேனும் உடம்பு பிரச்சனைகள் அல்லது மாத்திரை ஒவ்வாமை (Allergy) இருக்கா?"
elif lang.startswith("hi"):
conclusion_text = "धन्यवाद। आपकी स्वास्थ्य जानकारी सफलतापूर्वक दर्ज कर ली गई है। डॉक्टर जल्द ही आपकी समीक्षा करेंगे।"
symptom_q = "जी समझ गया। आपको यह समस्या कितने दिनों से है और क्या इसके लिए आपने कोई दवाई ली है?"
med_q = "ठीक है। क्या आपको किसी दवाई से एलर्जी या कोई अन्य बीमारी है?"
elif lang.startswith("te"):
conclusion_text = "చాలా ధన్యవాదాలు. మీ ఆరోగ్య వివరాలు నమోదు చేయబడ్డాయి. వైద్యులు త్వరలోనే పరిశీలిస్తారు."
symptom_q = "సరేనండి, ఈ సమస్య మీకు ఎన్ని రోజుల నుండి ఉంది? దీని కోసం ఏవైనా మందులు వాడారా?"
med_q = "ధన్యవాదాలు. మీకు ఏవైనా మందుల పడనితనం (Allergy) లేదా ఇతర ఆరోగ్య సమస్యలు ఉన్నాయా?"
elif lang.startswith("kn"):
conclusion_text = "ತುಂಬಾ ಧನ್ಯವಾದಗಳು. ನಿಮ್ಮ ಆರೋಗ್ಯದ ಮಾಹಿತಿ ದಾಖಲಾಗಿದೆ. ವೈದ್ಯರು ಶೀಘ್ರದಲ್ಲೇ ಪರಿಶೀಲಿಸಲಿದ್ದಾರೆ."
symptom_q = "ಸರಿ, ಈ ತೊಂದರೆ ನಿಮಗೆ ಎಷ್ಟು ದಿನಗಳಿಂದ ಇದೆ? ಯಾವುದಾದರೂ ಮಾತ್ರೆ ತೆಗೆದುಕೊಂಡಿದ್ದೀರಾ?"
med_q = "ಧನ್ಯವಾದಗಳು. ನಿಮಗೆ ಯಾವುದಾದರೂ ಔಷಧಿ ಅಲರ್ಜಿ (Allergy) ಅಥವಾ ಇತರ ಆರೋಗ್ಯ ಸಮಸ್ಯೆ ಇದೆಯೇ?"
elif lang.startswith("ml"):
conclusion_text = "വളരെ നന്ദി. താങ്കളുടെ വിവരങ്ങൾ രേഖപ്പെടുത്തിയിട്ടുണ്ട്. ഡോക്ടർ ഉടൻ പരിശോധിക്കുന്നതാണ്."
symptom_q = "ശരി, ഈ ലക്ഷണങ്ങൾ എത്ര ദിവസമായിട്ടുണ്ട്? ഇതിനായി എന്തെങ്കിലും മരുന്ന് കഴിച്ചിട്ടുണ്ടോ?"
med_q = "നന്ദി. താങ്കൾക്ക് എന്തെങ്കിലും മരുന്ന് അലർജിയോ മറ്റ് ആരോഗ്യ പ്രശ്നങ്ങളോ ഉണ്ടോ?"
elif lang.startswith("bn"):
conclusion_text = "অনেক ধন্যবাদ। আপনার স্বাস্থ্য সম্পর্কিত তথ্য জমা নেওয়া হয়েছে। চিকিৎসক শীঘ্রই পর্যালোচনা করবেন।"
symptom_q = "ঠিক আছে, এই সমস্যা আপনার কত দিন ধরে হচ্ছে? এর জন্য কোনো ওষুধ খেয়েছেন কি?"
med_q = "ধন্যবাদ। আপনার কি কোনো ওষুধে অ্যালার্জি বা অন্য কোনো রোগ আছে?"
elif lang.startswith("mr"):
conclusion_text = "खूप खूप धन्यवाद. आपली आरोग्य माहिती नोंदवली गेली आहे. डॉक्टर लवकरच तपासणी करतील."
symptom_q = "होय, हा त्रास तुम्हाला किती दिवसांपासून होत आहे आणि काही औषध घेतले आहे का?"
med_q = "धन्यवाद. आपल्याला काही औषधांची ॲलर्जी किंवा इतर कोणताही आजार आहे का?"
elif lang.startswith("gu"):
conclusion_text = "ખૂબ ખૂબ આભાર. આપની આરોગ્ય વિગતો નોંધાઈ ગઈ છે. ડોક્ટર જલ્દી તપાસ કરશે."
symptom_q = "બરાબર, આ તકલીફ તમને કેટલા દિવસથી છે અને કોઈ દવા લીધી છે?"
med_q = "આભાર. તમને કોઈ દવાની એલર્જી કે અન્ય કોઈ બીમારી છે?"
elif lang.startswith("pa"):
conclusion_text = "ਬਹੁਤ ਧੰਨਵਾਦ। ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਦਰਜ ਕਰ ਲਈ ਗਈ ਹੈ। ਡਾਕਟਰ ਜਲਦੀ ਹੀ ਜਾਂਚ ਕਰਨਗੇ।"
symptom_q = "ਜੀ ਠੀਕ ਹੈ, ਇਹ ਸਮੱਸਿਆ ਤੁਹਾਨੂੰ ਕਿੰਨੇ ਦਿਨਾਂ ਤੋਂ ਹੈ ਅਤੇ ਕੀ ਕੋਈ ਦਵਾਈ ਲਈ ਹੈ?"
med_q = "ਧੰਨਵਾਦ। ਕੀ ਤੁਹਾਨੂੰ ਕਿਸੇ ਦਵਾਈ ਤੋਂ ਐਲਰਜੀ ਜਾਂ ਕੋਈ ਹੋਰ ਬੀਮਾਰੀ ਹੈ?"
else:
conclusion_text = "Thank you. I have recorded your intake details for the doctor to review."
symptom_q = "How long have you had these symptoms, and have you taken any medicines?"
med_q = "Thank you. Do you have any known drug allergies or existing health conditions?"
# Fast conclusion if patient says "No" or already had 6 turns
if is_negative or turn_count >= 6:
return {
"reply": conclusion_text,
"next_stage": "confirmation",
"state_updates": {
"reason_for_visit": None,
"symptoms": [],
"medical_history": ["None reported"] if is_negative else [],
"medications": [],
"allergies": ["None"] if is_negative else []
},
"completed": True
}
if stage == "greeting":
return {
"reply": symptom_q,
"next_stage": "reason_for_visit",
"state_updates": {
"reason_for_visit": user_message,
"symptoms": [{"name": user_message, "duration": "recent"}],
"medical_history": [],
"medications": [],
"allergies": []
},
"completed": False
}
elif stage == "reason_for_visit":
return {
"reply": med_q,
"next_stage": "medications",
"state_updates": {
"reason_for_visit": user_message,
"symptoms": [{"name": user_message, "duration": "reported"}],
"medical_history": [],
"medications": [],
"allergies": []
},
"completed": False
}
elif stage == "medications":
return {
"reply": conclusion_text,
"next_stage": "confirmation",
"state_updates": {
"reason_for_visit": None,
"symptoms": [],
"medical_history": [],
"medications": [user_message] if not is_negative else [],
"allergies": []
},
"completed": False
}
else:
return {
"reply": conclusion_text,
"next_stage": "confirmation",
"state_updates": {
"reason_for_visit": None,
"symptoms": [],
"medical_history": [],
"medications": [],
"allergies": ["None"] if is_negative else [user_message]
},
"completed": True
}