abdibrahem commited on
Commit
3214945
·
1 Parent(s): fec2827

Some updates

Browse files
Files changed (1) hide show
  1. main.py +348 -367
main.py CHANGED
@@ -73,17 +73,17 @@ class HealthcareChatbot:
73
  self.user_id = 'e2fe5655-d6ac-447d-8237-850413288561'
74
  self.max_retries = 3
75
  self.retry_delay = 2
76
-
77
  # Store conversation history
78
  self.conversation_history = []
79
  self.max_history_length = 10 # Keep last 10 exchanges
80
-
81
  # Initialize components
82
  self._initialize_language_tools()
83
  self._initialize_llm()
84
  self._initialize_parsers_and_chains()
85
  self._initialize_date_parser()
86
-
87
  print("Healthcare Chatbot initialized successfully!")
88
  self._print_welcome_message()
89
 
@@ -111,7 +111,7 @@ class HealthcareChatbot:
111
  try:
112
  self.embeddings = HuggingFaceEmbeddings(model_name="intfloat/multilingual-e5-large")
113
  self.language_classifier = pipeline(
114
- "text-classification",
115
  model="papluca/xlm-roberta-base-language-detection",
116
  top_k=1
117
  )
@@ -156,172 +156,172 @@ class HealthcareChatbot:
156
 
157
  # Intent classification prompt
158
  self.intent_classifier_template = PromptTemplate(
159
- template="""
160
- You are an intent classifier. Your job is simple: understand what the user wants and check if any API endpoint can do that.
161
 
162
- User Message: {user_query}
163
- Language: {detected_language}
164
- API Endpoints: {endpoints_documentation}
165
-
166
- Think step by step:
167
-
168
- 1. What does the user want from this message?
169
- Read the user's message carefully. What is the user trying to say or accomplish? What would a human understand from this message?
170
-
171
- 2. Can any API endpoint fulfill what the user wants?
172
- Look at each API endpoint. Does any endpoint do what the user is asking for? Be very precise - only say yes if there's a clear match.
173
-
174
- Important rules:
175
- - Focus ONLY on the current message, ignore conversation history for classification
176
- - If the user is just talking, being social, or saying something casual, that's CONVERSATION
177
- - Only choose API_ACTION if the user is clearly asking for something an API endpoint can do
178
- - When you're not sure, choose CONVERSATION
179
-
180
- Answer in this format:
181
- {{
182
- "intent": "API_ACTION" or "CONVERSATION",
183
- "confidence": [0.0 to 1.0],
184
- "reasoning": "What does the user want? Can any API do this?",
185
- "requires_backend": true or false
186
- }}
187
- """,
188
- input_variables=["user_query", "detected_language", "conversation_history", "endpoints_documentation"]
189
- )
190
 
 
191
 
 
 
192
 
 
 
193
 
