112 lines
3.7 KiB
Python
112 lines
3.7 KiB
Python
from datetime import timedelta
|
|
from temporalio import workflow
|
|
|
|
with workflow.unsafe.imports_passed_through():
|
|
from .activities import (
|
|
structure_note_activity,
|
|
generate_billing_codes_activity,
|
|
analyze_lab_anomaly_activity,
|
|
send_alert_activity,
|
|
save_clinical_record_activity
|
|
)
|
|
|
|
@workflow.defn
|
|
class ClinicalIntakeWorkflow:
|
|
@workflow.run
|
|
async def run(self, raw_dictation: str) -> dict:
|
|
"""
|
|
Takes raw doctor's dictation, extracts structured clinical data,
|
|
and generates associated billing codes.
|
|
Returns the combined payload.
|
|
"""
|
|
# Step 1: AI Scribe (Structure the dictation)
|
|
structured_note = await workflow.execute_activity(
|
|
structure_note_activity,
|
|
raw_dictation,
|
|
start_to_close_timeout=timedelta(minutes=10)
|
|
)
|
|
|
|
# Step 2: Medical Coder (Generate ICD-10/CPT codes)
|
|
billing_codes = await workflow.execute_activity(
|
|
generate_billing_codes_activity,
|
|
structured_note,
|
|
start_to_close_timeout=timedelta(minutes=10)
|
|
)
|
|
|
|
# Step 3: Save to the client's database via ORM
|
|
save_payload = {
|
|
"raw_dictation": raw_dictation,
|
|
"clinical_note": structured_note,
|
|
"billing_codes": billing_codes
|
|
}
|
|
|
|
save_status = await workflow.execute_activity(
|
|
save_clinical_record_activity,
|
|
save_payload,
|
|
start_to_close_timeout=timedelta(minutes=1)
|
|
)
|
|
|
|
return {
|
|
"status": "success",
|
|
"db_status": save_status,
|
|
"clinical_note": structured_note,
|
|
"billing_codes": billing_codes
|
|
}
|
|
|
|
@workflow.defn
|
|
class LabResultWatcherWorkflow:
|
|
def __init__(self) -> None:
|
|
self._pending_lab_results = []
|
|
self._is_discharged = False
|
|
|
|
@workflow.signal
|
|
def add_lab_result(self, result: str) -> None:
|
|
self._pending_lab_results.append(result)
|
|
|
|
@workflow.signal
|
|
def discharge_patient(self) -> None:
|
|
self._is_discharged = True
|
|
|
|
@workflow.run
|
|
async def run(self, baseline_data: dict) -> dict:
|
|
"""
|
|
Runs continuously, processing new lab results via signals.
|
|
baseline_data: {"baseline": "...", "medications": ["..."]}
|
|
"""
|
|
alerts_triggered = 0
|
|
|
|
while not self._is_discharged:
|
|
# Wait until a new lab result arrives OR the patient is discharged
|
|
await workflow.wait_condition(
|
|
lambda: len(self._pending_lab_results) > 0 or self._is_discharged
|
|
)
|
|
|
|
# Process all pending results
|
|
while self._pending_lab_results:
|
|
new_result = self._pending_lab_results.pop(0)
|
|
|
|
input_data = {
|
|
"baseline": baseline_data.get("baseline", "None"),
|
|
"medications": baseline_data.get("medications", []),
|
|
"new_lab_result": new_result
|
|
}
|
|
|
|
anomaly_report = await workflow.execute_activity(
|
|
analyze_lab_anomaly_activity,
|
|
input_data,
|
|
start_to_close_timeout=timedelta(minutes=5)
|
|
)
|
|
|
|
if anomaly_report.get("is_dangerous", False):
|
|
await workflow.execute_activity(
|
|
send_alert_activity,
|
|
anomaly_report,
|
|
start_to_close_timeout=timedelta(minutes=1)
|
|
)
|
|
alerts_triggered += 1
|
|
|
|
return {
|
|
"status": "discharged",
|
|
"total_alerts_triggered": alerts_triggered
|
|
}
|