Spaces:
Sleeping
Sleeping
Create ClinicalStatusAgent.py
Browse files- ClinicalStatusAgent.py +60 -0
ClinicalStatusAgent.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class ClinicalStatusAgent:
|
| 2 |
+
def __init__(self, model: str = "gpt-4o"):
|
| 3 |
+
self.llm = ChatOpenAI(model=model, temperature=0)
|
| 4 |
+
self.agent = Agent(
|
| 5 |
+
role="Clinical Status Classifier",
|
| 6 |
+
goal="Determine the clinical status of confirmed diagnoses from patient chart excerpts.",
|
| 7 |
+
backstory="You are a meticulous clinical analyst. Your expertise lies in reviewing "
|
| 8 |
+
"medical documentation to classify a patient's condition as either active, "
|
| 9 |
+
"under monitoring, or purely historical.",
|
| 10 |
+
verbose=True,
|
| 11 |
+
memory=False,
|
| 12 |
+
llm=self.llm,
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
def determine_status_one(self, diagnosis_entry: dict) -> dict:
|
| 16 |
+
"""Determine the clinical status for a single confirmed diagnosis."""
|
| 17 |
+
diagnosis = diagnosis_entry["diagnosis"]
|
| 18 |
+
icd10 = diagnosis_entry["icd10"]
|
| 19 |
+
context = diagnosis_entry["context"]
|
| 20 |
+
|
| 21 |
+
task = Task(
|
| 22 |
+
description=(
|
| 23 |
+
f"Diagnosis: {diagnosis} (ICD-10: {icd10})\n\n"
|
| 24 |
+
f"Patient chart excerpts:\n{context}\n\n"
|
| 25 |
+
"Based *only* on the provided text, determine the Clinical Status of this diagnosis. "
|
| 26 |
+
"Choose exactly one of the following: {ACTIVE, MONITORING, HISTORICAL}.\n"
|
| 27 |
+
"- ACTIVE: The condition is currently under treatment, requires ongoing management, or is an acute issue.\n"
|
| 28 |
+
"- MONITORING: The condition is being watched via surveillance visits, follow-ups, or observation without active treatment.\n"
|
| 29 |
+
"- HISTORICAL: The condition is a past issue with no current clinical impact or management.\n\n"
|
| 30 |
+
"Output must be strict JSON:\n"
|
| 31 |
+
"{'clinical_status': 'ACTIVE/MONITORING/HISTORICAL', 'rationale': 'short justification for your choice'}"
|
| 32 |
+
),
|
| 33 |
+
expected_output="JSON with keys clinical_status and rationale",
|
| 34 |
+
agent=self.agent,
|
| 35 |
+
json_mode=True,
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
crew = Crew(agents=[self.agent], tasks=[task], process=Process.sequential, verbose=True)
|
| 39 |
+
result = crew.kickoff()
|
| 40 |
+
result = json.loads(repair_json(result))
|
| 41 |
+
|
| 42 |
+
return {
|
| 43 |
+
**diagnosis_entry,
|
| 44 |
+
"clinical_status": result.get("clinical_status"),
|
| 45 |
+
"status_rationale": result.get("rationale", "")
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
def run(self, confirmed_diagnoses: list[dict]) -> list[dict]:
|
| 49 |
+
"""Loop through all confirmed (yes) diagnoses and determine their clinical status."""
|
| 50 |
+
enriched_results = []
|
| 51 |
+
for entry in confirmed_diagnoses:
|
| 52 |
+
# CORRECTED: Checks for both explicit and implicit 'yes' answers
|
| 53 |
+
if entry.get("answer_explicit", "").lower() == "yes" or entry.get("answer_implicit", "").lower() == "yes":
|
| 54 |
+
print(f"\n[INFO] Determining clinical status for: {entry['diagnosis']} ({entry['icd10']})")
|
| 55 |
+
enriched = self.determine_status_one(entry)
|
| 56 |
+
enriched_results.append(enriched)
|
| 57 |
+
print(f"[STATUS RESULT] {enriched}")
|
| 58 |
+
else:
|
| 59 |
+
enriched_results.append(entry) # Pass through non-confirmed diagnoses
|
| 60 |
+
return enriched_results
|