Spaces:
Running
Running
Commit
·
72dc521
1
Parent(s):
b011019
Fix some issues before sendng the request
Browse files
main.py
CHANGED
@@ -599,10 +599,59 @@ class HealthcareChatbot:
|
|
599 |
}
|
600 |
|
601 |
time.sleep(self.retry_delay)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
602 |
|
603 |
def handle_api_action(self, user_query, detected_language, sentiment_result, keywords):
|
604 |
"""Handle API-based actions"""
|
605 |
try:
|
|
|
|
|
|
|
|
|
|
|
606 |
# Route the query to determine API endpoint
|
607 |
router_result = self.router_chain.invoke({
|
608 |
"endpoints_documentation": json.dumps(self.endpoints_documentation, indent=2),
|
@@ -615,20 +664,72 @@ class HealthcareChatbot:
|
|
615 |
|
616 |
# Parse router response
|
617 |
route_text = router_result["text"]
|
618 |
-
cleaned_response = re.sub(r'//.*?$', '', route_text, flags=re.MULTILINE)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
619 |
cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
|
|
|
|
|
620 |
cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
|
621 |
|
|
|
622 |
try:
|
|
|
623 |
parsed_route = json.loads(cleaned_response)
|
624 |
except json.JSONDecodeError:
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
630 |
|
631 |
-
print(f"🔍 Parsed route: {parsed_route}")
|
632 |
# Make backend API call
|
633 |
api_response = self.backend_call(parsed_route)
|
634 |
|
|
|
599 |
}
|
600 |
|
601 |
time.sleep(self.retry_delay)
|
602 |
+
def parse_relative_date(self, text, detected_language):
|
603 |
+
"""
|
604 |
+
Parse relative dates from text using a combination of methods
|
605 |
+
"""
|
606 |
+
today = datetime.now()
|
607 |
+
|
608 |
+
# Handle common relative date patterns in English and Arabic
|
609 |
+
tomorrow_patterns = {
|
610 |
+
'english': [r'\btomorrow\b', r'\bnext day\b'],
|
611 |
+
'arabic': [r'\bغدا\b', r'\bبكرة\b', r'\bغدًا\b', r'\bالغد\b']
|
612 |
+
}
|
613 |
+
|
614 |
+
next_week_patterns = {
|
615 |
+
'english': [r'\bnext week\b'],
|
616 |
+
'arabic': [r'\bالأسبوع القادم\b', r'\bالأسبوع المقبل\b', r'\bالاسبوع الجاي\b']
|
617 |
+
}
|
618 |
+
|
619 |
+
# Check for "tomorrow" patterns
|
620 |
+
for pattern in tomorrow_patterns.get(detected_language, []) + tomorrow_patterns.get('english', []):
|
621 |
+
if re.search(pattern, text, re.IGNORECASE):
|
622 |
+
return (today + timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%S')
|
623 |
+
|
624 |
+
# Check for "next week" patterns
|
625 |
+
for pattern in next_week_patterns.get(detected_language, []) + next_week_patterns.get('english', []):
|
626 |
+
if re.search(pattern, text, re.IGNORECASE):
|
627 |
+
return (today + timedelta(days=7)).strftime('%Y-%m-%dT%H:%M:%S')
|
628 |
+
|
629 |
+
# If NER model is available, use it to extract date entities
|
630 |
+
if self.date_parser and detected_language == 'english':
|
631 |
+
try:
|
632 |
+
date_entities = self.date_parser(text)
|
633 |
+
for entity in date_entities:
|
634 |
+
if entity['entity_group'] == 'DATE':
|
635 |
+
# Here you would need more complex date parsing logic
|
636 |
+
# This is just a placeholder
|
637 |
+
print(f"Found date entity: {entity['word']}")
|
638 |
+
# For now, just default to tomorrow if we detect any date
|
639 |
+
return (today + timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%S')
|
640 |
+
except Exception as e:
|
641 |
+
print(f"Error in date parsing: {e}")
|
642 |
+
|
643 |
+
# Default return None if no date pattern is recognized
|
644 |
+
return None
|
645 |
+
|
646 |
|
647 |
def handle_api_action(self, user_query, detected_language, sentiment_result, keywords):
|
648 |
"""Handle API-based actions"""
|
649 |
try:
|
650 |
+
|
651 |
+
parsed_date = self.parse_relative_date(user_query, detected_language)
|
652 |
+
if parsed_date:
|
653 |
+
print(f"Parsed relative date: {parsed_date}")
|
654 |
+
|
655 |
# Route the query to determine API endpoint
|
656 |
router_result = self.router_chain.invoke({
|
657 |
"endpoints_documentation": json.dumps(self.endpoints_documentation, indent=2),
|
|
|
664 |
|
665 |
# Parse router response
|
666 |
route_text = router_result["text"]
|
667 |
+
# cleaned_response = re.sub(r'//.*?$', '', route_text, flags=re.MULTILINE)
|
668 |
+
# cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
|
669 |
+
# cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
|
670 |
+
|
671 |
+
# try:
|
672 |
+
# parsed_route = json.loads(cleaned_response)
|
673 |
+
# except json.JSONDecodeError:
|
674 |
+
# json_match = re.search(r'\{.*?\}', cleaned_response, re.DOTALL)
|
675 |
+
# if json_match:
|
676 |
+
# parsed_route = json.loads(json_match.group(0))
|
677 |
+
# else:
|
678 |
+
# raise ValueError("Could not parse routing response")
|
679 |
+
|
680 |
+
# print(f"🔍 Parsed route: {parsed_route}")
|
681 |
+
cleaned_response = route_text
|
682 |
+
|
683 |
+
# Remove any comments (both single-line and multi-line)
|
684 |
+
cleaned_response = re.sub(r'//.*?$', '', cleaned_response, flags=re.MULTILINE)
|
685 |
cleaned_response = re.sub(r'/\*.*?\*/', '', cleaned_response, flags=re.DOTALL)
|
686 |
+
|
687 |
+
# Remove any trailing commas
|
688 |
cleaned_response = re.sub(r',(\s*[}\]])', r'\1', cleaned_response)
|
689 |
|
690 |
+
# Try different methods to parse the JSON response
|
691 |
try:
|
692 |
+
# First attempt: direct JSON parsing of cleaned response
|
693 |
parsed_route = json.loads(cleaned_response)
|
694 |
except json.JSONDecodeError:
|
695 |
+
try:
|
696 |
+
# Second attempt: extract JSON from markdown code block
|
697 |
+
json_match = re.search(r'```(?:json)?\s*(\{.*?\})\s*```', cleaned_response, re.DOTALL)
|
698 |
+
if json_match:
|
699 |
+
parsed_route = json.loads(json_match.group(1))
|
700 |
+
except (json.JSONDecodeError, AttributeError):
|
701 |
+
try:
|
702 |
+
# Third attempt: find JSON-like content using regex
|
703 |
+
json_pattern = r'\{\s*"endpoint"\s*:.*?\}'
|
704 |
+
json_match = re.search(json_pattern, cleaned_response, re.DOTALL)
|
705 |
+
if json_match:
|
706 |
+
json_str = json_match.group(0)
|
707 |
+
# Additional cleaning for the extracted JSON
|
708 |
+
json_str = re.sub(r'//.*?$', '', json_str, flags=re.MULTILINE)
|
709 |
+
json_str = re.sub(r',(\s*[}\]])', r'\1', json_str)
|
710 |
+
parsed_route = json.loads(json_str)
|
711 |
+
except (json.JSONDecodeError, AttributeError):
|
712 |
+
print(f"Failed to parse JSON. Raw response: {route_text}")
|
713 |
+
print(f"Cleaned response: {cleaned_response}")
|
714 |
+
raise ValueError("Could not extract valid JSON from LLM response")
|
715 |
+
|
716 |
+
if not parsed_route:
|
717 |
+
raise ValueError("Failed to parse LLM response into valid JSON")
|
718 |
+
|
719 |
+
# Replace any placeholder values and inject parsed dates if available
|
720 |
+
if 'params' in parsed_route:
|
721 |
+
if 'patient_id' in parsed_route['params']:
|
722 |
+
parsed_route['params']['patient_id'] = self.user_id
|
723 |
+
|
724 |
+
# Inject parsed date if available and a date parameter exists
|
725 |
+
date_params = ['appointment_date', 'date', 'schedule_date', 'date_time', 'new_date_time']
|
726 |
+
if parsed_date:
|
727 |
+
for param in date_params:
|
728 |
+
if param in parsed_route['params']:
|
729 |
+
parsed_route['params'][param] = parsed_date
|
730 |
+
|
731 |
+
print('Parsed route: ', parsed_route)
|
732 |
|
|
|
733 |
# Make backend API call
|
734 |
api_response = self.backend_call(parsed_route)
|
735 |
|