194
- # API routing prompt (reuse existing router_prompt_template)
195
- self.router_prompt_template = PromptTemplate(
196
- template="""
197
- You are an expert API routing assistant with deep analytical capabilities. Your role is to thoroughly understand user intentions and precisely match them with the most appropriate API endpoint after comprehensive analysis.
 
198
 
199
- === CURRENT CONTEXT ===
200
- Current Date/Time: {current_datetime}
201
- Current Timezone: {timezone}
202
- User Location/Locale: {user_locale}
 
 
 
 
 
 
203
 
204
- === AVAILABLE ENDPOINTS ===
205
- {endpoints_documentation}
206
 
207
- === USER REQUEST DETAILS ===
208
- User Query: {user_query}
209
- Detected Language: {detected_language}
210
- Extracted Keywords: {extracted_keywords}
211
- Sentiment Analysis: {sentiment_analysis}
212
- Conversation History: {conversation_history}
213
 
214
- === COMPREHENSIVE ANALYSIS PROCESS ===
215
-
216
- PHASE 1: DEEP QUERY UNDERSTANDING
217
- Thoroughly analyze the user's request by examining:
218
- - PRIMARY INTENT: What is the core action the user wants to perform?
219
- - SECONDARY INTENTS: Are there multiple actions or follow-up implications?
220
- - ENTITY IDENTIFICATION: What specific resources/objects are mentioned?
221
- - OPERATION TYPE: Create, Read, Update, Delete, Search, List, Filter, Aggregate?
222
- - IMPLICIT CONTEXT: What assumptions or unstated requirements exist?
223
- - URGENCY/PRIORITY: Is this time-sensitive or routine?
224
- - SCOPE: Single item, multiple items, or system-wide operation?
225
-
226
- PHASE 2: ENDPOINTS DOCUMENTATION COMPREHENSION
227
- For EACH endpoint in the documentation, analyze:
228
- - PURPOSE AND FUNCTIONALITY: What business problem does this endpoint solve?
229
- - REQUIRED VS OPTIONAL PARAMETERS: What data is absolutely necessary?
230
- - INPUT DATA TYPES AND FORMATS: How should data be structured?
231
- - EXPECTED OUTPUT: What will this endpoint return?
232
- - USE CASES: When would this endpoint be the best choice?
233
- - CONSTRAINTS AND LIMITATIONS: What are the boundaries of this endpoint?
234
- - RELATIONSHIP TO OTHER ENDPOINTS: How does it fit in the overall API ecosystem?
235
-
236
- PHASE 3: SEMANTIC MATCHING AND SCORING
237
- For each potential endpoint match:
238
- - INTENT ALIGNMENT SCORE (0-100): How well does the endpoint's purpose match user intent?
239
- - PARAMETER AVAILABILITY SCORE (0-100): How much required data can be extracted/inferred?
240
- - CONTEXT RELEVANCE SCORE (0-100): How well does this fit the conversation context?
241
- - OPERATIONAL COMPLEXITY SCORE (0-100): How straightforward is this operation?
242
- - TOTAL MATCH SCORE: Weighted average of above scores
243
-
244
- PHASE 4: TEMPORAL AND CONTEXTUAL PROCESSING
245
- Handle time-related expressions with precision:
246
- - RELATIVE TIME CONVERSION:
247
- * Arabic: اليوم/today, غدا/tomorrow, أمس/yesterday, بعد/after, قبل/before
248
- * English: today, tomorrow, yesterday, next week, in 2 hours, etc.
249
- * Context-aware: "next appointment", "usual time", "same day"
250
- - ABSOLUTE TIME PARSING:
251
- * Date formats: DD/MM/YYYY, MM-DD-YYYY, YYYY-MM-DD
252
- * Time formats: 12-hour (AM/PM), 24-hour, relative (morning/afternoon)
253
- - TIMEZONE CONSIDERATIONS:
254
- * Convert all times to user's timezone
255
- * Account for daylight saving time if applicable
256
- * Provide ISO 8601 formatted output
257
-
258
- PHASE 5: PARAMETER EXTRACTION AND VALIDATION
259
- Extract and validate ALL parameters:
260
- - DIRECT EXTRACTION: Explicitly mentioned values in user query
261
- - CONTEXTUAL INFERENCE: Values derivable from conversation history
262
- - TYPE CONVERSION: Ensure proper data types (string, int, float, datetime, boolean)
263
- - FORMAT VALIDATION: Check against endpoint requirements
264
- - DEFAULT VALUES: Apply sensible defaults for optional parameters
265
- - MISSING PARAMETER IDENTIFICATION: Clearly identify what's missing and why it's needed
266
-
267
- PHASE 6: DECISION VALIDATION AND CONFIDENCE ASSESSMENT
268
- Before finalizing the decision:
269
- - SANITY CHECK: Does this endpoint actually solve the user's problem?
270
- - ALTERNATIVE CONSIDERATION: Are there better endpoint options?
271
- - COMPLETENESS VERIFICATION: Are all required parameters available or obtainable?
272
- - EDGE CASE EVALUATION: What could go wrong with this choice?
273
- - CONFIDENCE CALCULATION: How certain are you about this routing decision?
274
-
275
- === RESPONSE FORMAT ===
276
- Provide your comprehensive analysis and decision in this exact JSON structure:
277
-
278
- {{
279
- "reasoning": {{
280
- "user_intent": "Detailed description of what the user wants to accomplish, including primary and secondary goals",
281
- "temporal_analysis": "How dates/times were interpreted and converted with step-by-step calculations",
282
- "context_used": "Any context from conversation history that was applied, including entity persistence and implicit references",
283
- "endpoint_analysis": "Thorough evaluation of why each potential endpoint was considered or rejected, with scoring rationale",
284
- "selected_endpoint": "Detailed explanation of why this specific endpoint was chosen over all others",
285
- "parameter_mapping": "Comprehensive explanation of how user query maps to endpoint parameters, including extraction methods and confidence levels"
286
- }},
287
- "endpoint": "/exact_endpoint_path_from_documentation",
288
- "method": "HTTP_METHOD",
289
- "params": {{
290
- "required_param_1": "extracted_or_converted_value",
291
- "required_param_2": "extracted_or_converted_value",
292
- "optional_param": "value_if_applicable"
293
- }},
294
- "missing_required": ["list", "of", "missing", "required", "parameters"],
295
- "confidence": 0.95
296
- }}
297
-
298
- === CRITICAL EXCELLENCE STANDARDS ===
299
- 1. **ACCURACY FIRST**: Only route to endpoints that exist in the documentation
300
- 2. **NO FABRICATION**: Never assume parameters or capabilities not explicitly documented
301
- 3. **COMPLETE UNDERSTANDING**: Demonstrate deep comprehension of both query and endpoints
302
- 4. **TEMPORAL PRECISION**: Handle all time expressions with mathematical accuracy
303
- 5. **CONTEXT MASTERY**: Leverage conversation history intelligently and completely
304
- 6. **MULTILINGUAL COMPETENCY**: Handle Arabic, English, and mixed-language queries flawlessly
305
- 7. **PARAMETER COMPLETENESS**: Account for every required parameter or clearly identify gaps
306
- 8. **CONFIDENCE HONESTY**: Provide realistic confidence scores with clear reasoning
307
- 9. **EDGE CASE AWARENESS**: Consider what could go wrong and prepare for it
308
- 10. **DECISION TRANSPARENCY**: Make your reasoning process completely clear and auditable
309
-
310
- === ADVANCED CONTEXT HANDLING ===
311
- - **Pronoun Resolution**: "Cancel it" → identify what "it" refers to from history
312
- - **Implicit References**: "Same time tomorrow" → extract time from previous context
313
- - **Entity Persistence**: Remember patient IDs, appointment IDs across conversation turns
314
- - **Intent Continuation**: Understand when user is continuing a previous request
315
- - **Correction Handling**: Detect when user is correcting previous information
316
-
317
- Think methodically through each phase. Demonstrate deep understanding before making decisions. Be thorough in your analysis and transparent in your reasoning.
318
- """,
319
- input_variables=[
320
- "endpoints_documentation", "user_query", "detected_language",
321
- "extracted_keywords", "sentiment_analysis", "conversation_history",
322
- "current_datetime", "timezone", "user_locale"
323
- ]
324
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  # self.router_prompt_template = PromptTemplate(
326
  # template="""
327
  # You are a precise API routing assistant. Your job is to analyze user queries and select the correct API endpoint with proper parameters.
@@ -448,162 +448,140 @@ class HealthcareChatbot:
448
  # API response formatting prompt (reuse existing user_response_template)
449
  # self.user_response_template = PromptTemplate(
450
  # template="""
451
- # You are a professional healthcare assistant. Generate clear, accurate responses using EXACT data from the system.
452
-
453
- # === STRICT REQUIREMENTS ===
454
- # - Respond ONLY in {detected_language}
455
- # - Use EXACT information from api_response - NO modifications
456
- # - Keep responses SHORT, SIMPLE, and DIRECT
457
- # - Use professional healthcare tone
458
- # - NEVER mix languages or make up information
459
 
460
- # === ORIGINAL REQUEST ===
461
  # User Query: {user_query}
462
  # User Sentiment: {sentiment_analysis}
 
463
 
464
- # === SYSTEM DATA ===
465
  # {api_response}
466
 
467
- # === LANGUAGE-SPECIFIC FORMATTING ===
468
-
469
- # FOR ARABIC RESPONSES:
470
- # - Use Modern Standard Arabic (الفصحى)
471
- # - Use Arabic numerals: ١، ٢، ٣، ٤، ٥، ٦، ٧، ٨، ٩، ١٠
472
- # - Time format: "من الساعة ٨:٠٠ صباحاً إلى ٥:٠٠ مساءً"
473
- # - Date format: "١٥ مايو ٢٠٢٥"
474
- # - Use proper Arabic medical terminology
475
- # - Keep sentences short and grammatically correct
476
- # - Example format for hospitals:
477
- # "مستشفى [الاسم] - العنوان: [العنوان الكامل] - أوقات العمل: من [الوقت] إلى [الوقت]"
478
-
479
- # FOR ENGLISH RESPONSES:
480
- # - Use clear, professional language
481
- # - Time format: "8:00 AM to 5:00 PM"
482
- # - Date format: "May 15, 2025"
483
- # - Keep sentences concise and direct
484
- # - Example format for hospitals:
485
- # "[Hospital Name] - Address: [Full Address] - Hours: [Opening Time] to [Closing Time]"
486
-
487
- # === RESPONSE STRUCTURE ===
488
- # 1. Direct answer to the user's question
489
- # 2. Essential details only (names, addresses, hours, contact info)
490
- # 3. Brief helpful note if needed
491
- # 4. No unnecessary introductions or conclusions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
 
493
  # === CRITICAL RULES ===
494
- # - Extract information EXACTLY as provided in api_response
495
- # - Do NOT include technical URLs, IDs, or system codes in the response
496
- # - Do NOT show raw links or booking URLs to users
497
- # - Present information in natural, conversational language
498
- # - Do NOT use bullet points or technical formatting
499
- # - Write as if you're speaking to the patient directly
500
- # - If data is missing, state "المعلومات غير متوفرة" (Arabic) or "Information not available" (English)
501
- # - Convert technical data into human-readable format
502
- # - NEVER add translations or explanations in other languages
503
- # - NEVER include "Translated response" or similar phrases
504
- # - END your response immediately after providing the requested information
505
- # - Do NOT add any English translation when responding in Arabic
506
- # - Do NOT add any Arabic translation when responding in English
507
-
508
- # === HUMAN-LIKE FORMATTING RULES ===
509
- # FOR ARABIC:
510
- # - Instead of "رابط الحجز: [URL]" → say "تم حجز موعدك بنجاح"
511
- # - Instead of "الأزمة: غير متوفرة" → omit or say "بدون أعراض محددة"
512
- # - Use natural sentences like "موعدك مع الدكتور [Name] يوم [Date] في تمام الساعة [Time]"
513
- # - Avoid technical terms and system language
514
-
515
- # FOR ENGLISH:
516
- # - Instead of "Booking URL: [link]" → say "Your appointment has been scheduled"
517
- # - Use natural sentences like "You have an appointment with Dr. [Name] on [Date] at [Time]"
518
- # - Avoid showing raw URLs, IDs, or technical data
519
-
520
- # === QUALITY CHECKS ===
521
- # Before responding, verify:
522
- # ✓ Response sounds natural and conversational
523
- # ✓ No technical URLs, IDs, or system codes are shown
524
- # ✓ Information is presented in human-friendly language
525
- # ✓ Grammar is correct in the target language
526
- # ✓ Response directly answers the user's question
527
- # ✓ No bullet points or technical formatting
528
- # ✓ Sounds like a helpful human assistant, not a system
529
-
530
- # Generate a response that is accurate, helpful, and professionally formatted.
531
-
532
- # === FINAL INSTRUCTION ===
533
- # Respond ONLY in the requested language. Do NOT provide translations, explanations, or additional text in any other language. Stop immediately after answering the user's question.
534
  # """,
535
  # input_variables=["user_query", "api_response", "detected_language", "sentiment_analysis"]
536
  # )
537
  self.user_response_template = PromptTemplate(
538
- template="""
539
- You are a professional healthcare assistant. Answer the user's question using the provided API data.
540
-
541
- User Query: {user_query}
542
- User Sentiment: {sentiment_analysis}
543
- Response Language: {detected_language}
544
-
545
- API Response Data:
546
- {api_response}
547
-
548
- === INSTRUCTIONS ===
549
-
550
- 1. Read and understand the API response data above
551
- 2. Use ONLY the actual data from the API response - never make up information
552
- 3. Respond in {detected_language} language only
553
- 4. Write like you're talking to a friend or family member - warm, friendly, and caring
554
- 5. Make it sound natural and conversational, not like a system message
555
- 6. Convert technical data to simple, everyday language
556
-
557
- === DATE AND TIME FORMATTING ===
558
-
559
- When you see date_time fields like '2025-05-30T10:28:10':
560
- - For English: Convert to "May 30, 2025 at 10:28 AM"
561
- - For Arabic: Convert to "٣٠ مايو ٢٠٢٥ في الساعة ١٠:٢٨ صباحاً"
562
-
563
- === RESPONSE EXAMPLES ===
564
-
565
- For appointment confirmations:
566
- - English: "Great! I've got your appointment set up for May 30, 2025 at 10:28 AM. Everything looks good!"
567
- - Arabic: "ممتاز! موعدك محجوز يوم ٣٠ مايو ٢٠٢٥ الساعة ١٠:٢٨ صباحاً. كل شيء جاهز!"
568
-
569
- For appointment info:
570
- - English: "Your next appointment is on May 30, 2025 at 10:28 AM. See you then!"
571
- - Arabic: "موعدك القادم يوم ٣٠ مايو ٢٠٢٥ الساعة ١٠:٢٨ صباحاً. نراك قريباً!"
572
-
573
- === TONE GUIDELINES ===
574
- - Use friendly words like: "Great!", "Perfect!", "All set!", "ممتاز!", "رائع!", "تمام!"
575
- - Add reassuring phrases: "Everything looks good", "You're all set", "كل شيء جاهز", "تم بنجاح"
576
- - Sound helpful and caring, not robotic or formal
577
-
578
- === LANGUAGE FORMATTING ===
579
-
580
- For Arabic responses:
581
- - Use Arabic numerals: ٠١٢٣٤٥٦٧٨٩
582
- - Use Arabic month names: يناير، فبراير، مارس، أبريل، مايو، يونيو، يوليو، أغسطس، سبتمبر، أكتوبر، نوفمبر، ديسمبر
583
- - Friendly, warm Arabic tone
584
-
585
- For English responses:
586
- - Use standard English numerals
587
- - 12-hour time format with AM/PM
588
- - Friendly, conversational English tone
589
-
590
- === CRITICAL RULES ===
591
- - Extract dates and times exactly as they appear in the API response
592
- - Never use example dates or placeholder information
593
- - Respond only in the specified language
594
- - Make your response sound like a helpful friend, not a computer
595
- - Focus on answering the user's specific question with warmth and care
596
-
597
- Generate a friendly, helpful response using the API data provided above.
598
- """,
599
- input_variables=["user_query", "api_response", "detected_language", "sentiment_analysis"]
600
- )
 
601
 
602
  # Create chains
603
  self.intent_chain = LLMChain(llm=self.llm, prompt=self.intent_classifier_template)
604
  self.router_chain = LLMChain(llm=self.llm, prompt=self.router_prompt_template)
605
  self.conversation_chain = LLMChain(llm=self.llm, prompt=self.conversation_template)
606
  self.api_response_chain = LLMChain(llm=self.llm, prompt=self.user_response_template)
 
607
  def detect_language(self, text):
608
  """Detect language of the input text"""
609
  if self.language_classifier and len(text.strip()) > 3:
@@ -611,7 +589,7 @@ class HealthcareChatbot:
611
  result = self.language_classifier(text)
612
  detected_lang = result[0][0]['label']
613
  confidence = result[0][0]['score']
614
-
615
  if detected_lang in ['ar', 'arabic']:
616
  return "arabic"
617
  elif detected_lang in ['en', 'english']:
@@ -620,12 +598,12 @@ class HealthcareChatbot:
620
  return "english" # Default to English for unsupported languages
621
  except:
622
  pass
623
-
624
  # Fallback: Basic Arabic detection
625
  arabic_pattern = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF]+')
