YanBoChen commited on
Commit
253609b
·
1 Parent(s): 16ee1e5

fix(mild bug): enhance user query prompts (more robust dealing process with .txt or .json) and add postpartum hemorrhage condition mapping

Browse files
evaluation/user_query.txt CHANGED
@@ -17,18 +17,18 @@ Suspected acute ischemic stroke. Tell me the next steps to take
17
 
18
  ### 一、Diagnosis-Focused(診斷為主)
19
 
20
- 1. I have a 68-year-old man with atrial fibrillation presenting with sudden slurred speech and right-sided weaknesswhat are the possible diagnoses, and how would you evaluate them?
21
- 2. A 40-year-old woman reports fever, urinary frequency, and dysuriawhat differential diagnoses should I consider, and which tests would you order?
22
- 3. A 50-year-old patient has progressive dyspnea on exertion and orthopnea over two weekswhat are the likely causes, and what diagnostic steps should I take?
23
 
24
  ### 二、Treatment-Focused(治療為主)
25
 
26
- 4. ECG shows a suspected acute STEMIwhat immediate interventions should I initiate in the next five minutes?
27
- 5. I have a patient diagnosed with bacterial meningitis—what empiric antibiotic regimen and supportive measures should I implement?
28
  6. A patient is in septic shock with BP 80/50 mmHg and HR 120 bpm—what fluid resuscitation and vasopressor strategy would you recommend?
29
 
30
  ### 三、Mixed(診斷+治療綜合)
31
 
32
  7. A 75-year-old diabetic presents with a non-healing foot ulcer and fever—what differential for osteomyelitis, diagnostic workup, and management plan do you suggest?
33
- 8. A 60-year-old COPD patient has worsening dyspnea and hypercapnia on ABG—how would you confirm the diagnosis, and what is your stepwise treatment approach?
34
- 9. A 28-year-old woman is experiencing postpartum hemorrhagewhat are the possible causes, what immediate resuscitation steps should I take, and how would you proceed with definitive management?
 
17
 
18
  ### 一、Diagnosis-Focused(診斷為主)
19
 
20
+ 1. I have a 68-year-old man with atrial fibrillation presenting with sudden slurred speech and right-sided weakness. what are the possible diagnoses, and how would you evaluate them?
21
+ 2. A 40-year-old woman reports fever, urinary frequency, and dysuria. what differential diagnoses should I consider, and which tests would you order?
22
+ 3. A 50-year-old patient has progressive dyspnea on exertion and orthopnea over two weeks. what are the likely causes, and what diagnostic steps should I take?
23
 
24
  ### 二、Treatment-Focused(治療為主)
25
 
26
+ 4. ECG shows a suspected acute STEMI. what immediate interventions should I initiate in the next five minutes?
27
+ 5. I have a patient diagnosed with bacterial meningitis. What empiric antibiotic regimen and supportive measures should I implement?
28
  6. A patient is in septic shock with BP 80/50 mmHg and HR 120 bpm—what fluid resuscitation and vasopressor strategy would you recommend?
29
 
30
  ### 三、Mixed(診斷+治療綜合)
31
 
32
  7. A 75-year-old diabetic presents with a non-healing foot ulcer and fever—what differential for osteomyelitis, diagnostic workup, and management plan do you suggest?
33
+ 8. A 60-year-old COPD patient has worsening dyspnea and hypercapnia on ABG. How would you confirm the diagnosis, and what is your stepwise treatment approach?
34
+ 9. A 28-year-old woman is experiencing postpartum hemorrhage. what are the possible causes, what immediate resuscitation steps should I take, and how would you proceed with definitive management?
src/llm_clients.py CHANGED
@@ -9,6 +9,8 @@ Date: 2025-07-29
9
 
10
  import logging
11
  import os
 
 
12
  from typing import Dict, Optional, Union
13
  from huggingface_hub import InferenceClient
