Update src/report_generator.py
Browse files- src/report_generator.py +69 -112
src/report_generator.py
CHANGED
|
@@ -14,43 +14,8 @@ from reportlab.lib.units import inch, cm
|
|
| 14 |
from reportlab.platypus import PageBreak, KeepTogether
|
| 15 |
|
| 16 |
from model import orchestrator_chat
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
# Function to format conversation history for report generation
|
| 20 |
-
def format_conversation_history(history, patient_info=None):
|
| 21 |
-
"""
|
| 22 |
-
Format the conversation history into a string suitable for LLM processing.
|
| 23 |
-
Optionally adds patient info at the beginning.
|
| 24 |
-
"""
|
| 25 |
-
formatted_text = "# Medical Consultation\n\n"
|
| 26 |
-
|
| 27 |
-
# Add patient info if provided
|
| 28 |
-
if patient_info:
|
| 29 |
-
formatted_text += "## Patient Information\n"
|
| 30 |
-
formatted_text += f"* Name: {patient_info.get('name', '')}\n"
|
| 31 |
-
formatted_text += f"* Age: {patient_info.get('age', '')}\n"
|
| 32 |
-
formatted_text += f"* Gender: {patient_info.get('gender', '')}\n\n"
|
| 33 |
-
|
| 34 |
-
formatted_text += "## Conversation Transcript\n\n"
|
| 35 |
-
|
| 36 |
-
for message in history:
|
| 37 |
-
role = message.get("role", "").strip()
|
| 38 |
-
content = message.get("content", "").strip()
|
| 39 |
-
|
| 40 |
-
if not content:
|
| 41 |
-
continue # Skip empty messages
|
| 42 |
-
|
| 43 |
-
if role.lower() == "user":
|
| 44 |
-
formatted_text += f"PATIENT: {content}\n\n"
|
| 45 |
-
elif role.lower() == "assistant":
|
| 46 |
-
formatted_text += f"ASSISTANT: {content}\n\n"
|
| 47 |
-
# Include explanations which often contain diagnostic reasoning
|
| 48 |
-
if "explanation" in message and message["explanation"]:
|
| 49 |
-
explanation = message.get("explanation", "").strip()
|
| 50 |
-
if explanation:
|
| 51 |
-
formatted_text += f"REASONING: {explanation}\n\n"
|
| 52 |
-
|
| 53 |
-
return formatted_text
|
| 54 |
|
| 55 |
|
| 56 |
# Function to encode images to base64 (similar to app.py)
|
|
@@ -461,91 +426,83 @@ def build_medical_report(data: dict) -> bytes:
|
|
| 461 |
|
| 462 |
|
| 463 |
def generate_and_download_report():
|
| 464 |
-
"""
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
|
| 468 |
-
|
| 469 |
-
st.session_state.pdf_data = None # Store PDF data for email
|
| 470 |
-
|
| 471 |
-
# Step 1: Collect patient name
|
| 472 |
if st.session_state.report_step == 1:
|
| 473 |
-
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
| 480 |
-
elif st.session_state.report_step == 2:
|
| 481 |
-
age = st.text_input("Patient Age:")
|
| 482 |
-
if st.button("Next"):
|
| 483 |
-
st.session_state.patient_info["age"] = age
|
| 484 |
-
st.session_state.report_step = 3
|
| 485 |
-
st.rerun()
|
| 486 |
-
|
| 487 |
-
# Step 3: Collect gender
|
| 488 |
-
elif st.session_state.report_step == 3:
|
| 489 |
-
gender = st.selectbox("Patient Gender:", ["Male", "Female", "Other", "Prefer not to say"])
|
| 490 |
if st.button("Generate Report"):
|
| 491 |
-
|
| 492 |
-
st.session_state.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 493 |
st.rerun()
|
| 494 |
-
|
| 495 |
-
# Step 4: Generate report
|
| 496 |
-
elif st.session_state.report_step == 4:
|
| 497 |
-
with st.spinner("Generating medical report..."):
|
| 498 |
-
# Format conversation with patient info - using the local format_conversation_history
|
| 499 |
-
conversation_text = format_conversation_history(
|
| 500 |
-
st.session_state.history,
|
| 501 |
-
st.session_state.patient_info
|
| 502 |
-
)
|
| 503 |
-
|
| 504 |
-
# Extract structured data
|
| 505 |
-
report_json = extract_medical_json(conversation_text)
|
| 506 |
-
|
| 507 |
-
# Override with collected patient info
|
| 508 |
-
report_json["patient"] = st.session_state.patient_info
|
| 509 |
-
report_json["visit_date"] = datetime.now().strftime("%Y-%m-%d")
|
| 510 |
-
|
| 511 |
-
# Generate PDF
|
| 512 |
-
pdf_bytes = build_medical_report(report_json)
|
| 513 |
-
st.session_state.pdf_data = pdf_bytes # Store PDF data for email
|
| 514 |
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
| 522 |
-
# Format the
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 526 |
st.download_button(
|
| 527 |
label="Download Report",
|
| 528 |
-
data=
|
| 529 |
-
file_name=f"
|
| 530 |
mime="application/pdf",
|
| 531 |
-
|
| 532 |
)
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
if st.button("Email Report"):
|
| 537 |
st.session_state.show_email_form = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 538 |
st.rerun()
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
# Button to start over
|
| 545 |
-
if st.button("Generate Another Report"):
|
| 546 |
-
st.session_state.report_step = 1
|
| 547 |
-
st.session_state.show_email_form = False
|
| 548 |
-
st.rerun()
|
| 549 |
|
| 550 |
|
| 551 |
def show_email_form():
|
|
|
|
| 14 |
from reportlab.platypus import PageBreak, KeepTogether
|
| 15 |
|
| 16 |
from model import orchestrator_chat
|
| 17 |
+
from utils import format_conversation_history
|
| 18 |
+
from session_state import get_full_history
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
|
| 21 |
# Function to encode images to base64 (similar to app.py)
|
|
|
|
| 426 |
|
| 427 |
|
| 428 |
def generate_and_download_report():
|
| 429 |
+
"""
|
| 430 |
+
Generate a medical report from the conversation history.
|
| 431 |
+
Shows a form for entering patient info and then allows downloading the report.
|
| 432 |
+
"""
|
| 433 |
+
# Step 1: Collect patient info
|
|
|
|
|
|
|
|
|
|
| 434 |
if st.session_state.report_step == 1:
|
| 435 |
+
st.text_input("Patient Name", key="patient_name",
|
| 436 |
+
value=st.session_state.patient_info.get("name", ""))
|
| 437 |
+
st.text_input("Age", key="patient_age",
|
| 438 |
+
value=st.session_state.patient_info.get("age", ""))
|
| 439 |
+
st.selectbox("Gender", ["Male", "Female", "Other"], key="patient_gender",
|
| 440 |
+
index=["Male", "Female", "Other"].index(st.session_state.patient_info.get("gender", "Male")))
|
| 441 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 442 |
if st.button("Generate Report"):
|
| 443 |
+
# Save patient info to session state
|
| 444 |
+
st.session_state.patient_info = {
|
| 445 |
+
"name": st.session_state.patient_name,
|
| 446 |
+
"age": st.session_state.patient_age,
|
| 447 |
+
"gender": st.session_state.patient_gender
|
| 448 |
+
}
|
| 449 |
+
st.session_state.report_step = 2
|
| 450 |
st.rerun()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 451 |
|
| 452 |
+
# Step 2: Generate and display report
|
| 453 |
+
elif st.session_state.report_step == 2:
|
| 454 |
+
with st.spinner("Generating report..."):
|
| 455 |
+
try:
|
| 456 |
+
# Get full conversation history from database
|
| 457 |
+
full_history = get_full_history()
|
| 458 |
+
|
| 459 |
+
# Format the conversation history for the report
|
| 460 |
+
formatted_conversation = format_conversation_history(
|
| 461 |
+
full_history,
|
| 462 |
+
st.session_state.patient_info
|
| 463 |
+
)
|
| 464 |
+
|
| 465 |
+
# Extract structured data from the conversation
|
| 466 |
+
medical_data = extract_medical_json(formatted_conversation)
|
| 467 |
+
|
| 468 |
+
# Update with patient info from the form
|
| 469 |
+
medical_data["patient"].update(st.session_state.patient_info)
|
| 470 |
+
|
| 471 |
+
# Set the visit date to today if not present
|
| 472 |
+
if not medical_data.get("visit_date"):
|
| 473 |
+
medical_data["visit_date"] = datetime.now().strftime("%Y-%m-%d")
|
| 474 |
+
|
| 475 |
+
# Generate PDF
|
| 476 |
+
pdf_data = build_medical_report(medical_data)
|
| 477 |
+
|
| 478 |
+
# Store PDF data in session state
|
| 479 |
+
st.session_state.pdf_data = pdf_data
|
| 480 |
+
|
| 481 |
+
# Create download button
|
| 482 |
st.download_button(
|
| 483 |
label="Download Report",
|
| 484 |
+
data=pdf_data,
|
| 485 |
+
file_name=f"medical_report_{st.session_state.patient_info['name'].replace(' ', '_')}.pdf",
|
| 486 |
mime="application/pdf",
|
| 487 |
+
use_container_width=True
|
| 488 |
)
|
| 489 |
+
|
| 490 |
+
# Show email option
|
| 491 |
+
if st.button("Email Report", use_container_width=True):
|
|
|
|
| 492 |
st.session_state.show_email_form = True
|
| 493 |
+
|
| 494 |
+
# Show email form if requested
|
| 495 |
+
if st.session_state.show_email_form:
|
| 496 |
+
show_email_form()
|
| 497 |
+
|
| 498 |
+
# Option to start over
|
| 499 |
+
if st.button("New Report", use_container_width=True):
|
| 500 |
+
st.session_state.report_step = 1
|
| 501 |
st.rerun()
|
| 502 |
+
|
| 503 |
+
except Exception as e:
|
| 504 |
+
st.error(f"Error generating report: {str(e)}")
|
| 505 |
+
st.button("Try Again", on_click=lambda: setattr(st.session_state, "report_step", 1))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
|
| 507 |
|
| 508 |
def show_email_form():
|