626
  if arabic_pattern.search(text):
627
  return "arabic"
628
-
629
  return "english"
630
 
631
  def analyze_sentiment(self, text):
@@ -639,7 +617,7 @@ class HealthcareChatbot:
639
  }
640
  except:
641
  pass
642
-
643
  return {"sentiment": "NEUTRAL", "score": 0.5}
644
 
645
  def extract_keywords(self, text):
@@ -655,12 +633,12 @@ class HealthcareChatbot:
655
  """Get recent conversation history as context"""
656
  if not self.conversation_history:
657
  return "No previous conversation"
658
-
659
  context = []
660
  for item in self.conversation_history[-3:]: # Last 3 exchanges
661
  context.append(f"User: {item['user_message']}")
662
  context.append(f"Bot: {item['bot_response'][:100]}...") # Truncate long responses
663
-
664
  return " | ".join(context)
665
 
666
  def add_to_history(self, user_message, bot_response, response_type):
@@ -671,7 +649,7 @@ class HealthcareChatbot:
671
  'bot_response': bot_response,
672
  'response_type': response_type
673
  })
674
-
675
  # Keep only recent history
676
  if len(self.conversation_history) > self.max_history_length:
677
  self.conversation_history = self.conversation_history[-self.max_history_length:]
@@ -685,14 +663,14 @@ class HealthcareChatbot:
685
  "conversation_history": self.get_conversation_context(),
686
  "endpoints_documentation": json.dumps(self.endpoints_documentation, indent=2)
687
  })
688
-
689
  # Parse the JSON response
690
  intent_text = result["text"]
691
  # Clean and parse JSON
692
  cleaned_response = re.sub(r'//.*?$', '', intent_text, flags=re.MULTILINE)
693
  cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
694
  cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
695
-
696
  try:
697
  intent_data = json.loads(cleaned_response)
698
  return intent_data
@@ -728,9 +706,9 @@ class HealthcareChatbot:
728
  "sentiment_analysis": json.dumps(sentiment_result),
729
  "conversation_history": self.get_conversation_context()
730
  })
731
-
732
  return result["text"].strip()
733
-
734
  except Exception as e:
735
  # Fallback response
736
  if detected_language == "arabic":
@@ -746,12 +724,13 @@ class HealthcareChatbot:
746
 
747
  print('Sending the api request')
748
  print(f"🔗 Making API call to {endpoint_method} {self.BASE_URL + endpoint_url} with params: {endpoint_params}")
749
-
750
  # Inject patient_id if needed
751
  if 'patient_id' in endpoint_params:
752
  endpoint_params['patient_id'] = self.user_id
753
-
754
  retries = 0
 
755
  while retries < self.max_retries:
756
  try:
757
  if endpoint_method.upper() == 'GET':
@@ -769,10 +748,11 @@ class HealthcareChatbot:
769
  headers=self.headers,
770
  timeout=10
771
  )
772
-
773
  response.raise_for_status()
 
774
  return response.json()
775
-
776
  except requests.exceptions.RequestException as e:
777
  retries += 1
778
  if retries >= self.max_retries:
@@ -781,35 +761,35 @@ class HealthcareChatbot:
781
  "details": str(e),
782
  "status_code": getattr(e.response, 'status_code', None) if hasattr(e, 'response') else None
783
  }
784
-
785
  time.sleep(self.retry_delay)
786
  def parse_relative_date(self, text, detected_language):
787
  """
788
  Parse relative dates from text using a combination of methods
789
  """
790
  today = datetime.now()
791
-
792
  # Handle common relative date patterns in English and Arabic
793
  tomorrow_patterns = {
794
  'english': [r'\btomorrow\b', r'\bnext day\b'],
795
  'arabic': [r'\bغدا\b', r'\bبكرة\b', r'\bغدًا\b', r'\bالغد\b']
796
  }
797
-
798
  next_week_patterns = {
799
  'english': [r'\bnext week\b'],
800
  'arabic': [r'\bالأسبوع القادم\b', r'\bالأسبوع المقبل\b', r'\bالاسبوع الجاي\b']
801
  }