14
  from dotenv import load_dotenv
@@ -68,6 +70,91 @@ class llm_Med42_70BClient:
68
  self.logger.error(f"Detailed Error: {repr(e)}")
69
  raise ValueError(f"Failed to initialize Medical LLM client: {str(e)}") from e
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  def analyze_medical_query(
72
  self,
73
  query: str,
@@ -138,6 +225,27 @@ class llm_Med42_70BClient:
138
  self.logger.info(f"Raw LLM Response: {response_text}")
139
  self.logger.info(f"Query Latency: {latency:.4f} seconds")
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  # Detect abnormal response
142
  if self._is_abnormal_response(response_text):
143
  self.logger.error(f"❌ Abnormal LLM response detected: {response_text[:50]}...")
@@ -149,15 +257,12 @@ class llm_Med42_70BClient:
149
  'latency': latency
150
  }
151
 
152
- # Extract condition from response
153
- extracted_condition = self._extract_condition(response_text)
154
-
155
  # Log the extracted condition
156
  self.logger.info(f"Extracted Condition: {extracted_condition}")
157
 
158
  return {
159
  'extracted_condition': extracted_condition,
160
- 'confidence': '0.8',
161
  'raw_response': response_text,
162
  'latency': latency # Add latency to the return dictionary
163
  }
 
9
 
10
  import logging
11
  import os
12
+ import json
13
+ import re
14
  from typing import Dict, Optional, Union
15
  from huggingface_hub import InferenceClient
16
  from dotenv import load_dotenv
 
70
  self.logger.error(f"Detailed Error: {repr(e)}")
71
  raise ValueError(f"Failed to initialize Medical LLM client: {str(e)}") from e
72
 
