Update src/model.py
Browse files- src/model.py +72 -35
src/model.py
CHANGED
|
@@ -1196,7 +1196,8 @@ def parse_doctor_response(response_text):
|
|
| 1196 |
"diagnosis": "",
|
| 1197 |
"treatment": "",
|
| 1198 |
"reasoning": [],
|
| 1199 |
-
"sources": []
|
|
|
|
| 1200 |
}
|
| 1201 |
|
| 1202 |
# Try to extract diagnosis
|
|
@@ -1210,7 +1211,7 @@ def parse_doctor_response(response_text):
|
|
| 1210 |
parsed["treatment"] = treatment_match.group(2).strip()
|
| 1211 |
|
| 1212 |
# Try to extract reasoning if present
|
| 1213 |
-
reasoning_match = re.search(r'(?i)reasoning:?\s*(.*?)(?:\n\n\Z|\Z)', response_text, re.DOTALL)
|
| 1214 |
if reasoning_match:
|
| 1215 |
reasoning_text = reasoning_match.group(1).strip()
|
| 1216 |
# Split into bullet points if present
|
|
@@ -1221,11 +1222,28 @@ def parse_doctor_response(response_text):
|
|
| 1221 |
parsed["reasoning"][0] = parsed["reasoning"][0].lstrip('- ')
|
| 1222 |
else:
|
| 1223 |
parsed["reasoning"] = [reasoning_text]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1224 |
|
| 1225 |
# Extract sources/references
|
| 1226 |
-
sources_match = re.search(r'(?i)(sources|references):?\s*(.*?)(?:\n\n\Z|\Z)', response_text, re.DOTALL)
|
| 1227 |
if sources_match:
|
| 1228 |
-
sources_text = sources_match.group(
|
| 1229 |
# Split into individual sources
|
| 1230 |
if '\n' in sources_text:
|
| 1231 |
parsed["sources"] = [item.strip() for item in sources_text.split('\n') if item.strip()]
|
|
@@ -1323,41 +1341,53 @@ def orchestrator_chat(history, query, use_rag, is_follow_up=False):
|
|
| 1323 |
# Add instructions for structured output
|
| 1324 |
if use_rag:
|
| 1325 |
output_instructions = """
|
| 1326 |
-
Please structure your response
|
| 1327 |
-
|
| 1328 |
-
|
| 1329 |
-
|
| 1330 |
-
|
| 1331 |
-
|
| 1332 |
-
|
| 1333 |
-
|
| 1334 |
-
4. IMPORTANT: You MUST cite between 2-3 different medical evidence sources using either:
|
| 1335 |
• [PMID:123456] format for PubMed articles
|
| 1336 |
• [DOI:10.xxxx/yyyy] format for Europe PMC articles without PMID
|
| 1337 |
-
|
| 1338 |
-
|
| 1339 |
-
|
| 1340 |
-
-
|
| 1341 |
-
|
| 1342 |
-
|
| 1343 |
-
|
| 1344 |
-
|
| 1345 |
-
|
| 1346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1347 |
"""
|
| 1348 |
else:
|
| 1349 |
# Different instructions when RAG is disabled - no mention of sources or citations
|
| 1350 |
output_instructions = """
|
| 1351 |
-
Please structure your response
|
| 1352 |
-
|
| 1353 |
-
|
| 1354 |
-
|
| 1355 |
-
|
| 1356 |
-
|
| 1357 |
-
|
| 1358 |
-
|
| 1359 |
-
**
|
| 1360 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1361 |
IMPORTANT: Since database search is disabled, do not include citations or sources in your response.
|
| 1362 |
"""
|
| 1363 |
|
|
@@ -1370,6 +1400,7 @@ def orchestrator_chat(history, query, use_rag, is_follow_up=False):
|
|
| 1370 |
# Extract and process sources
|
| 1371 |
explanation = None
|
| 1372 |
evidence = None
|
|
|
|
| 1373 |
|
| 1374 |
if use_rag:
|
| 1375 |
# Process the response to replace source placeholders with actual links
|
|
@@ -1388,6 +1419,9 @@ def orchestrator_chat(history, query, use_rag, is_follow_up=False):
|
|
| 1388 |
explanation = "\n".join([f"- {r}" for r in reasoning])
|
| 1389 |
else:
|
| 1390 |
explanation = reasoning
|
|
|
|
|
|
|
|
|
|
| 1391 |
else:
|
| 1392 |
# If RAG is disabled, just parse the response without source processing
|
| 1393 |
parsed_response = parse_doctor_response(response)
|
|
@@ -1400,9 +1434,12 @@ def orchestrator_chat(history, query, use_rag, is_follow_up=False):
|
|
| 1400 |
explanation = "\n".join([f"- {r}" for r in reasoning])
|
| 1401 |
else:
|
| 1402 |
explanation = reasoning
|
|
|
|
|
|
|
|
|
|
| 1403 |
|
| 1404 |
# Return the response (with links if RAG is enabled), explanation, and evidence
|
| 1405 |
-
return main_response, explanation, evidence_snippets
|
| 1406 |
|
| 1407 |
# Enhanced interactive loop with better handling of consultations
|
| 1408 |
def run_consultation(use_rag=True):
|
|
@@ -1428,7 +1465,7 @@ def run_consultation(use_rag=True):
|
|
| 1428 |
print("\nSearching medical databases...")
|
| 1429 |
|
| 1430 |
# Process query
|
| 1431 |
-
reply, explanation, evidence = orchestrator_chat(history, query, use_rag, is_follow_up)
|
| 1432 |
|
| 1433 |
# Display the AI response
|
| 1434 |
print("\n" + "=" * 30)
|
|
|
|
| 1196 |
"diagnosis": "",
|
| 1197 |
"treatment": "",
|
| 1198 |
"reasoning": [],
|
| 1199 |
+
"sources": [],
|
| 1200 |
+
"follow_up_questions": []
|
| 1201 |
}
|
| 1202 |
|
| 1203 |
# Try to extract diagnosis
|
|
|
|
| 1211 |
parsed["treatment"] = treatment_match.group(2).strip()
|
| 1212 |
|
| 1213 |
# Try to extract reasoning if present
|
| 1214 |
+
reasoning_match = re.search(r'(?i)(?:#{1,3}\s*)?reasoning:?\s*(.*?)(?:(?:#{1,3}\s*(?:follow[ -]?up questions|sources))|(?:\n\n\Z)|\Z)', response_text, re.DOTALL)
|
| 1215 |
if reasoning_match:
|
| 1216 |
reasoning_text = reasoning_match.group(1).strip()
|
| 1217 |
# Split into bullet points if present
|
|
|
|
| 1222 |
parsed["reasoning"][0] = parsed["reasoning"][0].lstrip('- ')
|
| 1223 |
else:
|
| 1224 |
parsed["reasoning"] = [reasoning_text]
|
| 1225 |
+
|
| 1226 |
+
# Extract follow-up questions
|
| 1227 |
+
follow_up_match = re.search(r'(?i)(?:#{1,3}\s*)?follow[ -]?up questions:?\s*(.*?)(?:(?:#{1,3}\s*(?:reasoning|sources))|(?:\n\n\Z)|\Z)', response_text, re.DOTALL)
|
| 1228 |
+
if follow_up_match:
|
| 1229 |
+
follow_up_text = follow_up_match.group(1).strip()
|
| 1230 |
+
# Extract numbered questions
|
| 1231 |
+
questions = re.findall(r'(?:^|\n)\s*\d+\.\s*(.*?)(?=\n\s*\d+\.|\Z)', follow_up_text, re.DOTALL)
|
| 1232 |
+
if questions:
|
| 1233 |
+
parsed["follow_up_questions"] = [q.strip() for q in questions if q.strip()]
|
| 1234 |
+
else:
|
| 1235 |
+
# Try to extract bullet points if no numbered questions
|
| 1236 |
+
questions = re.findall(r'(?:^|\n)\s*[-•*]\s*(.*?)(?=\n\s*[-•*]|\Z)', follow_up_text, re.DOTALL)
|
| 1237 |
+
if questions:
|
| 1238 |
+
parsed["follow_up_questions"] = [q.strip() for q in questions if q.strip()]
|
| 1239 |
+
elif follow_up_text.strip():
|
| 1240 |
+
# If no formatting but there's text, use the whole text
|
| 1241 |
+
parsed["follow_up_questions"] = [follow_up_text.strip()]
|
| 1242 |
|
| 1243 |
# Extract sources/references
|
| 1244 |
+
sources_match = re.search(r'(?i)(?:#{1,3}\s*)?(?:sources|references):?\s*(.*?)(?:\n\n\Z|\Z)', response_text, re.DOTALL)
|
| 1245 |
if sources_match:
|
| 1246 |
+
sources_text = sources_match.group(1).strip()
|
| 1247 |
# Split into individual sources
|
| 1248 |
if '\n' in sources_text:
|
| 1249 |
parsed["sources"] = [item.strip() for item in sources_text.split('\n') if item.strip()]
|
|
|
|
| 1341 |
# Add instructions for structured output
|
| 1342 |
if use_rag:
|
| 1343 |
output_instructions = """
|
| 1344 |
+
Please structure your response as follows:
|
| 1345 |
+
|
| 1346 |
+
**Main Response**
|
| 1347 |
+
Always provide a direct answer to the doctor's query first, even if you don't have all the information you'd like. Include:
|
| 1348 |
+
1. Your best answer based on the information already provided
|
| 1349 |
+
2. If appropriate, a differential diagnosis with likelihood assessments
|
| 1350 |
+
3. Recommendations for treatment or next steps
|
| 1351 |
+
4. Cite 2-3 different medical evidence sources using:
|
|
|
|
| 1352 |
• [PMID:123456] format for PubMed articles
|
| 1353 |
• [DOI:10.xxxx/yyyy] format for Europe PMC articles without PMID
|
| 1354 |
+
|
| 1355 |
+
**Follow-up Questions**
|
| 1356 |
+
IMPORTANT: Place all clarifying questions in this separate section, not in your main response.
|
| 1357 |
+
List 2-4 specific questions that would help you provide a more precise assessment.
|
| 1358 |
+
Format these as a numbered list.
|
| 1359 |
+
|
| 1360 |
+
**Reasoning**
|
| 1361 |
+
Provide bullet points explaining your clinical reasoning.
|
| 1362 |
+
|
| 1363 |
+
**Sources**
|
| 1364 |
+
List all references cited (2-3 sources), formatted as:
|
| 1365 |
+
- PMID: 12345678 - Author et al. (Year). Title. Journal.
|
| 1366 |
+
URL: https://pubmed.ncbi.nlm.nih.gov/12345678/
|
| 1367 |
+
- DOI: 10.xxxx/yyyy - Author et al. (Year). Title. Journal.
|
| 1368 |
+
URL: https://doi.org/10.xxxx/yyyy
|
| 1369 |
+
|
| 1370 |
+
IMPORTANT: Only cite sources provided in the evidence. Do not fabricate references.
|
| 1371 |
"""
|
| 1372 |
else:
|
| 1373 |
# Different instructions when RAG is disabled - no mention of sources or citations
|
| 1374 |
output_instructions = """
|
| 1375 |
+
Please structure your response as follows:
|
| 1376 |
+
|
| 1377 |
+
**Main Response**
|
| 1378 |
+
Always provide a direct answer to the doctor's query first, even if you don't have all the information you'd like. Include:
|
| 1379 |
+
1. Your best answer based on the information already provided
|
| 1380 |
+
2. If appropriate, a differential diagnosis
|
| 1381 |
+
3. Recommendations for treatment or next steps
|
| 1382 |
+
|
| 1383 |
+
**Follow-up Questions**
|
| 1384 |
+
IMPORTANT: Place all clarifying questions in this separate section, not in your main response.
|
| 1385 |
+
List 2-4 specific questions that would help you provide a more precise assessment.
|
| 1386 |
+
Format these as a numbered list.
|
| 1387 |
+
|
| 1388 |
+
**Reasoning**
|
| 1389 |
+
Provide bullet points explaining your clinical reasoning.
|
| 1390 |
+
|
| 1391 |
IMPORTANT: Since database search is disabled, do not include citations or sources in your response.
|
| 1392 |
"""
|
| 1393 |
|
|
|
|
| 1400 |
# Extract and process sources
|
| 1401 |
explanation = None
|
| 1402 |
evidence = None
|
| 1403 |
+
follow_up_questions = []
|
| 1404 |
|
| 1405 |
if use_rag:
|
| 1406 |
# Process the response to replace source placeholders with actual links
|
|
|
|
| 1419 |
explanation = "\n".join([f"- {r}" for r in reasoning])
|
| 1420 |
else:
|
| 1421 |
explanation = reasoning
|
| 1422 |
+
|
| 1423 |
+
# Extract follow-up questions
|
| 1424 |
+
follow_up_questions = parsed_response.get("follow_up_questions", [])
|
| 1425 |
else:
|
| 1426 |
# If RAG is disabled, just parse the response without source processing
|
| 1427 |
parsed_response = parse_doctor_response(response)
|
|
|
|
| 1434 |
explanation = "\n".join([f"- {r}" for r in reasoning])
|
| 1435 |
else:
|
| 1436 |
explanation = reasoning
|
| 1437 |
+
|
| 1438 |
+
# Extract follow-up questions
|
| 1439 |
+
follow_up_questions = parsed_response.get("follow_up_questions", [])
|
| 1440 |
|
| 1441 |
# Return the response (with links if RAG is enabled), explanation, and evidence
|
| 1442 |
+
return main_response, explanation, follow_up_questions, evidence_snippets
|
| 1443 |
|
| 1444 |
# Enhanced interactive loop with better handling of consultations
|
| 1445 |
def run_consultation(use_rag=True):
|
|
|
|
| 1465 |
print("\nSearching medical databases...")
|
| 1466 |
|
| 1467 |
# Process query
|
| 1468 |
+
reply, explanation, follow_up_questions, evidence = orchestrator_chat(history, query, use_rag, is_follow_up)
|
| 1469 |
|
| 1470 |
# Display the AI response
|
| 1471 |
print("\n" + "=" * 30)
|