802
-
803
  # Check for "tomorrow" patterns
804
  for pattern in tomorrow_patterns.get(detected_language, []) + tomorrow_patterns.get('english', []):
805
  if re.search(pattern, text, re.IGNORECASE):
806
  return (today + timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%S')
807
-
808
  # Check for "next week" patterns
809
  for pattern in next_week_patterns.get(detected_language, []) + next_week_patterns.get('english', []):
810
  if re.search(pattern, text, re.IGNORECASE):
811
  return (today + timedelta(days=7)).strftime('%Y-%m-%dT%H:%M:%S')
812
-
813
  # If NER model is available, use it to extract date entities
814
  if self.date_parser and detected_language == 'english':
815
  try:
@@ -823,7 +803,7 @@ class HealthcareChatbot:
823
  return (today + timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%S')
824
  except Exception as e:
825
  print(f"Error in date parsing: {e}")
826
-
827
  # Default return None if no date pattern is recognized
828
  return None
829
 
@@ -831,11 +811,11 @@ class HealthcareChatbot:
831
  def handle_api_action(self, user_query, detected_language, sentiment_result, keywords):
832
  """Handle API-based actions"""
833
  try:
834
-
835
- parsed_date = self.parse_relative_date(user_query, detected_language)
836
- if parsed_date:
837
- print(f"Parsed relative date: {parsed_date}")
838
-
839
  # Route the query to determine API endpoint
840
  router_result = self.router_chain.invoke({
841
  "endpoints_documentation": json.dumps(self.endpoints_documentation, indent=2),
@@ -843,15 +823,18 @@ class HealthcareChatbot:
843
  "detected_language": detected_language,
844
  "extracted_keywords": ", ".join(keywords),
845
  "sentiment_analysis": json.dumps(sentiment_result),
846
- "conversation_history": self.get_conversation_context()
 
 
 
847
  })
848
-
849
  # Parse router response
850
  route_text = router_result["text"]
851
  # cleaned_response = re.sub(r'//.*?$', '', route_text, flags=re.MULTILINE)
852
  # cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
853
  # cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
854
-
855
  # try:
856
  # parsed_route = json.loads(cleaned_response)
857
  # except json.JSONDecodeError:
@@ -860,17 +843,17 @@ class HealthcareChatbot:
860
  # parsed_route = json.loads(json_match.group(0))
861
  # else:
862
  # raise ValueError("Could not parse routing response")
863
-
864
  # print(f"🔍 Parsed route: {parsed_route}")
865
  cleaned_response = route_text
866
-
867
  # Remove any comments (both single-line and multi-line)
868
  cleaned_response = re.sub(r'//.*?$', '', cleaned_response, flags=re.MULTILINE)
869
  cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
870
-
871
  # Remove any trailing commas
872
  cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
873
-
874
  # Try different methods to parse the JSON response
875
  try:
876
  # First attempt: direct JSON parsing of cleaned response
@@ -896,27 +879,27 @@ class HealthcareChatbot:
896
  print(f"Failed to parse JSON. Raw response: {route_text}")
897
  print(f"Cleaned response: {cleaned_response}")
898
  raise ValueError("Could not extract valid JSON from LLM response")
899
-
900
  if not parsed_route:
901
  raise ValueError("Failed to parse LLM response into valid JSON")
902
-
903
  # Replace any placeholder values and inject parsed dates if available
904
  if 'params' in parsed_route:
905
  if 'patient_id' in parsed_route['params']:
906
  parsed_route['params']['patient_id'] = self.user_id
907
-
908
  # Inject parsed date if available and a date parameter exists
909
- date_params = ['appointment_date', 'date', 'schedule_date', 'date_time', 'new_date_time']
910
- if parsed_date:
911
- for param in date_params:
912
- if param in parsed_route['params']:
913
- parsed_route['params'][param] = parsed_date
914
-
915
  print('Parsed route: ', parsed_route)
916
 
917
  # Make backend API call
918
  api_response = self.backend_call(parsed_route)
919
-
920
  print("🔗 API response received:", api_response)
921
  # Generate user-friendly response
922
  user_response_result = self.api_response_chain.invoke({
@@ -927,20 +910,20 @@ class HealthcareChatbot:
927
  })
928
 
929
  print("🔗 API response:", user_response_result["text"].strip())
930
-
931
  return {
932
  "response": user_response_result["text"].strip(),
933
  "api_data": api_response,
934
  "routing_info": parsed_route
935
  }
936
-
937
  except Exception as e:
938
  # Fallback error response
939
  if detected_language == "arabic":
940
  error_msg = "أعتذر، لم أتمكن من معالجة طلبك. يرجى المحاولة مرة أخرى أو صياغة السؤال بطريقة مختلفة."
941
  else:
942
  error_msg = "I apologize, I couldn't process your request. Please try again or rephrase your question."
943
-
944
  return {
945
  "response": error_msg,
946
  "api_data": {"error": str(e)},
@@ -950,7 +933,7 @@ class HealthcareChatbot:
950
  def chat(self, user_message: str) -> ChatResponse:
951
  """Main chat method that handles user messages"""
952
  start_time = time.time()
953
-
954
  # Check for exit commands
955
  exit_commands = ['quit', 'exit', 'bye', 'خروج', 'وداعا', 'مع السلامة']
956
  if user_message.lower().strip() in exit_commands:
@@ -960,19 +943,19 @@ class HealthcareChatbot:
960
  message="Goodbye! Take care of your health! / وداعاً! اعتن بصحتك!",
961
  language="bilingual"
962
  )
963
-
964
  try:
965
  # Language detection and analysis
966
  detected_language = self.detect_language(user_message)
967
  sentiment_result = self.analyze_sentiment(user_message)
968
  keywords = self.extract_keywords(user_message)
969
-
970
  print(f"🔍 Language: {detected_language} | Sentiment: {sentiment_result['sentiment']} | Keywords: {keywords}")
971
-
972
  # Classify intent
973
  intent_data = self.classify_intent(user_message, detected_language)
974
  print(f"🎯 Intent: {intent_data['intent']} (confidence: {intent_data.get('confidence', 'N/A')})")
975
-
976
  # Handle based on intent
977
  if intent_data["intent"] == "API_ACTION" and intent_data.get("requires_backend", False):
978
  # Handle API-based actions
@@ -980,7 +963,7 @@ class HealthcareChatbot:
980
  action_result = self.handle_api_action(user_message, detected_language, sentiment_result, keywords)
981
 
982
  # print(action_result)
983
-
984
  response = ChatResponse(
985
  response_id=f"resp_{int(time.time())}",
986
  response_type="api_action",
@@ -989,12 +972,12 @@ class HealthcareChatbot:
989
  api_data=json.dumps(action_result["api_data"]) if 'action_result' in action_result else None,
990
  language=detected_language
991
  )
992
-
993
  else:
994
  # Handle conversational responses
995
  print("💬 Processing conversational response...")
996
  conv_response = self.handle_conversation(user_message, detected_language, sentiment_result)
997
-
998
  response = ChatResponse(
999
  response_id=f"resp_{int(time.time())}",
1000
  response_type="conversation",
@@ -1002,17 +985,17 @@ class HealthcareChatbot:
1002
  api_call_made=False,
1003
  language=detected_language
1004
  )
1005
-
1006
  # Add to conversation history
1007
  self.add_to_history(user_message, response.message, response.response_type)
1008
-
1009
  print(f"⏱️ Processing time: {time.time() - start_time:.2f}s")
1010
  return response
1011
-
1012
  except Exception as e:
1013
  print(f"❌ Error in chat processing: {e}")
1014
  error_msg = "I apologize for the technical issue. Please try again. / أعتذر عن المشكلة التقنية. يرجى المحاولة مرة أخرى."
1015
-
1016
  return ChatResponse(
1017
  response_id=f"resp_{int(time.time())}",
1018
  response_type="conversation",
@@ -1024,41 +1007,39 @@ class HealthcareChatbot:
1024
  def start_interactive_chat(self):
1025
  """Start an interactive chat session"""
1026
  print("🚀 Starting interactive chat session...")
1027
-
1028
  while True:
1029
  try:
1030
  # Get user input
1031
  user_input = input("\n👤 You: ").strip()
1032
-
1033
  if not user_input:
1034
  continue
1035
-
1036
  # Process the message
1037
  print("🤖 Processing...")
1038
  response = self.chat(user_input)
1039
-
1040
  # Display response
1041
  print(f"\n🏥 Healthcare Bot: {response.message}")
1042
-
1043
  # Show additional info if API call was made
1044
  if response.api_call_made and response.api_data:
1045
  if "error" not in response.api_data:
1046
  print("✅ Successfully retrieved information from healthcare system")
1047
  else:
1048
  print("⚠️ There was an issue accessing the healthcare system")
1049
-
1050
  # Check for exit
1051
  if "Goodbye" in response.message or "وداعاً" in response.message:
1052
  break
1053
-
1054
  except KeyboardInterrupt:
1055
  print("\n\n👋 Chat session ended. Goodbye!")
1056
  break
1057
  except Exception as e:
1058
  print(f"\n❌ Unexpected error: {e}")
1059
  print("The chat session will continue...")
1060
-
1061
-
1062
  # Create a simple function to start the chatbot
1063
  # def start_healthcare_chatbot():
1064
  # """Initialize and start the healthcare chatbot"""
 
73
  self.user_id = 'e2fe5655-d6ac-447d-8237-850413288561'
74
  self.max_retries = 3
75
  self.retry_delay = 2
76
+
77
  # Store conversation history
78
  self.conversation_history = []
79
  self.max_history_length = 10 # Keep last 10 exchanges
80
+
81
  # Initialize components
82
  self._initialize_language_tools()
83
  self._initialize_llm()
84
  self._initialize_parsers_and_chains()
85
  self._initialize_date_parser()
86
+
87
  print("Healthcare Chatbot initialized successfully!")
88
  self._print_welcome_message()
89
 
 
111
  try:
112
  self.embeddings = HuggingFaceEmbeddings(model_name="intfloat/multilingual-e5-large")
113
  self.language_classifier = pipeline(
114
+ "text-classification",
115
  model="papluca/xlm-roberta-base-language-detection",
116
  top_k=1
117
  )
 
156
 
157
  # Intent classification prompt
158
  self.intent_classifier_template = PromptTemplate(
159
+ template="""
160
+ You are an intent classifier. Your job is simple: understand what the user wants and check if any API endpoint can do that.
161
 
162
+ User Message: {user_query}
163
+ Language: {detected_language}
164
+ API Endpoints: {endpoints_documentation}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
+ Think step by step:
167
 
168
+ 1. What does the user want from this message?
169
+ Read the user's message carefully. What is the user trying to say or accomplish? What would a human understand from this message?
170
 
171
+ 2. Can any API endpoint fulfill what the user wants?
172
+ Look at each API endpoint. Does any endpoint do what the user is asking for? Be very precise - only say yes if there's a clear match.
173
 
174
+ Important rules:
175
+ - Focus ONLY on the current message, ignore conversation history for classification
176
+ - If the user is just talking, being social, or saying something casual, that's CONVERSATION
177
+ - Only choose API_ACTION if the user is clearly asking for something an API endpoint can do
178
+ - When you're not sure, choose CONVERSATION
179
 
180
+ Answer in this format:
181
+ {{
182
+ "intent": "API_ACTION" or "CONVERSATION",
183
+ "confidence": [0.0 to 1.0],
184
+ "reasoning": "What does the user want? Can any API do this?",
185
+ "requires_backend": true or false
186
+ }}
187
+ """,
188
+ input_variables=["user_query", "detected_language", "conversation_history", "endpoints_documentation"]
189
+ )
190
 
 
 
191
 
 
 
 
 
 
 
192
 
193
+
194
+ # API routing prompt (reuse existing router_prompt_template)
195
+ self.router_prompt_template = PromptTemplate(
196
+ template="""
197
+ You are an expert API routing assistant with deep analytical capabilities. Your role is to thoroughly understand user intentions and precisely match them with the most appropriate API endpoint after comprehensive analysis.
198
+
199
+ === CURRENT CONTEXT ===
200
+ Current Date/Time: {current_datetime}
201
+ Current Timezone: {timezone}
202
+ User Location/Locale: {user_locale}
203
+
204
+ === AVAILABLE ENDPOINTS ===
205
+ {endpoints_documentation}
206
+
207
+ === USER REQUEST DETAILS ===
208
+ User Query: {user_query}
209
+ Detected Language: {detected_language}
210
+ Extracted Keywords: {extracted_keywords}
211
+ Sentiment Analysis: {sentiment_analysis}
212
+ Conversation History: {conversation_history}
213
+
214
+ === COMPREHENSIVE ANALYSIS PROCESS ===
215
+
216
+ PHASE 1: DEEP QUERY UNDERSTANDING
217
+ Thoroughly analyze the user's request by examining:
218
+ - PRIMARY INTENT: What is the core action the user wants to perform?
219
+ - SECONDARY INTENTS: Are there multiple actions or follow-up implications?
220
+ - ENTITY IDENTIFICATION: What specific resources/objects are mentioned?
221
+ - OPERATION TYPE: Create, Read, Update, Delete, Search, List, Filter, Aggregate?
222
+ - IMPLICIT CONTEXT: What assumptions or unstated requirements exist?
223
+ - URGENCY/PRIORITY: Is this time-sensitive or routine?
224
+ - SCOPE: Single item, multiple items, or system-wide operation?
225
+
226
+ PHASE 2: ENDPOINTS DOCUMENTATION COMPREHENSION
227
+ For EACH endpoint in the documentation, analyze:
228
+ - PURPOSE AND FUNCTIONALITY: What business problem does this endpoint solve?
229
+ - REQUIRED VS OPTIONAL PARAMETERS: What data is absolutely necessary?
230
+ - INPUT DATA TYPES AND FORMATS: How should data be structured?
231
+ - EXPECTED OUTPUT: What will this endpoint return?
232
+ - USE CASES: When would this endpoint be the best choice?
233
+ - CONSTRAINTS AND LIMITATIONS: What are the boundaries of this endpoint?
234
+ - RELATIONSHIP TO OTHER ENDPOINTS: How does it fit in the overall API ecosystem?
235
+
236
+ PHASE 3: SEMANTIC MATCHING AND SCORING
237
+ For each potential endpoint match:
238
+ - INTENT ALIGNMENT SCORE (0-100): How well does the endpoint's purpose match user intent?
239
+ - PARAMETER AVAILABILITY SCORE (0-100): How much required data can be extracted/inferred?
240
+ - CONTEXT RELEVANCE SCORE (0-100): How well does this fit the conversation context?
241
+ - OPERATIONAL COMPLEXITY SCORE (0-100): How straightforward is this operation?
242
+ - TOTAL MATCH SCORE: Weighted average of above scores
243
+
244
+ PHASE 4: TEMPORAL AND CONTEXTUAL PROCESSING
245
+ Handle time-related expressions with precision:
246
+ - RELATIVE TIME CONVERSION:
247
+ * Arabic: اليوم/today, غدا/tomorrow, أمس/yesterday, بعد/after, قبل/before
248
+ * English: today, tomorrow, yesterday, next week, in 2 hours, etc.
249
+ * Context-aware: "next appointment", "usual time", "same day"
250
+ - ABSOLUTE TIME PARSING:
251
+ * Date formats: DD/MM/YYYY, MM-DD-YYYY, YYYY-MM-DD
252
+ * Time formats: 12-hour (AM/PM), 24-hour, relative (morning/afternoon)
253
+ - TIMEZONE CONSIDERATIONS:
254
+ * Convert all times to user's timezone
255
+ * Account for daylight saving time if applicable
256
+ * Provide ISO 8601 formatted output
257
+
258
+ PHASE 5: PARAMETER EXTRACTION AND VALIDATION
259
+ Extract and validate ALL parameters:
260
+ - DIRECT EXTRACTION: Explicitly mentioned values in user query
261
+ - CONTEXTUAL INFERENCE: Values derivable from conversation history
262
+ - TYPE CONVERSION: Ensure proper data types (string, int, float, datetime, boolean)
263
+ - FORMAT VALIDATION: Check against endpoint requirements
264
+ - DEFAULT VALUES: Apply sensible defaults for optional parameters
265
+ - MISSING PARAMETER IDENTIFICATION: Clearly identify what's missing and why it's needed
266
+
267
+ PHASE 6: DECISION VALIDATION AND CONFIDENCE ASSESSMENT
268
+ Before finalizing the decision:
269
+ - SANITY CHECK: Does this endpoint actually solve the user's problem?
270
+ - ALTERNATIVE CONSIDERATION: Are there better endpoint options?
271
+ - COMPLETENESS VERIFICATION: Are all required parameters available or obtainable?
272
+ - EDGE CASE EVALUATION: What could go wrong with this choice?
273
+ - CONFIDENCE CALCULATION: How certain are you about this routing decision?
274
+
275
+ === RESPONSE FORMAT ===
276
+ Provide your comprehensive analysis and decision in this exact JSON structure:
277
+
278
+ {{
279
+ "reasoning": {{
280
+ "user_intent": "Detailed description of what the user wants to accomplish, including primary and secondary goals",
281
+ "temporal_analysis": "How dates/times were interpreted and converted with step-by-step calculations",
282
+ "context_used": "Any context from conversation history that was applied, including entity persistence and implicit references",
283
+ "endpoint_analysis": "Thorough evaluation of why each potential endpoint was considered or rejected, with scoring rationale",
284
+ "selected_endpoint": "Detailed explanation of why this specific endpoint was chosen over all others",
285
+ "parameter_mapping": "Comprehensive explanation of how user query maps to endpoint parameters, including extraction methods and confidence levels"
286
+ }},
287
+ "endpoint": "/exact_endpoint_path_from_documentation",
288
+ "method": "HTTP_METHOD",
289
+ "params": {{
290
+ "required_param_1": "extracted_or_converted_value",
291
+ "required_param_2": "extracted_or_converted_value",
292
+ "optional_param": "value_if_applicable"
293
+ }},
294
+ "missing_required": ["list", "of", "missing", "required", "parameters"],
295
+ "confidence": 0.95
296
+ }}
297
+
298
+ === CRITICAL EXCELLENCE STANDARDS ===
299
+ 1. **ACCURACY FIRST**: Only route to endpoints that exist in the documentation
300
+ 2. **NO FABRICATION**: Never assume parameters or capabilities not explicitly documented
301
+ 3. **COMPLETE UNDERSTANDING**: Demonstrate deep comprehension of both query and endpoints
302
+ 4. **TEMPORAL PRECISION**: Handle all time expressions with mathematical accuracy
303
+ 5. **CONTEXT MASTERY**: Leverage conversation history intelligently and completely
304
+ 6. **MULTILINGUAL COMPETENCY**: Handle Arabic, English, and mixed-language queries flawlessly
305
+ 7. **PARAMETER COMPLETENESS**: Account for every required parameter or clearly identify gaps
306
+ 8. **CONFIDENCE HONESTY**: Provide realistic confidence scores with clear reasoning
307
+ 9. **EDGE CASE AWARENESS**: Consider what could go wrong and prepare for it
308
+ 10. **DECISION TRANSPARENCY**: Make your reasoning process completely clear and auditable
309
+
310
+ === ADVANCED CONTEXT HANDLING ===
311
+ - **Pronoun Resolution**: "Cancel it" → identify what "it" refers to from history
312
+ - **Implicit References**: "Same time tomorrow" → extract time from previous context
313
+ - **Entity Persistence**: Remember patient IDs, appointment IDs across conversation turns
314
+ - **Intent Continuation**: Understand when user is continuing a previous request
315
+ - **Correction Handling**: Detect when user is correcting previous information
316
+
317
+ Think methodically through each phase. Demonstrate deep understanding before making decisions. Be thorough in your analysis and transparent in your reasoning.
318
+ """,
319
+ input_variables=[
320
+ "endpoints_documentation", "user_query", "detected_language",
321
+ "extracted_keywords", "sentiment_analysis", "conversation_history",
322
+ "current_datetime", "timezone", "user_locale"
323
+ ]
324
+ )
325
  # self.router_prompt_template = PromptTemplate(
326
  # template="""
327
  # You are a precise API routing assistant. Your job is to analyze user queries and select the correct API endpoint with proper parameters.
 
448
  # API response formatting prompt (reuse existing user_response_template)
449
  # self.user_response_template = PromptTemplate(
450
  # template="""
451
+ # You are a professional healthcare assistant. Answer the user's question using the provided API data.
 
 
 
 
 
 
 
452
 
 
453
  # User Query: {user_query}
454
  # User Sentiment: {sentiment_analysis}
455
+ # Response Language: {detected_language}
456
 
457
+ # API Response Data:
458
  # {api_response}
459
 
460
+ # === INSTRUCTIONS ===
461
+
462
+ # 1. Read and understand the API response data above
463
+ # 2. Use ONLY the actual data from the API response - never make up information
464
+ # 3. Respond in {detected_language} language only
465
+ # 4. Write like you're talking to a friend or family member - warm, friendly, and caring
466
+ # 5. Make it sound natural and conversational, not like a system message
467
+ # 6. Convert technical data to simple, everyday language
468
+
469
+ # === DATE AND TIME FORMATTING ===
470
+
471
+ # When you see date_time fields like '2025-05-30T10:28:10':
472
+ # - For English: Convert to "May 30, 2025 at 10:28 AM"
473
+ # - For Arabic: Convert to "٣٠ مايو ٢٠٢٥ في الساعة ١٠:٢٨ صباحاً"
474
+
475
+ # === RESPONSE EXAMPLES ===
476
+
477
+ # For appointment confirmations:
478
+ # - English: "Great! I've got your appointment set up for May 30, 2025 at 10:28 AM. Everything looks good!"
479
+ # - Arabic: "ممتاز! موعدك محجوز يوم ٣٠ مايو ٢٠٢٥ الساعة ١٠:٢٨ صباحاً. كل شيء جاهز!"
480
+
481
+ # For appointment info:
482
+ # - English: "Your next appointment is on May 30, 2025 at 10:28 AM. See you then!"
483
+ # - Arabic: "موعدك القادم يوم ٣٠ مايو ٢٠٢٥ الساعة ١٠:٢٨ صباحاً. نراك قريباً!"
484
+
485
+ # === TONE GUIDELINES ===
486
+ # - Use friendly words like: "Great!", "Perfect!", "All set!", "ممتاز!", "رائع!", "تمام!"
487
+ # - Add reassuring phrases: "Everything looks good", "You're all set", "كل شيء جاهز", "تم بنجاح"
488
+ # - Sound helpful and caring, not robotic or formal
489
+
490
+ # === LANGUAGE FORMATTING ===
491
+
492
+ # For Arabic responses:
493
+ # - Use Arabic numerals: ٠١٢٣٤٥٦٧٨٩
494
+ # - Use Arabic month names: يناير، فبراير، مارس، أبريل، مايو، يونيو، يوليو، أغسطس، سبتمبر، أكتوبر، نوفمبر، ديسمبر
495
+ # - Friendly, warm Arabic tone
496
+
497
+ # For English responses:
498
+ # - Use standard English numerals
499
+ # - 12-hour time format with AM/PM
500
+ # - Friendly, conversational English tone
501
 
502
  # === CRITICAL RULES ===
503
+ # - Extract dates and times exactly as they appear in the API response
504
+ # - Never use example dates or placeholder information
505
+ # - Respond only in the specified language
506
+ # - Make your response sound like a helpful friend, not a computer
507
+ # - Focus on answering the user's specific question with warmth and care
508
+
509
+ # Generate a friendly, helpful response using the API data provided above.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  # """,
511
  # input_variables=["user_query", "api_response", "detected_language", "sentiment_analysis"]
512
  # )
513
  self.user_response_template = PromptTemplate(
514
+ template="""
515
+ You are a professional healthcare assistant. Your task is to carefully analyze the API data and respond to the user's question accurately.
516
+
517
+ User Query: {user_query}
518
+ User Sentiment: {sentiment_analysis}
519
+ Response Language: {detected_language}
520
+
521
+ API Response Data:
522
+ {api_response}
523
+
524
+ === CRITICAL INSTRUCTIONS ===
525
+
526
+ 1. FIRST: Carefully read and analyze the API response data above
527
+ 2. SECOND: Identify all date_time fields in the format 'YYYY-MM-DDTHH:MM:SS'
528
+ 3. THIRD: Extract the EXACT dates and times from the API response - DO NOT use any example dates
529
+ 4. FOURTH: Convert these extracted dates to the user-friendly format specified below
530
+ 5. FIFTH: Respond ONLY in {detected_language} language
531
+ 6. Use a warm, friendly, conversational tone like talking to a friend
532
+
533
+ === DATE EXTRACTION AND CONVERSION ===
534
+
535
+ Step 1: Find date_time fields in the API response (format: 'YYYY-MM-DDTHH:MM:SS')
536
+ Step 2: Convert ONLY the actual extracted dates using these rules:
537
+
538
+ For English:
539
+ - Convert 'YYYY-MM-DDTHH:MM:SS' to readable format
540
+ - Example: '2025-06-01T08:00:00' becomes "June 1, 2025 at 8:00 AM"
541
+ - Use 12-hour format with AM/PM
542
+
543
+ For Arabic:
544
+ - Convert to Arabic numerals and month names
545
+ - Example: '2025-06-01T08:00:00' becomes "١ يونيو ٢٠٢٥ في الساعة ٨:٠٠ صباحاً"
546
+ - Arabic months: يناير، فبراير، مارس، أبريل، مايو، يونيو، يوليو، أغسطس، سبتمبر، أكتوبر، نوفمبر، ديسمبر
547
+ - Arabic numerals: ٠١٢٣٤٥٦٧٨٩
548
+
549
+ === RESPONSE APPROACH ===
550
+
551
+ 1. Analyze what the user is asking for
552
+ 2. Find the relevant information in the API response
553
+ 3. Extract actual dates/times from the API data
554
+ 4. Convert technical information to simple language
555
+ 5. Respond warmly and helpfully
556
+
557
+ === TONE AND LANGUAGE ===
558
+
559
+ English responses:
560
+ - Use phrases like: "Great!", "Perfect!", "All set!", "Here's what I found:"
561
+ - Be conversational and reassuring
562
+
563
+ Arabic responses:
564
+ - Use phrases like: "ممتاز!", "رائع!", "تمام!", "إليك ما وجدته:"
565
+ - Be warm and helpful in Arabic style
566
+
567
+ === IMPORTANT REMINDERS ===
568
+ - NEVER use example dates from this prompt
569
+ - ALWAYS extract dates from the actual API response data
570
+ - If no dates exist in API response, don't mention any dates
571
+ - Stay focused on answering the user's specific question
572
+ - Use only information that exists in the API response
573
+
574
+ Now, carefully analyze the API response above and generate a helpful response to the user's query using ONLY the actual data provided.
575
+ """,
576
+ input_variables=["user_query", "api_response", "detected_language", "sentiment_analysis"]
577
+ )
578
 
579
  # Create chains
580
  self.intent_chain = LLMChain(llm=self.llm, prompt=self.intent_classifier_template)
581
  self.router_chain = LLMChain(llm=self.llm, prompt=self.router_prompt_template)
582
  self.conversation_chain = LLMChain(llm=self.llm, prompt=self.conversation_template)
583
  self.api_response_chain = LLMChain(llm=self.llm, prompt=self.user_response_template)
584
+
585
  def detect_language(self, text):
586
  """Detect language of the input text"""
587
  if self.language_classifier and len(text.strip()) > 3:
 
589
  result = self.language_classifier(text)
590
  detected_lang = result[0][0]['label']
591
  confidence = result[0][0]['score']
592
+
593
  if detected_lang in ['ar', 'arabic']:
594
  return "arabic"
595
  elif detected_lang in ['en', 'english']:
 
598
  return "english" # Default to English for unsupported languages
599
  except:
600
  pass
601
+
602
  # Fallback: Basic Arabic detection
603
  arabic_pattern = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF]+')
604
  if arabic_pattern.search(text):
605
  return "arabic"
606
+
607
  return "english"
608
 
609
  def analyze_sentiment(self, text):
 
617
  }
618
  except:
619
  pass
620
+
621
  return {"sentiment": "NEUTRAL", "score": 0.5}
622
 
623
  def extract_keywords(self, text):
 
633
  """Get recent conversation history as context"""
634
  if not self.conversation_history:
635
  return "No previous conversation"
636
+
637
  context = []
638
  for item in self.conversation_history[-3:]: # Last 3 exchanges
639
  context.append(f"User: {item['user_message']}")
640
  context.append(f"Bot: {item['bot_response'][:100]}...") # Truncate long responses
641
+
642
  return " | ".join(context)
643
 
644
  def add_to_history(self, user_message, bot_response, response_type):
 
649
  'bot_response': bot_response,
650
  'response_type': response_type
651
  })