73
+ def fix_json_formatting(self, response_text: str) -> str:
74
+ """
75
+ Fix common JSON formatting errors
76
+
77
+ Args:
78
+ response_text: Raw response text that may contain JSON errors
79
+
80
+ Returns:
81
+ Fixed JSON string
82
+ """
83
+ # 1. Fix missing commas between key-value pairs
84
+ # Look for "value" "key" pattern and add comma
85
+ fixed = re.sub(r'"\s*\n\s*"', '",\n "', response_text)
86
+
87
+ # 2. Fix missing commas between values and keys
88
+ fixed = re.sub(r'"\s*(["\[])', '",\1', fixed)
89
+
90
+ # 3. Remove trailing commas
91
+ fixed = re.sub(r',\s*}', '}', fixed)
92
+ fixed = re.sub(r',\s*]', ']', fixed)
93
+
94
+ # 4. Ensure string values are properly quoted
95
+ fixed = re.sub(r':\s*([^",{}\[\]]+)\s*([,}])', r': "\1"\2', fixed)
96
+
97
+ return fixed
98
+
99
+ def parse_medical_response(self, response_text: str) -> Dict:
100
+ """
101
+ Enhanced JSON parsing logic with error recovery
102
+
103
+ Args:
104
+ response_text: Raw response text from Med42-70B
105
+
106
+ Returns:
107
+ Parsed response dictionary
108
+ """
109
+ try:
110
+ return json.loads(response_text)
111
+ except json.JSONDecodeError as e:
112
+ self.logger.warning(f"Initial JSON parsing failed: {e}")
113
+
114
+ # Attempt to fix common JSON errors
115
+ try:
116
+ fixed_response = self.fix_json_formatting(response_text)
117
+ self.logger.info("Attempting to parse fixed JSON")
118
+ return json.loads(fixed_response)
119
+ except json.JSONDecodeError as e2:
120
+ self.logger.error(f"Fixed JSON parsing also failed: {e2}")
121
+
122
+ # Try to extract partial information
123
+ try:
124
+ return self.extract_partial_medical_info(response_text)
125
+ except:
126
+ # Final fallback format
127
+ return {
128
+ "extracted_condition": "parsing_error",
129
+ "confidence": "0.0",
130
+ "is_medical": True,
131
+ "raw_response": response_text,
132
+ "error": str(e)
133
+ }
134
+
135
+ def extract_partial_medical_info(self, response_text: str) -> Dict:
136
+ """
137
+ Extract partial medical information from malformed response
138
+
139
+ Args:
140
+ response_text: Malformed response text
141
+
142
+ Returns:
143
+ Dictionary with extracted information
144
+ """
145
+ # Try to extract condition
146
+ condition_match = re.search(r'"extracted_condition":\s*"([^"]*)"', response_text)
147
+ confidence_match = re.search(r'"confidence":\s*"([^"]*)"', response_text)
148
+ medical_match = re.search(r'"is_medical":\s*(true|false)', response_text)
149
+
150
+ return {
151
+ "extracted_condition": condition_match.group(1) if condition_match else "unknown",
152
+ "confidence": confidence_match.group(1) if confidence_match else "0.0",
153
+ "is_medical": medical_match.group(1) == "true" if medical_match else True,
154
+ "raw_response": response_text,
155
+ "parsing_method": "partial_extraction"
156
+ }
157
+
158
  def analyze_medical_query(
159
  self,
160
  query: str,
 
225
  self.logger.info(f"Raw LLM Response: {response_text}")
226
  self.logger.info(f"Query Latency: {latency:.4f} seconds")
227
 
228
+ # Enhanced response parsing - handle both JSON and text formats
229
+ try:
230
+ # Try to parse as JSON first (in case API returns JSON)
231
+ parsed_response = self.parse_medical_response(response_text)
232
+
233
+ # If it's a valid JSON response, extract condition from it
234
+ if isinstance(parsed_response, dict) and 'extracted_condition' in parsed_response:
235
+ extracted_condition = parsed_response.get('extracted_condition', '')
236
+ confidence = parsed_response.get('confidence', '0.8')
237
+ self.logger.info(f"Parsed JSON response - Condition: {extracted_condition}")
238
+ else:
239
+ # Fallback to text extraction
240
+ extracted_condition = self._extract_condition(response_text)
241
+ confidence = '0.8'
242
+
243
+ except Exception as parse_error:
244
+ self.logger.warning(f"Response parsing failed: {parse_error}")
245
+ # Fallback to text extraction
246
+ extracted_condition = self._extract_condition(response_text)
247
+ confidence = '0.8'
248
+
249
  # Detect abnormal response
250
  if self._is_abnormal_response(response_text):
251
  self.logger.error(f"❌ Abnormal LLM response detected: {response_text[:50]}...")
 
257
  'latency': latency
258
  }
259
 
 
 
 
260
  # Log the extracted condition
261
  self.logger.info(f"Extracted Condition: {extracted_condition}")
262
 
263
  return {
264
  'extracted_condition': extracted_condition,
265
+ 'confidence': confidence,
266
  'raw_response': response_text,
267
  'latency': latency # Add latency to the return dictionary
268
  }
src/medical_conditions.py CHANGED
@@ -63,6 +63,10 @@ CONDITION_KEYWORD_MAPPING: Dict[str, Dict[str, str]] = {
63
  "seizure disorder": {
64
  "emergency": "seizure|status epilepticus|postictal state",
65
  "treatment": "antiepileptic drugs|EEG monitoring|neurology consult"
 
 
 
 
66
  }
67
  }
68
 
 
63
  "seizure disorder": {
64
  "emergency": "seizure|status epilepticus|postictal state",
65
  "treatment": "antiepileptic drugs|EEG monitoring|neurology consult"
66
+ },
67
+ "postpartum_hemorrhage": {
68
+ "emergency": "postpartum hemorrhage|uterine atony|placental retention|vaginal laceration",
69
+ "treatment": "uterine massage|IV oxytocin infusion|blood transfusion|surgical intervention"
70
  }
71
  }
72