Last updated: 2026-05-30
All AI features are gated byENABLE_AI_FEATURES=true(global) +hospitals.ai_features_enabled=true(per-tenant).
| 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
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:
ANTHROPIC_API_KEY is set β call Claude claude-haiku-4-5-20251001.x-guest-session-id header present β save result to guest_symptom_checks table.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:
queue_snapshots table β branch queue depth every 15 min.appointments.actual_wait_minutes β auto-persisted on consultation completion.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
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
Endpoints:
POST /medications/dose-logs/:doseLogId/log β Mark a dose as taken | skipped | missedGET /medications/prescriptions/:prescriptionId/dose-logs β Dose schedule for a prescriptionGET /patients/:id/adherence?from=&to= β Adherence rate over a date rangeResponse (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.).
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"
}
]