652
+
653
  # Keep only recent history
654
  if len(self.conversation_history) > self.max_history_length:
655
  self.conversation_history = self.conversation_history[-self.max_history_length:]
 
663
  "conversation_history": self.get_conversation_context(),
664
  "endpoints_documentation": json.dumps(self.endpoints_documentation, indent=2)
665
  })
666
+
667
  # Parse the JSON response
668
  intent_text = result["text"]
669
  # Clean and parse JSON
670
  cleaned_response = re.sub(r'//.*?$', '', intent_text, flags=re.MULTILINE)
671
  cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
672
  cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
673
+
674
  try:
675
  intent_data = json.loads(cleaned_response)
676
  return intent_data
 
706
  "sentiment_analysis": json.dumps(sentiment_result),
707
  "conversation_history": self.get_conversation_context()
708
  })
709
+
710
  return result["text"].strip()
711
+
712
  except Exception as e:
713
  # Fallback response
714
  if detected_language == "arabic":
 
724
 
725
  print('Sending the api request')
726
  print(f"🔗 Making API call to {endpoint_method} {self.BASE_URL + endpoint_url} with params: {endpoint_params}")
727
+
728
  # Inject patient_id if needed
729
  if 'patient_id' in endpoint_params:
730
  endpoint_params['patient_id'] = self.user_id
