Benedette Otieno
feat: Add Kenya county risk intelligence and integrate into epidemiological context
a33aad5 | title: Ebola Case Detection | |
| colorFrom: red | |
| colorTo: yellow | |
| sdk: gradio | |
| sdk_version: 6.16.0 | |
| app_file: app.py | |
| pinned: false | |
| python_version: "3.11" | |
| # Ebola Virus Disease Clinical Screening AI Agent | |
| Production-ready adaptive EVD screening agent for healthcare workers, built with Python, Pydantic, an LLM-driven reasoning layer, LangGraph, and Gradio. | |
| This agent performs dynamic clinical interviewing and classifies: | |
| - No Case | |
| - Suspected Case | |
| - Probable Case | |
| It does not classify Confirmed Case (laboratory confirmation is intentionally out of scope). | |
| ## 1) Solution Architecture | |
| ### Layer 1: Conversation Manager | |
| - Maintains session memory and full conversation history. | |
| - Tracks already asked questions and pending question. | |
| - Applies one-turn clinician input and returns one-turn agent output. | |
| ### Layer 2: LLM Clinical Reasoning Agent | |
| - Uses an LLM to summarize known evidence, identify missing evidence, extract structured facts, and choose the next best single question. | |
| - Adapts questioning dynamically to symptoms, travel, exposure, and epidemiological context. | |
| - Stops questioning when the model determines sufficient evidence has been gathered. | |
| ### Layer 3: Epidemiological Context Engine | |
| - Loads configurable outbreak context from JSON. | |
| - Computes proximity/context risk modifier from district, neighboring outbreaks, and alerts. | |
| - Prioritizes exposure questions earlier in high-risk context. | |
| ### Layer 4: Explainability Module | |
| - Generates structured, auditable rationale: | |
| - Classification | |
| - Evidence collected | |
| - Criteria/definition match explanation | |
| - Recommended action | |
| ## 2) Folder Structure | |
| ```text | |
| . | |
| ├── app.py | |
| ├── requirements.txt | |
| ├── data/ | |
| │ └── epi_context.sample.json | |
| ├── evd_agent/ | |
| │ ├── __init__.py | |
| │ ├── config.py | |
| │ ├── context_engine.py | |
| │ ├── conversation.py | |
| │ ├── explainability.py | |
| │ ├── graph.py | |
| │ ├── llm_client.py | |
| │ ├── models.py | |
| │ └── reasoning.py | |
| └── tests/ | |
| └── | |
| ``` | |
| ## 3) Data Models | |
| Implemented with Pydantic in `evd_agent/models.py`: | |
| - `PatientFacts`: structured interview variables (symptoms, exposure, death, lab availability, location). | |
| - `EpidemiologicalContext`: outbreak metadata and alerts. | |
| - `DecisionOutput`: classification, rule, evidence, action, confidence, stop flag. | |
| - `LLMInterviewPlan`: structured LLM output for evidence summary, fact updates, and next question. | |
| - `InterviewState`: full session state, asked questions, pending question, history. | |
| - `TurnResult`: structured output for each turn. | |
| ## 4) State Schema | |
| `InterviewState` fields: | |
| - `session_id`: unique UUID per session | |
| - `status`: in_progress | complete | |
| - `facts`: patient feature store | |
| - `context`: loaded epidemiological context | |
| - `history`: full clinician/assistant turns | |
| - `asked_questions`: dedup set | |
| - `followup_question_count`: tracks the max 3 follow-up questions rule | |
| - `pending_question_text`: next LLM-generated question | |
| - `decision`: current decision snapshot | |
| - `llm_summary`: latest reasoning summary from the model | |
| - `rationale_log`: extensible audit trail | |
| ## 5) Agent Workflow Diagram | |
| ```mermaid | |
| flowchart TD | |
| A[Clinician Input] --> B[Conversation Manager] | |
| B --> D[LLM Reasoning Agent] | |
| D --> E[Structured Fact Updates] | |
| E --> H{Case Definition Met? by LLM + MOH guidance} | |
| H -- Yes --> I[Suspected or Probable] | |
| H -- No --> J[LLM-Generated Next Question] | |
| I --> K[Explainability Module] | |
| J --> K | |
| K --> L[Gradio UI Panels + Chat] | |
| ``` | |
| LangGraph orchestration is implemented in `evd_agent/graph.py` with nodes: | |
| - `ingest_input` | |
| - `llm_reason` | |
| - `compose_response` | |
| ## 6) Clinical Reasoning Logic | |
| Clinical decisions are made directly by the LLM using Kenya MOH case definitions plus county context as supplemental situational awareness. | |
| County context influences question priority and concern level but does not independently classify a case. | |
| ## 7) Clinical Reasoning Workflow | |
| Suspected case triggers if any: | |
| - Unexplained bleeding. | |
| - Sudden unexplained death. | |
| - Fever >= 38C with at least 3 compatible symptoms. | |
| - Fever >= 38C with qualifying exposure in previous 21 days. | |
| Probable case triggers when all: | |
| - Deceased, | |
| - Meets suspected criteria, | |
| - Epidemiological linkage to known case, | |
| - Laboratory confirmation unavailable. | |
| Adaptive questioning behavior: | |
| - One question at a time. | |
| - Stops immediately once suspect/probable criteria are met. | |
| - Uses LLM reasoning to prioritize highest-value unresolved evidence. | |
| - Asks a maximum of 3 follow-up questions when no case definition is met. | |
| - Avoids duplicate questions through state tracking. | |
| ## 8) Gradio Implementation | |
| Gradio app in `app.py` includes: | |
| - Chat interface | |
| - Conversation history | |
| - Session memory (`gr.State` with `InterviewState`) | |
| - Classification panel | |
| - Epidemiological context panel | |
| - Alert banner | |
| - Reset button | |
| ## 9) Deployment Instructions | |
| ### Local run | |
| ```bash | |
| python -m venv .venv | |
| source .venv/bin/activate | |
| pip install -r requirements.txt | |
| python app.py | |
| ``` | |
| Open `http://localhost:7860`. | |
| ### Configurable context | |
| Set custom context file: | |
| ```bash | |
| export EVD_CONTEXT_PATH=/absolute/path/to/epi_context.json | |
| python app.py | |
| ``` | |
| ### LLM configuration | |
| Set an OpenAI-compatible model before starting the app. The UI will not launch without credentials, and the initial interview turn is generated by the LLM: | |
| ```bash | |
| export EVD_LLM_API_KEY=your_key_here | |
| export EVD_LLM_MODEL=gpt-4.1-mini | |
| python app.py | |
| ``` | |
| You can also use a local `.env` file (auto-loaded by the app): | |
| ```bash | |
| cp .env.example .env | |
| # edit .env with your real key | |
| python app.py | |
| ``` | |
| Optional custom endpoint: | |
| ```bash | |
| export EVD_LLM_BASE_URL=https://your-openai-compatible-endpoint | |
| python app.py | |
| ``` | |
| ### Container (example) | |
| ```dockerfile | |
| FROM python:3.12-slim | |
| WORKDIR /app | |
| COPY . . | |
| RUN pip install --no-cache-dir -r requirements.txt | |
| EXPOSE 7860 | |
| CMD ["python", "app.py"] | |
| ``` | |
| ## 10) Production Hardening Recommendations | |
| 1. Add authentication and role-based access control for surveillance users. | |
| 2. Encrypt data in transit and at rest (TLS + disk/database encryption). | |
| 3. Replace in-memory session state with durable backend store (PostgreSQL/Redis). | |
| 4. Add structured audit logging (classification path, timestamp, user identity, facility). | |
| 5. Add observability (metrics, traces, interview completion rates, escalation latency). | |
| 6. Add input validation guardrails and red-team testing for ambiguous narratives. | |
| 7. Add clinical governance versioning for case definitions by country/date. | |
| 8. Integrate notification adapters (SMS, DHIS2, surveillance endpoint APIs). | |
| 9. Add high-availability deployment and disaster recovery plan. | |
| 10. Add unit/integration/regression tests to CI/CD gates. | |
| ## 11) Complete Python Code | |
| All complete runnable code is included in this repository under: | |
| - `app.py` | |
| - `evd_agent/*.py` | |
| ## Notes on Clinical Scope | |
| - This system is a surveillance decision-support assistant and should be used under official public health protocols. | |
| - Confirmed case classification is intentionally excluded, pending laboratory diagnostics. |