rivheal-docs

AI / ML Features

Last updated: 2026-05-30
All AI features are gated by ENABLE_AI_FEATURES=true (global) + hospitals.ai_features_enabled=true (per-tenant).


Feature Status Matrix

Feature Status Implementation Endpoint
Symptom Checker (rule-based fallback) βœ… Live SymptomCheckerService.analyzeWithRules() POST /symptom-checker/analyze
Symptom Checker (Claude LLM) βœ… Live* SymptomCheckerService.analyzeWithLlm() POST /symptom-checker/analyze
AI Health Assistant chat 🟑 Scaffold RasaService β†’ requires Rasa server POST /assistant/chat
Guest chat (no auth) 🟑 Scaffold RasaService POST /assistant/chat/guest
Multi-language support 🟑 Partial Urgency strings in 5 languages in rasa.service.ts β€”
Wait-time prediction 🟑 Proxy ready MlProxyService β†’ FastAPI; models not yet trained GET /predict/wait-time
No-show prediction 🟑 Proxy ready MlProxyService β†’ FastAPI; models not yet trained POST /predict/no-show
RivHealth Score βœ… Live* HealthScoreService formula-based GET /patients/:id/health-score
Lab trend alerts βœ… Live LabAlertsService β€” queries is_abnormal + is_critical GET /patients/:id/lab-alerts
Medication adherence tracking βœ… Live MedicationAdherenceService β€” dose log entity POST /medications/dose-logs/:id/log
Queue snapshot collection βœ… Live QueueSnapshotsService cron β€” every 15 min internal
Actual wait time persistence βœ… Live auto-computed on completeConsultation() internal
Outbreak detection ❌ Planned β€” β€”
Fraud detection ❌ Planned β€” β€”
Dynamic pricing ❌ Planned β€” β€”
Voice input (Nigerian accent) ❌ Planned β€” β€”
Wearables integration ❌ Planned β€” β€”

*Requires ENABLE_AI_FEATURES=true


Symptom Checker β€” LLM Flow

Endpoint: POST /symptom-checker/analyze
Auth: Public (guest OK)
Headers: x-guest-session-id: <uuid> (optional β€” persists result for merge after login)

Request:

{ "symptoms": ["fever", "cough", "fatigue"] }

Response:

{
  "triage": "medium",
  "suggestion": "Consult a doctor within 24 hours",
  "possibleConditions": ["Common cold", "Influenza", "Malaria", "Typhoid"]
}

Logic:

  1. If ANTHROPIC_API_KEY is set β†’ call Claude claude-haiku-4-5-20251001.
  2. System prompt instructs the model to return JSON with Nigerian-relevant conditions.
  3. On any LLM error β†’ fall back to keyword-matching rules.
  4. If x-guest-session-id header present β†’ save result to guest_symptom_checks table.

Wait-Time Prediction

Endpoint: GET /predict/wait-time?branchId=<uuid>
Auth: JWT
Headers: X-Hospital-Id: <uuid>

Response:

{
  "predictedWaitMinutes": 22,
  "confidence": 0.80,
  "isFallback": false
}

Architecture:

NestJS MlProxyService
  β”œβ”€β”€ Checks FeatureFlagsService.isAiEnabled(hospitalId)
  β”œβ”€β”€ Fetches current queue length from QueueSnapshotsService
  β”œβ”€β”€ POST http://ml-service:8000/predict/wait-time
  β”‚     { hour, dayOfWeek, queueLength, doctorAvgTime }
  └── On timeout/error β†’ returns { predictedWaitMinutes: 30, isFallback: true }

Training data collected:

Train a model:

cd rivheal-ml-service
python trainers/train.py --model wait_time --csv data/appointments.csv
# Saves models/wait_time_model.pkl
docker compose restart ml-service

RivHealth Score

Endpoint: GET /patients/:id/health-score
Auth: JWT
Feature flag: ENABLE_AI_FEATURES=true

Response:

{
  "score": 76,
  "riskLevel": "low",
  "breakdown": {
    "labScore": 85,
    "chronicConditionScore": 70,
    "appointmentAdherenceScore": 80
  },
  "computedAt": "2026-05-30T10:00:00Z"
}

Formula (v1):

score = labScore Γ— 0.35 + chronicConditionScore Γ— 0.35 + appointmentAdherenceScore Γ— 0.30

Medication Adherence

Endpoints:

Response (adherence stats):

{
  "total": 30,
  "taken": 25,
  "missed": 3,
  "skipped": 2,
  "adherenceRate": 83
}

Scheduling doses:
MedicationAdherenceService.scheduleDosesForPrescription() inserts dose logs at configured hours (8am, 8pm for twice-daily, etc.).


Lab Trend Alerts

Endpoint: GET /patients/:id/lab-alerts?limit=20
Auth: JWT

Returns all lab results where is_abnormal = true OR is_critical = true, sorted newest first.

[
  {
    "labResultId": "uuid",
    "testName": "Complete Blood Count",
    "isAbnormal": true,
    "isCritical": false,
    "interpretation": "WBC elevated",
    "reportedAt": "2026-05-28T09:00:00Z"
  }
]