731
+
732
  retries = 0
733
+ response = None
734
  while retries < self.max_retries:
735
  try:
736
  if endpoint_method.upper() == 'GET':
 
748
  headers=self.headers,
749
  timeout=10
750
  )
751
+
752
  response.raise_for_status()
753
+ print('Backend Response : ', response.json())
754
  return response.json()
755
+
756
  except requests.exceptions.RequestException as e:
757
  retries += 1
758
  if retries >= self.max_retries:
 
761
  "details": str(e),
762
  "status_code": getattr(e.response, 'status_code', None) if hasattr(e, 'response') else None
763
  }
764
+
765
  time.sleep(self.retry_delay)
766
  def parse_relative_date(self, text, detected_language):
767
  """
768
  Parse relative dates from text using a combination of methods
769
  """
770
  today = datetime.now()
771
+
772
  # Handle common relative date patterns in English and Arabic
773
  tomorrow_patterns = {
774
  'english': [r'\btomorrow\b', r'\bnext day\b'],
775
  'arabic': [r'\bغدا\b', r'\bبكرة\b', r'\bغدًا\b', r'\bالغد\b']
776
  }
777
+
778
  next_week_patterns = {
779
  'english': [r'\bnext week\b'],
780
  'arabic': [r'\bالأسبوع القادم\b', r'\bالأسبوع المقبل\b', r'\bالاسبوع الجاي\b']
781
  }
