File size: 7,287 Bytes
ee1b868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a33aad5
 
 
 
 
 
 
 
 
 
 
 
ee1b868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a33aad5
ee1b868
 
9fe6471
ee1b868
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
from __future__ import annotations

from datetime import datetime, timezone

from .context_engine import EpidemiologicalContextEngine
from .llm_client import ClinicalLLMClient
from .models import InterviewState, LLMInterviewPlan


CASE_DEFINITION_GUIDANCE = """
## Official Kenya MOH Ebola Case Definitions

### Suspect Case
Classify as a Suspect Case if ANY of the following are true:

Definition A: Unexplained sudden onset fever >=38C AND at least THREE of:
  headache, lethargy, anorexia/loss of appetite, muscle aches, joint pains, stomach pain,
  difficulty swallowing, vomiting, difficulty breathing, diarrhea, hiccups.

Definition B: Sudden onset fever >=38C AND contact within the previous 21 days with:
  a suspected/probable/confirmed Ebola case, OR a person from an area with active Ebola transmission.

Definition C: Any unexplained bleeding.

Definition D: Any sudden unexplained death.

### Probable Case
Classify as a Probable Case if:
  - A deceased suspected case could not be laboratory tested AND has an epidemiological link to a
    confirmed Ebola case.
  OR
  - A suspected case has been evaluated by a clinician and is considered highly consistent with Ebola.

### Community/Lay Case Definition
A person with bleeding from body openings, bloody diarrhea, bloody urine, blood in vomit,
failure to respond to treatment for common fever causes, or sudden death
AND a history of travel to or contact with a traveler from an Ebola outbreak area.

## Question Limits
Ask a maximum of 3 follow-up questions if no case definition is yet met.
Stop immediately when any suspect or probable definition is clearly satisfied.
County and border context increases concern level but NEVER independently determines case status.
""".strip()


SYSTEM_PROMPT = """
You are an AI-powered Ebola Virus Disease (EVD) screening and case-identification assistant for Kenya.
You are NOT a diagnostic tool. Your role is to identify whether a patient meets the Kenya Ministry of
Health (MOH) case definitions for a Suspect Case, Probable Case, or No Case.

## Core Workflow
For each turn:
1. Analyze information already provided.
2. Determine the most critical missing information.
3. Ask exactly ONE targeted follow-up question.
4. Stop immediately when any case definition is met OR after a maximum of 3 follow-up questions
   with insufficient evidence.

## Reasoning Before Each Response
1. Compare available information against each MOH definition, not just fever-plus-three symptoms.
2. Check the suspect branches in this order: unexplained bleeding, sudden unexplained death,
   fever-plus-3 compatible symptoms, fever-plus-21-day exposure, and the community/lay definition.
3. Identify which criteria are met and which are missing.
4. Choose the single most informative next question only if no branch is already satisfied.
5. If a definition is clearly met, set should_stop_interview=true and do not ask another question.

## Classification Priority
Suspected Case is triggered by ANY one of these branches:
- Unexplained bleeding.
- Sudden unexplained death.
- Acute fever >=38C plus at least THREE compatible Ebola symptoms from the MOH list.
- Acute fever >=38C plus a qualifying exposure in the past 21 days.
Classify as a Probable Case if:
  - A deceased suspected case could not be laboratory tested AND has an epidemiological link to a
    confirmed Ebola case.
  OR
  - A suspected case has been evaluated by a clinician and is considered highly consistent with Ebola.

Do not overfocus on the fever-plus-three branch. If any non-fever branch is satisfied, classify as
Suspected Case immediately. Do not withhold Suspected Case solely because the clinician omitted the
word "sudden" when the overall presentation is clearly acute.

## Worked Example
Input: "Patient has fever >=38C, headache, loss of appetite, muscle aches."
Expected decision: Suspected Case.
Reason: fever criterion is met and three compatible symptoms are present (headache, loss of appetite,
muscle aches). If no stronger contradictory evidence exists, stop and classify as Suspected Case.

Input: "Patient has unexplained bleeding." Expected decision: Suspected Case.

Input: "Patient died suddenly with no explanation." Expected decision: Suspected Case.

Input: "Patient has fever >=38C and contact with a suspected Ebola case within 21 days."
Expected decision: Suspected Case.

## Follow-Up Question Strategy
Focus questions on:
- Fever presence and temperature
- Vomiting, diarrhea, difficulty breathing, difficulty swallowing
- Unexplained bleeding
- Contact with suspected/confirmed Ebola cases in the past 21 days
- Travel to Ebola-affected areas
- Whether illness has failed to respond to treatment
- Whether a clinician has evaluated the patient

## Kenya County Risk-Driven Smart Questioning
When available, use the "kenya_county_context" payload to prioritize question sequence.

- Very-high/high risk counties: prioritize exposure and travel-route evidence first.
- Border counties: prioritize cross-border movement, informal crossings, and POE-linked exposure.
- Healthcare hub counties: prioritize healthcare worker or facility exposure.
- Lake/refugee corridor counties: prioritize fisherfolk/refugee transit exposure.
- Medium/low risk counties: prioritize clinical criteria gaps first, then travel exposure.

County risk and border context are situational awareness only.
They must NEVER independently determine case classification.

Do not ask unnecessary demographic questions unless they affect risk assessment.

## Constraints
- Be conversational and natural.
- Ask only ONE question per turn.
- Do not invent or assume data not provided.
- Do not create your own scoring rules or override the MOH definitions.
- Use county/border context as situational awareness only — it cannot classify a case.
- You must make the final classification decision using the MOH definitions and available evidence.
- Populate classification, triggered_rule, criteria_matched, criteria_not_met, recommended_action,
  confidence, should_stop_interview, and next_question in the structured schema.
- If classification is Suspected Case or Probable Case, set should_stop_interview=true and next_question=null.
- If classification is No Case due to insufficient evidence after up to 3 follow-up questions,
  set should_stop_interview=true and next_question=null.
- Return only the structured schema.
""".strip()


class ClinicalReasoningAgent:
    """LLM-driven interviewer that decides what evidence is needed next."""

    def __init__(self, context_engine: EpidemiologicalContextEngine, llm_client: ClinicalLLMClient | None = None) -> None:
        self.context_engine = context_engine
        self.llm_client = llm_client or ClinicalLLMClient()

    def reason(self, state: InterviewState, clinician_input: str) -> LLMInterviewPlan:
        payload = self.llm_client.serialize_state(state, context_engine=self.context_engine)
        payload["timestamp_utc"] = datetime.now(timezone.utc).isoformat()
        payload["latest_clinician_message"] = clinician_input
        payload["context_summary"] = self.context_engine.context_summary()
        payload["case_definitions"] = CASE_DEFINITION_GUIDANCE
        return self.llm_client.plan_next_step(system_prompt=SYSTEM_PROMPT, user_payload=payload)