782
+
783
  # Check for "tomorrow" patterns
784
  for pattern in tomorrow_patterns.get(detected_language, []) + tomorrow_patterns.get('english', []):
785
  if re.search(pattern, text, re.IGNORECASE):
786
  return (today + timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%S')
787
+
788
  # Check for "next week" patterns
789
  for pattern in next_week_patterns.get(detected_language, []) + next_week_patterns.get('english', []):
790
  if re.search(pattern, text, re.IGNORECASE):
791
  return (today + timedelta(days=7)).strftime('%Y-%m-%dT%H:%M:%S')
792
+
793
  # If NER model is available, use it to extract date entities
794
  if self.date_parser and detected_language == 'english':
795
  try:
 
803
  return (today + timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%S')
804
  except Exception as e:
805
  print(f"Error in date parsing: {e}")
806
+
807
  # Default return None if no date pattern is recognized
808
  return None
809
 
 
811
  def handle_api_action(self, user_query, detected_language, sentiment_result, keywords):
812
  """Handle API-based actions"""
813
  try:
814
+
815
+ # parsed_date = self.parse_relative_date(user_query, detected_language)
816
+ # if parsed_date:
817
+ # print(f"Parsed relative date: {parsed_date}")
818
+
819
  # Route the query to determine API endpoint
820
  router_result = self.router_chain.invoke({
821
  "endpoints_documentation": json.dumps(self.endpoints_documentation, indent=2),
 
823
  "detected_language": detected_language,
824
  "extracted_keywords": ", ".join(keywords),
825
  "sentiment_analysis": json.dumps(sentiment_result),
826
+ "conversation_history": self.get_conversation_context(),
827
+ "current_datetime": datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
828
+ "timezone": "UTC",
829
+ "user_locale": "en-US"
830
  })
831
+
832
  # Parse router response
833
  route_text = router_result["text"]
834
  # cleaned_response = re.sub(r'//.*?$', '', route_text, flags=re.MULTILINE)
835
  # cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
836
  # cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
837
+
838
  # try:
839
  # parsed_route = json.loads(cleaned_response)
840
  # except json.JSONDecodeError:
 
843
  # parsed_route = json.loads(json_match.group(0))
844
  # else:
845
  # raise ValueError("Could not parse routing response")
846
+
847
  # print(f"🔍 Parsed route: {parsed_route}")
848
  cleaned_response = route_text
849
+
850
  # Remove any comments (both single-line and multi-line)
851
  cleaned_response = re.sub(r'//.*?$', '', cleaned_response, flags=re.MULTILINE)
852
  cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
853
+
854
  # Remove any trailing commas
855
  cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
856
+
857
  # Try different methods to parse the JSON response
858
  try:
859
  # First attempt: direct JSON parsing of cleaned response
 
879
  print(f"Failed to parse JSON. Raw response: {route_text}")
880
  print(f"Cleaned response: {cleaned_response}")
881
  raise ValueError("Could not extract valid JSON from LLM response")
882
+
883
  if not parsed_route:
884
  raise ValueError("Failed to parse LLM response into valid JSON")
885
+
886
  # Replace any placeholder values and inject parsed dates if available
887
  if 'params' in parsed_route:
888
  if 'patient_id' in parsed_route['params']:
889
  parsed_route['params']['patient_id'] = self.user_id
890
+
891
  # Inject parsed date if available and a date parameter exists
892
+ # date_params = ['appointment_date', 'date', 'schedule_date', 'date_time', 'new_date_time']
893
+ # if parsed_date:
894
+ # for param in date_params:
895
+ # if param in parsed_route['params']:
896
+ # parsed_route['params'][param] = parsed_date
897
+
898
  print('Parsed route: ', parsed_route)
899
 
900
  # Make backend API call
901
  api_response = self.backend_call(parsed_route)
902
+
903
  print("🔗 API response received:", api_response)
904
  # Generate user-friendly response
905
  user_response_result = self.api_response_chain.invoke({
 
910
  })
911
 
912
  print("🔗 API response:", user_response_result["text"].strip())
913
+
914
  return {
915
  "response": user_response_result["text"].strip(),
916
  "api_data": api_response,
917
  "routing_info": parsed_route
918
  }
919
+
920
  except Exception as e:
921
  # Fallback error response
922
  if detected_language == "arabic":
923
  error_msg = "أعتذر، لم أتمكن من معالجة طلبك. يرجى المحاولة مرة أخرى أو صياغة السؤال بطريقة مختلفة."
924
  else:
925
  error_msg = "I apologize, I couldn't process your request. Please try again or rephrase your question."
926
+
927
  return {
928
  "response": error_msg,
929
  "api_data": {"error": str(e)},
 
933
  def chat(self, user_message: str) -> ChatResponse:
934
  """Main chat method that handles user messages"""
935
  start_time = time.time()
936
+
937
  # Check for exit commands
938
  exit_commands = ['quit', 'exit', 'bye', 'خروج', 'وداعا', 'مع السلامة']
939
  if user_message.lower().strip() in exit_commands:
 
943
  message="Goodbye! Take care of your health! / وداعاً! اعتن بصحتك!",
944
  language="bilingual"
945
  )
946
+
947
  try:
948
  # Language detection and analysis
949
  detected_language = self.detect_language(user_message)
950
  sentiment_result = self.analyze_sentiment(user_message)
951
  keywords = self.extract_keywords(user_message)
952
+
953
  print(f"🔍 Language: {detected_language} | Sentiment: {sentiment_result['sentiment']} | Keywords: {keywords}")
954
+
955
  # Classify intent
956
  intent_data = self.classify_intent(user_message, detected_language)
957
  print(f"🎯 Intent: {intent_data['intent']} (confidence: {intent_data.get('confidence', 'N/A')})")
958
+
959
  # Handle based on intent
960
  if intent_data["intent"] == "API_ACTION" and intent_data.get("requires_backend", False):
961
  # Handle API-based actions
 
963
  action_result = self.handle_api_action(user_message, detected_language, sentiment_result, keywords)
964
 
965
  # print(action_result)
966
+
967
  response = ChatResponse(
968
  response_id=f"resp_{int(time.time())}",
969
  response_type="api_action",
 
972
  api_data=json.dumps(action_result["api_data"]) if 'action_result' in action_result else None,
973
  language=detected_language
974
  )
975
+
976
  else:
977
  # Handle conversational responses
978
  print("💬 Processing conversational response...")
979
  conv_response = self.handle_conversation(user_message, detected_language, sentiment_result)
980
+
981
  response = ChatResponse(
982
  response_id=f"resp_{int(time.time())}",
983
  response_type="conversation",
 
985
  api_call_made=False,
986
  language=detected_language
987
  )
988
+
989
  # Add to conversation history
990
  self.add_to_history(user_message, response.message, response.response_type)
991
+
992
  print(f"⏱️ Processing time: {time.time() - start_time:.2f}s")
993
  return response
994
+
995
  except Exception as e:
996
  print(f"❌ Error in chat processing: {e}")
997
  error_msg = "I apologize for the technical issue. Please try again. / أعتذر عن المشكلة التقنية. يرجى المحاولة مرة أخرى."
998
+
999
  return ChatResponse(
1000
  response_id=f"resp_{int(time.time())}",
1001
  response_type="conversation",
 
1007
  def start_interactive_chat(self):
1008
  """Start an interactive chat session"""
1009
  print("🚀 Starting interactive chat session...")
1010
+
1011
  while True:
1012
  try:
1013
  # Get user input
1014
  user_input = input("\n👤 You: ").strip()
1015
+
1016
  if not user_input:
1017
  continue
1018
+
1019
  # Process the message
1020
  print("🤖 Processing...")
1021
  response = self.chat(user_input)
1022
+
1023
  # Display response
1024
  print(f"\n🏥 Healthcare Bot: {response.message}")
1025
+
1026
  # Show additional info if API call was made
1027
  if response.api_call_made and response.api_data:
1028
  if "error" not in response.api_data:
1029
  print("✅ Successfully retrieved information from healthcare system")
1030
  else:
1031
  print("⚠️ There was an issue accessing the healthcare system")
1032
+
1033
  # Check for exit
1034
  if "Goodbye" in response.message or "وداعاً" in response.message:
1035
  break
1036
+
1037
  except KeyboardInterrupt:
1038
  print("\n\n👋 Chat session ended. Goodbye!")
1039
  break
1040
  except Exception as e:
1041
  print(f"\n❌ Unexpected error: {e}")
1042
  print("The chat session will continue...")
 
 
1043
  # Create a simple function to start the chatbot
1044
  # def start_healthcare_chatbot():
1045
  # """Initialize and start the healthcare chatbot"""