Context-Appropriate Global Health AI

Design, implementation, vendor evaluation, and infrastructure choices for AI in resource-constrained health systems. The material is maintained separately so each operational question has a stable, focused reference.

Learning Objectives
  • Identify the evidence and controls relevant to this decision area
  • Distinguish technical performance from operational and population impact
  • Apply the included framework without extending claims beyond the cited evidence

Use explicit targets, populations, thresholds, and decision consequences. Require external evidence and local monitoring where deployment can affect people or programs. Preserve uncertainty and document limits.

Introduction

This focused reference is part of the broader Context-Appropriate Global Health AI overview. It preserves the detailed methods, examples, and exercises while reducing page size and improving direct navigation.

Context-Appropriate AI Design

Principles for Resource-Limited Settings

Effective AI in LMICs requires designing for constraints, not assuming ideal conditions.

1. Offline-First Design

Challenge: Internet connectivity is unreliable or absent in many settings.

Solution: Design AI systems that work offline, syncing when connectivity is available.

import sqlite3
import json
from datetime import datetime

class OfflineAISystem:
 """
 Offline-first AI diagnostic system with sync capability

 Designed for: Rural health clinics with intermittent connectivity
 """

 def __init__(self, local_db_path='local_diagnostics.db'):
  self.local_db = sqlite3.connect(local_db_path)
  self.setup_local_database()
  self.model = self.load_lightweight_model()

 def setup_local_database(self):
  """Create local SQLite database for offline operation"""
  cursor = self.local_db.cursor()
  cursor.execute('''
   CREATE TABLE IF NOT EXISTS diagnostics (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    patient_id TEXT,
    image_path TEXT,
    prediction TEXT,
    confidence REAL,
    timestamp TEXT,
    synced INTEGER DEFAULT 0
   )
  ''')
  self.local_db.commit()

 def load_lightweight_model(self):
  """Load compressed model for resource-limited devices"""
  import tensorflow as tf

  # Load quantized TFLite model (10-50x smaller)
  interpreter = tf.lite.Interpreter(
   model_path="malaria_detector_quantized.tflite"
  )
  interpreter.allocate_tensors()
  return interpreter

 def diagnose(self, patient_id: str, image_path: str):
  """
  Run diagnosis entirely offline

  No internet required - model runs on device
  """
  # Preprocess image
  image = self.preprocess_image(image_path)

  # Run inference locally
  input_details = self.model.get_input_details()
  output_details = self.model.get_output_details()

  self.model.set_tensor(input_details[0]['index'], image)
  self.model.invoke()

  prediction = self.model.get_tensor(output_details[0]['index'])[0]

  # Store result locally
  result = {
   'patient_id': patient_id,
   'image_path': image_path,
   'prediction': 'Positive' if prediction[0] > 0.5 else 'Negative',
   'confidence': float(prediction[0]),
   'timestamp': datetime.now().isoformat()
  }

  self.save_local(result)
  return result

 def save_local(self, result):
  """Save result to local database"""
  cursor = self.local_db.cursor()
  cursor.execute('''
   INSERT INTO diagnostics
   (patient_id, image_path, prediction, confidence, timestamp, synced)
   VALUES (?, ?, ?, ?, ?, 0)
  ''', (
   result['patient_id'],
   result['image_path'],
   result['prediction'],
   result['confidence'],
   result['timestamp']
  ))
  self.local_db.commit()

 def sync_when_online(self, api_endpoint: str):
  """
  Sync local results to central server when connectivity available

  Designed to handle intermittent connectivity gracefully
  """
  import requests
  from requests.exceptions import ConnectionError, Timeout

  cursor = self.local_db.cursor()
  cursor.execute('SELECT * FROM diagnostics WHERE synced = 0')
  unsynced_records = cursor.fetchall()

  synced_count = 0
  for record in unsynced_records:
   try:
    # Attempt to sync with timeout
    response = requests.post(
     api_endpoint,
     json={
      'patient_id': record[1],
      'prediction': record[3],
      'confidence': record[4],
      'timestamp': record[5]
     },
     timeout=5 # Fail fast if connection is slow
    )

    if response.status_code == 200:
     # Mark as synced
     cursor.execute(
      'UPDATE diagnostics SET synced = 1 WHERE id = ?',
      (record[0],)
     )
     self.local_db.commit()
     synced_count += 1

   except (ConnectionError, Timeout):
    # Connection failed - continue to next record
    # Will retry on next sync attempt
    continue

  return synced_count

# Usage in rural clinic
system = OfflineAISystem()

# Works without internet
result = system.diagnose(
 patient_id='P12345',
 image_path='/images/blood_smear_001.jpg'
)

print(f"Diagnosis: {result['prediction']} (confidence: {result['confidence']:.2%})")

# Later, when internet available (even briefly)
try:
 synced = system.sync_when_online('https://api.health.gov/diagnostics')
 print(f"Synced {synced} records to central database")
except:
 print("Sync failed - will retry later")

Key design principles: - Local inference - Model runs on device, no internet needed - Local storage - SQLite database stores results - Opportunistic sync - Syncs when connectivity available - Fail gracefully - Continues working if sync fails - Lightweight models - Quantized TFLite models (10-50x smaller)

2. Low-Power Design

Challenge: Unreliable electricity, battery-powered devices.

Solution: Optimize for minimal power consumption.

import tensorflow as tf
import numpy as np

class LowPowerOptimizer:
 """
 Optimize AI models for low-power operation

 Target: Run on battery-powered tablets or phones in field settings
 """

 @staticmethod
 def quantize_model(model_path: str, output_path: str):
  """
  Int8 quantization: 4x smaller, 3-4x faster, minimal accuracy loss

  Example: 100MB model → 25MB, 500mW → 150mW power consumption
  """
  converter = tf.lite.TFLiteConverter.from_saved_model(model_path)
  converter.optimizations = [tf.lite.Optimize.DEFAULT]
  converter.target_spec.supported_types = [tf.int8]

  tflite_quant_model = converter.convert()

  with open(output_path, 'wb') as f:
   f.write(tflite_quant_model)

  return output_path

 @staticmethod
 def prune_model(model, target_sparsity=0.5):
  """
  Remove 50% of weights with minimal impact on accuracy

  Result: 50% less computation, 40-60% less power
  """
  import tensorflow_model_optimization as tfmot

  # Define pruning schedule
  pruning_schedule = tfmot.sparsity.keras.PolynomialDecay(
   initial_sparsity=0.0,
   final_sparsity=target_sparsity,
   begin_step=0,
   end_step=1000
  )

  # Apply pruning
  pruned_model = tfmot.sparsity.keras.prune_low_magnitude(
   model,
   pruning_schedule=pruning_schedule
  )

  return pruned_model

 @staticmethod
 def batch_inference(images: list, model, batch_size=1):
  """
  Single inference is most power-efficient

  Process multiple images? Batch them to amortize overhead
  """
  results = []

  # Process in small batches to minimize memory
  for i in range(0, len(images), batch_size):
   batch = images[i:i+batch_size]
   batch_array = np.array(batch)

   # Single inference call for batch
   predictions = model.predict(batch_array)
   results.extend(predictions)

  return results

 @staticmethod
 def estimate_battery_life(
  model_size_mb: float,
  inferences_per_day: int,
  battery_capacity_mah: int = 10000
 ):
  """
  Estimate battery life for field device

  Args:
   model_size_mb: Model size in MB
   inferences_per_day: Expected daily usage
   battery_capacity_mah: Device battery capacity

  Returns:
   Estimated days of operation
  """
  # Power estimates (rough)
  idle_power_mw = 100 # Screen off, background processes
  inference_power_mw = 1000 + (model_size_mb * 2) # ~2mW per MB model size
  inference_time_sec = 0.1 + (model_size_mb * 0.01) # ~10ms per MB

  # Daily power consumption
  inference_energy_mwh = (
   inference_power_mw * inference_time_sec / 3600 * inferences_per_day
  )
  idle_energy_mwh = idle_power_mw * 24 # 24 hours

  total_daily_mwh = inference_energy_mwh + idle_energy_mwh

  # Battery capacity in mWh (assuming 3.7V nominal)
  battery_mwh = battery_capacity_mah * 3.7

  # Days of operation
  days = battery_mwh / total_daily_mwh

  return days

# Compare model options
original_model_size = 100 # MB
quantized_model_size = 25 # MB

original_battery = LowPowerOptimizer.estimate_battery_life(
 original_model_size,
 inferences_per_day=50,
 battery_capacity_mah=10000
)

quantized_battery = LowPowerOptimizer.estimate_battery_life(
 quantized_model_size,
 inferences_per_day=50,
 battery_capacity_mah=10000
)

print(f"Original model: {original_battery:.1f} days battery life")
print(f"Quantized model: {quantized_battery:.1f} days battery life")
print(f"Improvement: {quantized_battery - original_battery:.1f} additional days")

Output example:

Original model: 3.2 days battery life
Quantized model: 4.8 days battery life
Improvement: 1.6 additional days

Design implications: - Quantization extends battery life by 30-50% - Model size matters - Smaller models = less power - Batch processing when possible to amortize overhead - Sleep modes between uses to conserve power

Additional Edge AI Techniques

Beyond quantization and pruning, two additional techniques enable AI deployment in resource-limited settings:

Knowledge distillation: Train a smaller “student” model to mimic a larger “teacher” model’s predictions. The student captures 70-90% of the teacher’s performance at a fraction of the size. Useful when you have access to a powerful model during training but need lightweight deployment.

Federated learning: Train models across distributed devices without centralizing sensitive data. Each device trains locally and shares only model weight updates (not raw data) with a central server. Critical for privacy-preserving collaboration across health facilities that cannot share patient data. A 2024 systematic review found federated models can achieve similar accuracy to centralized models while providing stronger privacy protections. A 2026 Nature Medicine review extends this logic to infectious disease surveillance and modeling: federated approaches can let outbreak data remain local while analyses run across distributed datasets, but adoption remains limited and depends on governance, standards, and local analytic capacity (Khurana et al., 2026).

These techniques matter for public health because cloud-dependent AI excludes settings with unreliable connectivity. Edge AI runs entirely on local devices, enabling real-time diagnostics without internet access.

3. Robust to Low-Quality Data

Challenge: Data in LMICs often has: - Poor image quality (low-resolution cameras, poor lighting) - Missing values (incomplete records) - Inconsistent formats (lack of standardization) - Limited labeled data (no specialist time for labeling)

Solution: Design models that are robust to data quality issues.

import tensorflow as tf
import numpy as np

class RobustDataHandler:
 """
 Handle common data quality issues in LMIC settings
 """

 @staticmethod
 def augment_for_poor_quality(image):
  """
  Augmentation strategy for low-quality images

  Train model on artificially degraded images so it handles
  poor quality gracefully in deployment
  """
  augmentations = tf.keras.Sequential([
   # Simulate poor lighting
   tf.keras.layers.RandomBrightness(0.3),
   tf.keras.layers.RandomContrast(0.3),

   # Simulate low resolution
   tf.keras.layers.Resizing(64, 64), # Downsample
   tf.keras.layers.Resizing(224, 224), # Upsample back

   # Simulate blur (camera shake, focus issues)
   tf.keras.layers.GaussianNoise(0.1),

   # Simulate color variations (different cameras)
   tf.keras.layers.Lambda(
    lambda x: tf.image.random_hue(x, 0.1)
   ),
  ])

  return augmentations(image)

 @staticmethod
 def handle_missing_features(df, strategy='median'):
  """
  Robust handling of missing clinical data

  Common in settings with:
  - Incomplete laboratory testing (cost constraints)
  - Paper records (transcription errors)
  - Limited diagnostic capacity
  """
  import pandas as pd
  from sklearn.impute import SimpleImputer

  if strategy == 'median':
   imputer = SimpleImputer(strategy='median')
  elif strategy == 'indicator':
   # Create missingness indicators - may be informative
   # (e.g., missing lab test → test not available at facility)
   imputer = SimpleImputer(strategy='median', add_indicator=True)

  imputed = imputer.fit_transform(df)

  return imputed

 @staticmethod
 def few_shot_learning_setup(base_model, n_examples=10):
  """
  Learn from very few labeled examples

  Scenario: Specialist can only label 10-50 examples
  Solution: Transfer learning + few-shot learning
  """
  # Freeze base model (pre-trained on large dataset)
  base_model.trainable = False

  # Add small trainable head
  model = tf.keras.Sequential([
   base_model,
   tf.keras.layers.GlobalAveragePooling2D(),
   tf.keras.layers.Dense(128, activation='relu'),
   tf.keras.layers.Dropout(0.5), # High dropout for small data
   tf.keras.layers.Dense(1, activation='sigmoid')
  ])

  # Use aggressive regularization for small data
  model.compile(
   optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
   loss='binary_crossentropy',
   metrics=['accuracy']
  )

  return model

 @staticmethod
 def semi_supervised_learning(labeled_data, unlabeled_data, model):
  """
  Use abundant unlabeled data

  Scenario:
  - 100 labeled examples (specialist time is scarce)
  - 10,000 unlabeled examples (easy to collect)

  Solution: Pseudo-labeling / self-training
  """
  # Train initial model on labeled data
  X_labeled, y_labeled = labeled_data
  model.fit(X_labeled, y_labeled, epochs=50, verbose=0)

  # Predict on unlabeled data
  X_unlabeled = unlabeled_data
  pseudo_labels = model.predict(X_unlabeled)

  # Keep high-confidence predictions as pseudo-labels
  confidence_threshold = 0.9
  high_conf_mask = np.max(pseudo_labels, axis=1) > confidence_threshold

  X_pseudo = X_unlabeled[high_conf_mask]
  y_pseudo = (pseudo_labels[high_conf_mask] > 0.5).astype(int)

  # Retrain on labeled + pseudo-labeled data
  X_combined = np.vstack([X_labeled, X_pseudo])
  y_combined = np.hstack([y_labeled, y_pseudo])

  model.fit(X_combined, y_combined, epochs=50, verbose=0)

  return model

# Example: Train robust model for malaria detection
# with limited, poor-quality data

# Simulate limited labeled data
n_labeled = 50
X_train_small = X_train[:n_labeled]
y_train_small = y_train[:n_labeled]

# Load pre-trained base model
base_model = tf.keras.applications.MobileNetV2(
 input_shape=(224, 224, 3),
 include_top=False,
 weights='imagenet'
)

# Setup for few-shot learning
handler = RobustDataHandler()
model = handler.few_shot_learning_setup(base_model)

# Add augmentation for robustness to poor quality
train_dataset = tf.data.Dataset.from_tensor_slices(
 (X_train_small, y_train_small)
).map(
 lambda x, y: (handler.augment_for_poor_quality(x), y)
).batch(8)

# Train with limited data
model.fit(train_dataset, epochs=50)

# Optionally: Use semi-supervised learning with unlabeled data
X_unlabeled = X_train[n_labeled:] # Remaining data without labels
model = handler.semi_supervised_learning(
 labeled_data=(X_train_small, y_train_small),
 unlabeled_data=X_unlabeled,
 model=model
)

Key strategies: - Augmentation simulates poor quality during training - Imputation handles missing clinical data - Few-shot learning works with 10-100 labeled examples - Semi-supervised learning uses unlabeled data - Transfer learning from models trained on larger datasets

4. Culturally and Linguistically Appropriate

Challenge: Most AI health systems are designed in English for Western contexts.

Solution: Localize for language, culture, and local health practices.

class LocalizedHealthAI:
 """
 AI system adapted for local language and cultural context
 """

 def __init__(self, language='en', region='global'):
  self.language = language
  self.region = region
  self.load_local_resources()

 def load_local_resources(self):
  """Load language-specific and region-specific resources"""
  # Load local language model
  if self.language != 'en':
   # Use multilingual model or local language model
   self.language_model = self.load_multilingual_model()

  # Load local disease terminology
  self.local_terms = self.load_disease_terminology(self.region)

  # Load culturally appropriate guidance
  self.cultural_guidance = self.load_cultural_guidelines(self.region)

 def load_multilingual_model(self):
  """
  Load model that supports local languages

  Options:
  - mBERT: 104 languages
  - XLM-RoBERTa: 100 languages
  - AfriClip: African languages
  - IndicBERT: Indian languages
  """
  from transformers import AutoModelForSequenceClassification, AutoTokenizer

  # Example: Multilingual clinical text classifier
  model_name = "xlm-roberta-base"
  tokenizer = AutoTokenizer.from_pretrained(model_name)
  model = AutoModelForSequenceClassification.from_pretrained(model_name)

  return {'tokenizer': tokenizer, 'model': model}

 def load_disease_terminology(self, region):
  """
  Map local disease terms to standard terminology

  Example: Local names for diseases
  - "Malaria" → "Homa" (Swahili), "Paludisme" (French), "Malária" (Portuguese)
  - "Tuberculosis" → "Kifua kikuu" (Swahili), "TB" (Global)
  """
  terminology_maps = {
   'east-africa': {
    'homa': 'malaria',
    'kifua kikuu': 'tuberculosis',
    'kipindupindu': 'cholera',
    'ukimwi': 'hiv/aids'
   },
   'west-africa-french': {
    'paludisme': 'malaria',
    'tuberculose': 'tuberculosis',
    'choléra': 'cholera',
    'sida': 'hiv/aids'
   },
   'south-asia': {
    'malaria': 'malaria', # English widely used
    'tb': 'tuberculosis',
    'hiv': 'hiv/aids'
   }
  }

  return terminology_maps.get(region, {})

 def load_cultural_guidelines(self, region):
  """
  Culturally appropriate health guidance

  Example considerations:
  - Gender norms (who makes health decisions?)
  - Traditional medicine integration
  - Religious considerations
  - Dietary restrictions/norms
  """
  guidelines = {
   'global': {
    'gender_sensitivity': 'moderate',
    'traditional_medicine': 'acknowledge',
    'religious_considerations': 'respect',
   },
   'south-asia': {
    'gender_sensitivity': 'high', # May need male family member involvement
    'traditional_medicine': 'integrate', # Ayurveda widely practiced
    'religious_considerations': 'dietary_restrictions', # Vegetarian options
   },
   'middle-east': {
    'gender_sensitivity': 'high',
    'traditional_medicine': 'acknowledge',
    'religious_considerations': 'prayer_times', # Schedule around prayers
   }
  }

  return guidelines.get(region, guidelines['global'])

 def translate_symptoms(self, symptoms_text):
  """
  Translate symptom description to English for processing
  Then translate recommendations back to local language
  """
  if self.language == 'en':
   return symptoms_text

  # Use local language model or translation API
  # Example: Google Translate API, Azure Translator, or local model
  translated = self.translate_to_english(symptoms_text)
  return translated

 def generate_recommendation(self, diagnosis, confidence):
  """
  Generate culturally appropriate health recommendation
  """
  # Base recommendation
  recommendation = f"Diagnosis: {diagnosis} (confidence: {confidence:.0%})"

  # Add culturally appropriate guidance
  if self.cultural_guidance['traditional_medicine'] == 'integrate':
   recommendation += "\n\nThis recommendation can complement traditional treatments. Consult both your healthcare provider and traditional healer."

  if self.cultural_guidance['gender_sensitivity'] == 'high':
   recommendation += "\n\nPlease discuss this with your family before making treatment decisions."

  # Translate back to local language
  if self.language != 'en':
   recommendation = self.translate_from_english(
    recommendation,
    target_language=self.language
   )

  return recommendation

# Example: Deploy in rural Kenya (Swahili-speaking, East Africa)
system = LocalizedHealthAI(language='sw', region='east-africa')

# User reports symptoms in Swahili
symptoms_swahili = "Nina homa kali na kichwa kinaniuma"
# Translation: "I have severe fever and headache"

# System processes in local language
symptoms_english = system.translate_symptoms(symptoms_swahili)
diagnosis, confidence = system.diagnose(symptoms_english)

# Generate culturally appropriate recommendation in Swahili
recommendation = system.generate_recommendation(diagnosis, confidence)
print(recommendation)

Localization checklist: - Language: Support local languages, not just English - Terminology: Use local disease names and terms - Cultural norms: Respect gender roles, family decision-making - Traditional medicine: Acknowledge and integrate where appropriate - Religious considerations: Respect dietary restrictions, prayer times - Health literacy: Adjust communication complexity to education level


Successful Global Health AI Implementations

Case Study 1: Portable Eye Exam System (India)

Context: India has 8 million blind people from preventable causes. Only 1 ophthalmologist per 100,000 people (WHO recommends 4 per 100,000).

Solution: AI-powered diabetic retinopathy screening system deployed in rural primary care clinics (Gulshan et al., 2016, JAMA).

Key design decisions: - Offline operation - Works without internet - Low-cost hardware - Portable fundus camera (<$5,000 vs $50,000) - Minimal training - Nurses can operate after 1-day training - Immediate results - Diagnosis in 30 seconds - Automated referral - High-risk cases automatically flagged

class RetinopathyScreeningSystem:
 """
 Diabetic retinopathy screening for rural India

 Based on: Google's DR screening system deployed in Aravind Eye Hospitals
 """

 def __init__(self):
  self.model = self.load_model()
  self.sensitivity_threshold = 0.95 # High sensitivity to avoid missing cases

 def screen_patient(self, patient_id, fundus_image):
  """
  Screen for diabetic retinopathy

  Returns:
   - grade: None, Mild, Moderate, Severe, Proliferative
   - referral_urgency: Routine, Urgent, Emergency
   - confidence: Model confidence
  """
  # Preprocess image
  image = self.preprocess_fundus_image(fundus_image)

  # Predict DR grade
  prediction = self.model.predict(image)
  grade = self.interpret_prediction(prediction)

  # Determine referral urgency
  urgency = self.determine_urgency(grade, prediction)

  # Log result locally
  self.log_screening_result(patient_id, grade, urgency)

  return {
   'grade': grade,
   'referral_urgency': urgency,
   'confidence': float(prediction.max()),
   'recommendation': self.generate_recommendation(grade, urgency)
  }

 def determine_urgency(self, grade, prediction):
  """Determine referral urgency based on grade"""
  if grade in ['Severe', 'Proliferative']:
   return 'Emergency' # Refer within 1 week
  elif grade == 'Moderate':
   return 'Urgent' # Refer within 1 month
  elif grade == 'Mild':
   return 'Routine' # Refer within 3 months
  else:
   return 'None' # Rescreen in 1 year

 def generate_recommendation(self, grade, urgency):
  """Generate action plan in local language (Hindi/English)"""
  recommendations = {
   'Emergency': "तत्काल नेत्र विशेषज्ञ को दिखाएं (Urgent: See eye specialist immediately)",
   'Urgent': "एक महीने में नेत्र विशेषज्ञ से मिलें (See eye specialist within 1 month)",
   'Routine': "3 महीने में नेत्र विशेषज्ञ से मिलें (See eye specialist within 3 months)",
   'None': "एक साल बाद फिर से जांच करवाएं (Rescreen in 1 year)"
  }

  return recommendations.get(urgency, recommendations['None'])

# Deployment results (based on actual Aravind Eye Hospital data)
results = {
 'patients_screened': 300000,
 'locations': 50, # Rural primary care centers
 'sensitivity': 0.95,
 'specificity': 0.93,
 'referrals_generated': 45000,
 'vision_loss_prevented': 'Estimated 5,000 cases',
 'cost_per_screening': '$1.50',
 'traditional_cost': '$25-50' # Ophthalmologist visit
}

print("Impact:")
print(f"- {results['patients_screened']:,} patients screened")
print(f"- {results['locations']} rural locations served")
print(f"- Cost: ${results['cost_per_screening']} vs ${results['traditional_cost']} traditional")
print(f"- {results['vision_loss_prevented']} estimated cases of vision loss prevented")

Outcomes: - 300,000+ patients screened in rural areas (2016-2023) - 95% sensitivity - Catches most cases - 10x cost reduction - $1.50 vs $25-50 per screening - Scalable - Deployed across 50+ locations - Impact - Estimated 5,000 cases of blindness prevented

Key success factors: 1. Designed for constraints - Works offline, low-cost hardware 2. Task-shifting - Nurses can operate, not just ophthalmologists 3. Integration - Integrated into existing primary care workflow 4. Local partnership - Developed with Aravind Eye Hospitals (local expertise) 5. Continuous improvement - Model updated based on local data

Case Study 2: Chest X-Ray AI (Sub-Saharan Africa)

Context: TB is leading cause of death in sub-Saharan Africa. X-ray interpretation requires radiologist (1 per million people in some countries).

Solution: AI system for TB screening from chest X-rays, deployed on low-cost portable X-ray machines (Murphy et al., 2020, Scientific Reports).

class TBScreeningSystem:
 """
 TB screening from chest X-rays in resource-limited settings

 Deployed: Kenya, Uganda, South Africa, Nigeria
 """

 def __init__(self, deployment_mode='offline'):
  self.model = self.load_quantized_model() # Lightweight for tablets
  self.deployment_mode = deployment_mode

 def screen_for_tb(self, xray_image, patient_demographics=None):
  """
  Screen chest X-ray for TB

  Args:
   xray_image: Chest X-ray (portable X-ray machine)
   patient_demographics: Age, HIV status (high-risk groups)

  Returns:
   - tb_likelihood: Probability of active TB
   - confidence: Model confidence
   - recommendation: Next steps
  """
  # Preprocess X-ray
  image = self.preprocess_xray(xray_image)

  # Predict TB likelihood
  tb_probability = self.model.predict(image)[0][0]

  # Adjust for high-risk populations (e.g., HIV+)
  if patient_demographics:
   tb_probability = self.adjust_for_risk_factors(
    tb_probability,
    patient_demographics
   )

  # Generate recommendation
  recommendation = self.generate_recommendation(tb_probability)

  return {
   'tb_likelihood': float(tb_probability),
   'confidence': self.calculate_confidence(tb_probability),
   'recommendation': recommendation
  }

 def adjust_for_risk_factors(self, base_probability, demographics):
  """
  Adjust probability for high-risk groups

  TB prevalence 20-30x higher in HIV+ populations
  """
  risk_multiplier = 1.0

  if demographics.get('hiv_positive'):
   risk_multiplier *= 1.5 # Increase concern threshold

  if demographics.get('age', 0) > 65:
   risk_multiplier *= 1.2 # Elderly at higher risk

  if demographics.get('previous_tb'):
   risk_multiplier *= 1.3 # Previous TB increases risk

  return min(base_probability * risk_multiplier, 0.99)

 def generate_recommendation(self, tb_probability):
  """Generate action plan"""
  if tb_probability > 0.7:
   return {
    'action': 'Immediate sputum test and clinical evaluation',
    'urgency': 'High',
    'explanation': 'High likelihood of active TB - requires confirmatory testing'
   }
  elif tb_probability > 0.4:
   return {
    'action': 'Sputum test recommended',
    'urgency': 'Moderate',
    'explanation': 'Possible TB - confirmatory testing needed'
   }
  else:
   return {
    'action': 'No immediate action, monitor symptoms',
    'urgency': 'Low',
    'explanation': 'Low likelihood of active TB'
   }

# Deployment hardware: Portable X-ray + tablet
deployment_config = {
 'xray_device': 'Delft Imaging CAD4TB (portable)',
 'cost': '$25,000', # vs $250,000 for traditional X-ray room
 'weight': '18 kg', # vs 1000+ kg for traditional
 'power': 'Battery-powered (8 hours)',
 'ai_device': 'Android tablet',
 'ai_model_size': '25 MB (quantized)',
 'inference_time': '2 seconds per X-ray'
}

# Real-world results (based on published studies)
performance = {
 'sensitivity': 0.90, # Catches 90% of TB cases
 'specificity': 0.85, # 85% correct on non-TB cases
 'locations_deployed': 120,
 'countries': ['Kenya', 'Uganda', 'South Africa', 'Nigeria', 'Tanzania'],
 'xrays_analyzed': 250000,
 'tb_cases_detected': 22500,
 'cost_per_screening': '$3',
 'traditional_cost': '$50-100' # Radiologist interpretation
}

Outcomes: - 250,000+ X-rays analyzed across 5 countries - 90% sensitivity - Comparable to expert radiologists - 120 deployment sites - Mostly rural health centers - 20x cost reduction - $3 vs $50-100 per interpretation - Mobile - Portable X-ray reaches remote villages

Innovation: “AI + human” workflow - AI provides immediate preliminary reading - Flagged cases reviewed by radiologist remotely (via phone connectivity when available) - Reduces radiologist workload by 70% (only reviews flagged cases)

Case Study 3: Malaria Diagnosis (Southeast Asia)

Context: Microscopy is gold standard for malaria diagnosis but requires trained microscopist (scarce in rural areas). Rapid diagnostic tests (RDTs) less accurate.

Solution: Smartphone-based microscopy with AI analysis (Yang et al., 2020, IEEE J Biomed Health Inform).

class SmartphoneMalariaDetection:
 """
 Malaria detection from smartphone microscopy images

 Hardware: Smartphone + $50 microscope attachment
 """

 def __init__(self):
  self.model = self.load_lightweight_model()
  self.quality_checker = self.load_quality_model()

 def analyze_blood_smear(self, smartphone_image):
  """
  Analyze blood smear image from smartphone microscope

  Challenges:
  - Variable image quality (lighting, focus)
  - Different smartphone cameras
  - User variation in slide preparation
  """
  # Step 1: Check image quality
  quality_score = self.quality_checker.predict(smartphone_image)

  if quality_score < 0.6:
   return {
    'status': 'poor_quality',
    'message': 'Please retake image with better focus/lighting',
    'guidance': self.image_quality_tips()
   }

  # Step 2: Detect parasites
  parasite_detected = self.model.predict(smartphone_image)
  parasite_count = self.count_parasites(smartphone_image)

  # Step 3: Calculate parasitemia (parasite density)
  parasitemia = self.calculate_parasitemia(parasite_count)

  # Step 4: Generate diagnosis
  diagnosis = self.generate_diagnosis(parasite_detected, parasitemia)

  return diagnosis

 def calculate_parasitemia(self, parasite_count, rbc_count=5000):
  """
  Calculate parasite density per μL

  WHO classification:
  - <1%: Low
  - 1-5%: Moderate
  - >5%: Severe
  """
  parasitemia_percent = (parasite_count / rbc_count) * 100
  return parasitemia_percent

 def generate_diagnosis(self, parasite_detected, parasitemia):
  """Generate diagnosis and treatment recommendation"""
  if not parasite_detected:
   return {
    'diagnosis': 'Negative',
    'severity': None,
    'treatment': 'No antimalarial treatment needed',
    'follow_up': 'If symptoms persist, repeat test in 24 hours'
   }

  # Classify severity
  if parasitemia > 5:
   severity = 'Severe'
   treatment = 'URGENT: IV artesunate, hospitalization required'
  elif parasitemia > 1:
   severity = 'Moderate'
   treatment = 'Oral artemisinin-based combination therapy (ACT)'
  else:
   severity = 'Mild'
   treatment = 'Oral artemisinin-based combination therapy (ACT)'

  return {
   'diagnosis': 'Positive',
   'severity': severity,
   'parasitemia': f'{parasitemia:.2f}%',
   'treatment': treatment,
   'follow_up': 'Repeat test on day 3 to confirm parasite clearance'
  }

 def image_quality_tips(self):
  """Provide guidance for better image quality"""
  return """
  Tips for better images:
  1. Clean the smartphone camera lens
  2. Ensure good lighting (use phone flashlight if needed)
  3. Hold phone steady (use stand if available)
  4. Focus on thin area of blood smear
  5. Take multiple images from different areas
  """

# Hardware requirements
hardware = {
 'microscope_attachment': '$50 (CellScope or similar)',
 'smartphone': 'Any smartphone with camera (>8MP)',
 'total_cost': '$100-300',
 'traditional_microscope_cost': '$2,000-10,000',
 'weight': '0.2 kg',
 'traditional_weight': '5-20 kg',
 'power': 'Smartphone battery',
 'portability': 'Fits in pocket'
}

# Deployment results (based on field studies)
field_results = {
 'sensitivity': 0.92,
 'specificity': 0.94,
 'agreement_with_expert': 0.93, # Cohen's kappa
 'time_per_test': '3 minutes',
 'expert_time': '15-30 minutes',
 'countries': ['Cambodia', 'Myanmar', 'Thailand', 'Bangladesh'],
 'village_health_workers_trained': 450,
 'tests_performed': 75000,
 'cost_per_test': '$0.10', # No consumables needed
 'rdt_cost': '$1-2' # Rapid diagnostic test
}

print("Smartphone microscopy impact:")
print(f"- Accuracy: {field_results['sensitivity']:.0%} sensitivity, {field_results['specificity']:.0%} specificity")
print(f"- Speed: {field_results['time_per_test']} vs {field_results['expert_time']} for expert")
print(f"- Cost: ${field_results['cost_per_test']} vs ${field_results['rdt_cost']} for RDT")
print(f"- Deployments: {field_results['village_health_workers_trained']} village health workers trained")
print(f"- Tests performed: {field_results['tests_performed']:,}")

Outcomes: - 92% sensitivity - Nearly as accurate as expert microscopy - 10-20x faster - 3 minutes vs 15-30 minutes - 10-20x cheaper - $0.10 per test vs $1-2 for RDT - Ultra-portable - Fits in pocket, reaches remote villages - Task-shifting - Village health workers can perform, not just lab technicians

Key innovation: Quality control - AI checks image quality before analysis - Provides real-time feedback to improve image capture - Reduces false results from poor-quality images


Case Study 4: SMS-Based Disease Surveillance (Uganda mTRAC)

Context: Uganda faced challenges with disease surveillance, paper-based reporting was slow (weeks to reach national level), incomplete (40-60% reporting rates), and delayed outbreak response.

Solution: mTRAC (Mobile Tracking of Health Services) - SMS-based reporting system with automated anomaly detection (Cummins and Huddleston, 2013, IDS Bulletin; UNICEF Uganda).

How it Works:

  1. Weekly SMS Reports: Health workers send standardized SMS with disease counts
  • Example: DIAR 15 MAL 23 PNE 3 (Diarrhea 15 cases, Malaria 23, Pneumonia 3)
  • Works on basic feature phones (not smartphones)
  • No internet required (SMS via 2G network)
  1. Automated Data Processing:
  • Natural language processing extracts case counts
  • Validates data (flags impossible values, missing reports)
  • Aggregates to district/national levels in real-time
  1. Automated Outbreak Detection:
  • Compares current cases to historical baselines
  • Flags anomalies (statistical outliers)
  • Prioritizes alerts by severity and confidence
  • Sends alerts to district health teams within hours
  1. Feedback Loop:
  • Health workers receive confirmation SMS
  • District teams get weekly summary reports
  • System prompts non-reporters automatically

Deployment Scale: - 4,500+ health facilities (80% of Uganda’s facilities) - 15,000+ health workers trained - 95% weekly reporting rate (vs 40-60% previously) - Hours to national level (vs weeks with paper)

Impact Documented:

# Uganda mTRAC Impact (2016-2021 data)
impact_metrics = {
 'reporting_rate': {
  'before': 0.45, # 45% of facilities reporting
  'after': 0.95, # 95% of facilities reporting
  'improvement': '+111%'
 },
 'reporting_timeliness': {
  'before': '14-21 days', # Paper reports
  'after': '<24 hours', # SMS submission to national database
  'improvement': '95% faster'
 },
 'outbreak_detection_time': {
  'before': '3-4 weeks', # Time to detect outbreak
  'after': '3-7 days',
  'improvement': '75-85% faster'
 },
 'data_quality': {
  'completeness': '+89%', # More complete data fields
  'accuracy': '+67%',  # Fewer errors vs paper transcription
 },
 'health_worker_time': {
  'reporting_time': '5 minutes/week', # vs 30 minutes for paper
  'training_time': '2 hours',   # Simple SMS format
 },
 'cost_per_facility': {
  'setup': '$50',   # Initial training + SIM card
  'monthly': '$2',   # SMS costs
  'paper_system': '$15/month', # Paper, printing, courier
 },
 'outbreak_responses': {
  'cholera_2018': 'Detected in 3 days, contained to 2 districts',
  'measles_2019': 'Detected week 1, vaccination campaign week 2',
  'covid19_2020': 'Adapted for COVID reporting in 2 weeks'
 }
}

print("\\nmTRAC Impact Summary:")
print(f"Coverage: {impact_metrics['reporting_rate']['after']:.0%} of facilities reporting weekly")
print(f"Timeliness: {impact_metrics['reporting_timeliness']['after']} to national level")
print(f"Outbreak Detection: {impact_metrics['outbreak_detection_time']['after']} (vs {impact_metrics['outbreak_detection_time']['before']})")
print(f"Cost: ${impact_metrics['cost_per_facility']['monthly']}/facility/month")

Why This Succeeded:

  1. Context-Appropriate Technology:
  • SMS works on basic phones (no smartphone needed)
  • Functions with 2G networks (reliable even in rural areas)
  • Minimal training required (standardized format)
  • Offline-capable (SMS queues when no signal)
  1. Simple, Sustainable:
  • $2/month per facility (vs $15 for paper system)
  • No dependency on external servers (Uganda hosts data)
  • Local capacity built (Ugandan IT team maintains system)
  • Integrated with existing workflows (weekly reporting)
  1. Government Ownership:
  • Uganda Ministry of Health owns system
  • Hosted on government servers
  • Ugandan team provides support
  • Sustainable beyond donor funding
  1. Evidence of Impact:
  • Multiple peer-reviewed studies documenting effectiveness
  • WHO recommended as model for other countries
  • Adapted by Kenya, Tanzania, Zambia
  • Expanded to COVID-19, maternal health, supply chain monitoring

Lessons for Other LMICs:

  • Start simple: SMS before apps, basic phones before smartphones
  • Build on existing: Weekly reporting already routine, just digitized process
  • Government ownership: Sustainability requires local control and capacity
  • Demonstrate value: Early wins (outbreak detection) secured long-term support
  • Plan for scale: Designed for national deployment from start, not pilot projects

Expansion Beyond Disease Surveillance: - Stock-out reporting (medicines, vaccines) - Birth and death registration - Maternal health monitoring - Community health worker supervision - Supply chain logistics

Key Innovation: The AI component (anomaly detection) is intentionally simple, statistical outlier detection, not complex machine learning. This ensures: - Transparent (health teams understand how alerts generated) - Maintainable (local IT teams can update thresholds) - Reliable (doesn’t fail due to model drift or data shifts) - Trustworthy (health workers trust what they understand)

Recognition: - 2019: USAID Development Innovation Ventures Award - 2020: WHO Best Practice for Digital Health - 2021: Expanded to 13 African countries

Why SMS-Based Surveillance Works

Advantages Over Smartphone Apps: - 100x wider reach - Basic phones far more common than smartphones in rural areas - 10x lower cost - No smartphone purchase required ($20 feature phone vs $200+ smartphone) - Reliable - 2G SMS works where 3G/4G internet unreliable - Familiar - Health workers already use SMS, minimal learning curve - Battery efficient - Feature phones last days/weeks vs hours for smartphone apps - Maintainable - Simpler technology, local teams can support

When to Use SMS vs Apps: - SMS - Structured reporting, high coverage priority, infrastructure limited - Apps - Complex data, multimedia needed, smartphone penetration high

The best technology is the one that actually works in your context, not the most sophisticated.

Case Study 5: Open-Source NLP for Clinical Note Surveillance (Brazil)

Context: Brazil’s Unified Health System (SUS) generates millions of unstructured free-text clinical notes annually. Critical public health signals, including underreported conditions such as gender-based violence, remain buried in narrative text that traditional surveillance systems cannot process.

Solution: Vital Strategies’ Brazil team deployed open-source NLP to convert unstructured clinical notes into structured surveillance data within SUS (Vital Strategies, February 2026; WHO & IndiaAI, AI Health Casebook, 2026).

How It Works:

  1. NLP extraction: Open-source language models parse free-text clinical notes, identifying diagnoses, risk factors, and social determinants not captured in structured fields
  2. Structured output: Extracted data is mapped to standardized public health categories, enabling integration with existing surveillance pipelines
  3. Surveillance enrichment: Conditions typically underreported in structured data (notably gender-based violence) surface through narrative text analysis

Scale:

  • 39 million clinical notes processed in the pilot phase
  • Deployed within Brazil’s existing public health infrastructure (SUS)
  • Uses open-source models, reducing licensing costs and enabling local adaptation

Why This Matters for LMICs:

  • Resource-efficient: Open-source tools avoid vendor lock-in and recurring license fees
  • Builds on existing data: Does not require new data collection; it unlocks value already in clinical records
  • Addresses underreporting: Surfaces conditions that patients disclose in clinical encounters but that never reach surveillance systems through structured reporting
  • Reproducible: The open-source approach allows adaptation to other health systems with similar free-text documentation

This case study was featured in the WHO-supported Casebook on Real-World Impact of AI in Health, launched at the India AI Impact Summit in February 2026. The same event saw the release of Version 2.0 of Vital Strategies’ Foundations & Futures report, which assessed AI readiness across 63 countries and introduced an AI Use-Case Prerequisites Matrix distinguishing minimum conditions for safe initiation from the foundations required for sustained, population-level integration.

For a related discussion of NLP applied to surveillance data streams, see the Syndromic Surveillance section in the Surveillance chapter.


Practical Action Framework for Implementing AI in Resource-Limited Settings

Concrete, actionable steps for public health practitioners considering AI implementation in low-resource contexts:

Phase 1: Assessment and Planning (1-3 months)

For a validated multi-country readiness framework, see Vital Strategies’ Foundations & Futures (Version 2.0, 2026), which evaluated AI readiness across 63 countries along five dimensions: governance, data systems, connectivity, human capacity, and sustainable financing (Vital Strategies, February 2026).

Step-by-Step Assessment Checklist

Infrastructure Assessment:

Electricity reliability - % of target facilities with reliable power? _______ - Alternative power available? (solar, batteries, generators) - If <80% reliable: Plan for battery-powered or low-power solutions

Internet connectivity - Network type available? (2G / 3G / 4G / fiber / satellite) - Reliability? (always / intermittent / rare) - Cost per MB? _______ (high costs → offline-first design) - If intermittent: Plan for offline-capable systems + sync when connected

Existing technology - % health workers with smartphones? _______ - % with basic phones? _______ - Existing digital systems? (EMR, reporting systems) - If <50% smartphones: Consider SMS/basic phone solutions

Capacity Assessment:

Technical skills - IT staff available? Yes / No | Number: _______ - Skills present: ☐ Programming ☐ Database ☐ System admin ☐ Data analysis - Training capacity: High / Medium / Low - Gap: What skills missing? _______________________

Data quality - Current data completeness: _______% - Current data timeliness: _______ (days from collection to use) - Data validation processes: Yes / No - If <80% complete/accurate: Address data quality BEFORE AI implementation

Workflow integration - Current reporting burden: _______ minutes/day per health worker - Existing workflows documented? Yes / No - Stakeholder buy-in? (Health workers / Managers / IT / Leadership): _______ - Red flag: If AI adds >10 minutes/day, expect resistance

Financial Assessment:

Budget planning - One-time costs: Hardware $_______ | Software $_______ | Training $_______ - Recurring costs: Maintenance $_______ /year | Internet $_______ /month - Funding sources: ☐ Government ☐ Donors ☐ Partnership ☐ Other: _______ - Sustainability: Funded beyond pilot period? Yes / No / Uncertain - Red flag: If sustainability uncertain, consider simpler sustainable alternative

Governance Assessment:

Ownership and control - Who owns the data? (Government / External partner / Unclear) - Data hosted where? (In-country / Cloud / External) - Who maintains system? (Local team / Vendor / External partner) - Exit strategy: What happens if funding ends? _______________________ - Red flag: If answers are “External” or “Unclear,” address governance first

Phase 2: Technology Selection (1-2 months)

Decision Framework: Choosing Appropriate AI Solutions

Use this decision tree:

START: What problem are you solving?

├─ STRUCTURED REPORTING (counts, yes/no, select options)
│ ├─ Smartphone penetration >80%?
│ │ └─ YES → Mobile app (ODK, CommCare, DHIS2)
│ │ └─ NO → SMS-based system (RapidPro, FrontlineSMS, mTRAC-style)
│
├─ IMAGE-BASED DIAGNOSIS (X-rays, microscopy, dermatology)
│ ├─ Reliable internet?
│ │ └─ YES → Cloud AI (Azure, AWS, Google)
│ │ └─ NO → On-device AI (TensorFlow Lite, Edge deployment)
│ ├─ Existing imaging equipment quality?
│ │ └─ High → Standard models may work
│ │ └─ Low → Retrain on local equipment + augment for image quality
│
├─ OUTBREAK DETECTION / SURVEILLANCE
│ ├─ Real-time reporting exists?
│ │ └─ YES → Add anomaly detection layer
│ │ └─ NO → First digitize reporting (SMS/app), then add AI
│ ├─ Data quality sufficient?
│ │ └─ YES (>80% complete, timely) → AI feasible
│ │ └─ NO (<80%) → Fix data collection first, AI later
│
├─ RISK PREDICTION / STRATIFICATION
│ ├─ Electronic health records exist?
│ │ └─ YES → Train on local data (performance, fairness crucial)
│ │ └─ NO → Paper-based → Digitize first, AI later
│ ├─ External model available?
│ │ └─ MUST validate on local population before deployment
│ │ └─ Expect 20-40% performance drop, retrain if needed
│
└─ LANGUAGE/TEXT TASKS (translation, information extraction)
 ├─ Language supported by major LLMs?
 │ └─ YES (English, Spanish, French, etc.) → LLMs viable
 │ └─ NO (low-resource language) → Likely requires custom solution
 ├─ PHI involved?
  └─ YES → Local models only (Llama 2, Mistral, on-premise)
  └─ NO → Enterprise LLMs with BAAs acceptable

Key Selection Principles:

  1. Offline-first when internet unreliable
  • TensorFlow Lite, ONNX Runtime, Edge deployment
  • Data sync when connectivity available
  • Avoid: Cloud-only solutions
  1. Low-power when electricity limited
  • Efficient models (MobileNet, SqueezeNet, quantized models)
  • Battery-powered devices
  • Avoid: High-compute models (GPT-4, large vision models)
  1. Simple when local capacity limited
  • Rule-based systems, statistical methods
  • Transparent, interpretable models
  • Open-source with active communities
  • Avoid: Proprietary black boxes
  • Avoid: Complex deep learning if can’t maintain
  1. Government-owned when sustainability matters
  • In-country data hosting
  • Open-source, customizable
  • Local team trained to maintain
  • Avoid: Vendor lock-in
  • Avoid: Dependency on external servers

Phase 3: Implementation (3-6 months)

Pilot-First Approach:

Month 1-2: Small Pilot (5-10 sites) - Select diverse sites (urban/rural, high/low-performing) - Intensive support (weekly check-ins) - Rapid iteration based on feedback - Measure: Usability, data quality, acceptability, early impact

Month 3-4: Expanded Pilot (20-50 sites) - Scale to more sites with less intensive support - Train local supervisors to provide support - Refine training materials based on pilot 1 - Measure: Same metrics + sustainability indicators

Month 5-6: Regional Scale (100+ sites) - Deploy to entire district/region - Minimal external support (local team leads) - Integrate into routine supervision - Measure: All above + cost-effectiveness

Success Criteria for Each Phase:

Metric Pilot 1 Target Pilot 2 Target Scale Target
Adoption rate >80% >85% >90%
Data completeness >75% >85% >90%
Data timeliness <7 days <3 days <24 hours
User satisfaction >70% satisfied >80% satisfied >85% satisfied
System uptime >90% >95% >99%
Cost per site Higher (learning) Decreasing Sustainable

Go/No-Go Decision Points:

After each pilot phase, assess: - ☐ Metrics meeting targets? - ☐ Users finding it valuable? - ☐ Technical issues manageable? - ☐ Cost sustainable? - ☐ Government committed to scale?

If NO to ≥2 questions: PAUSE, troubleshoot, revise before scaling

Phase 4: Monitoring and Adaptation (Ongoing)

Continuous Improvement Cycle:

Monthly: - Usage statistics (adoption, data quality, errors) - User feedback (health workers, supervisors, analysts) - Technical performance (uptime, response time, accuracy)

Quarterly: - Impact assessment (health outcomes, efficiency, cost) - Fairness audit (performance across subgroups, facilities) - Capacity assessment (local team skills, independence) - Financial sustainability check

Annually: - Thorough evaluation (peer-reviewed study if possible) - Cost-effectiveness analysis - Scale-up planning (new regions, new use cases) - Technology refresh (update models, infrastructure)

Common Pitfalls to Avoid

1. Technology-First Thinking - Avoid: “We have this great AI model, let’s find a problem” - Better: “We have this urgent problem, what’s the simplest effective solution?”

2. Pilot Syndrome - Avoid: Successful 6-month pilot → funding ends → system abandoned - Better: Plan for sustainability from day 1, government ownership essential

3. Ignoring Context - Avoid: Importing solutions from high-income settings without adaptation - Better: Design for local constraints (internet, power, skills, workflows)

4. Over-Engineering - Avoid: Complex deep learning when simple statistics would work - Better: Start simple, add complexity only if clearly beneficial

5. Poor Data Quality - Avoid: Building AI on incomplete, inaccurate, delayed data - Better: Fix data collection process first, then add AI

6. Capacity Neglect - Avoid: External experts build system, locals can’t maintain after departure - Better: Build local capacity from start, plan for handover

7. No Feedback Loop - Avoid: Deploy and forget - Better: Continuous monitoring, user feedback, iterative improvement

8. Fairness Blindness - Avoid: Assuming AI works equally well for all populations - Better: Test performance across subgroups, address disparities


DHIS2: The Global Standard for Health Information

DHIS2 (District Health Information Software 2) is the world’s most widely used health information management system, deployed in over 80 countries and covering 3.2 billion people. Understanding DHIS2 is essential for anyone working on AI in LMIC contexts.

Why DHIS2 Matters for AI

Scale and adoption: - Used by 80+ countries for national health information systems - Covers 3.2 billion people (40% of world population) - Free, open-source, actively maintained by University of Oslo

AI integration opportunities: - Standardized data structure enables cross-country learning - API access for automated data extraction and analysis - Built-in analytics that AI can augment - Community health worker apps (DHIS2 Capture) provide mobile data collection

Common use cases: - Disease surveillance and outbreak detection - Immunization tracking and coverage analysis - Supply chain management and stock prediction - Health facility performance monitoring

DHIS2 + AI Integration Patterns

# Example: Extract DHIS2 data for anomaly detection
import requests

def get_dhis2_disease_data(base_url, username, password, dataset_id, period):
    """
    Extract disease surveillance data from DHIS2 for AI analysis
    """
    # DHIS2 API endpoint for analytics
    endpoint = f"{base_url}/api/analytics.json"

    params = {
        'dimension': f'dx:{dataset_id}',
        'dimension': f'pe:{period}',
        'dimension': 'ou:LEVEL-3',  # District level
        'skipMeta': 'true'
    }

    response = requests.get(
        endpoint,
        params=params,
        auth=(username, password)
    )

    return response.json()

# Feed into anomaly detection pipeline
# disease_data = get_dhis2_disease_data(...)
# anomalies = detect_outbreaks(disease_data)

Resources: - DHIS2 Developer Portal - DHIS2 Academy - Free training courses - DHIS2 Community - Implementation support

Implementation Evidence from Lao PDR

Lao PDR piloted a DHIS2 Tracker-based electronic immunisation registry in one district hospital in November 2022, expanded it to two provinces in 2023, and completed nationwide rollout in 2024. A mixed-methods evaluation in the two earliest implementation regions combined surveys of 26 healthcare workers, 18 stakeholder interviews, workflow observation, and a data-quality assessment of 849,055 unique vaccination events (Patel et al., 2026).

The evaluation found high user acceptance alongside material data and implementation limits. Vaccine type was missing for 15.66% of events, vaccination date was missing for 14.91%, and only 15.26% of vaccinations were recorded within three days. Workforce capacity, electricity, connectivity, governance, and sustainable financing therefore remain prerequisites for using registry data in forecasting or coverage analysis (Patel et al., 2026).


Simplified AI Vendor Evaluation for Resource-Limited Settings

Health departments with limited technical capacity need a streamlined evaluation process. Use this one-page checklist before adopting any AI tool.

Quick Vendor Evaluation Checklist (1-Page Version)

Before you begin: If you cannot answer “yes” to the first three questions, do not proceed.

Must-Have Requirements (All must be YES)

# Question YES/NO
1 Can the system work offline or with intermittent connectivity?
2 Is the system validated on populations similar to yours?
3 Can your staff operate it with less than 1 week of training?
4 Does the vendor provide local language support?
5 Is pricing transparent and sustainable for your budget?

Red Flags (Any YES = Reconsider)

# Question YES/NO
1 Does the vendor require your data to leave the country?
2 Is the system “black box” with no explainability?
3 Does the contract lock you in for >2 years?
4 Has the vendor never deployed in a similar setting?
5 Does the vendor dismiss questions about bias/fairness?

Key Questions to Ask Vendors

  1. “Where has this been deployed in similar settings?”
    • Get specific country/facility references
    • Contact those sites directly
  2. “What happens when internet is unavailable?”
    • Acceptable: “Works offline, syncs when connected”
    • Unacceptable: “Requires constant connectivity”
  3. “How was the model validated on our population?”
    • Acceptable: “Validated on [similar LMIC population]”
    • Unacceptable: “Validated in US/Europe, should generalize”
  4. “What is the total cost of ownership for 5 years?”
    • Include: licensing, training, maintenance, infrastructure
    • Watch for hidden costs (API calls, storage, support)
  5. “What happens when the contract ends?”
    • Data portability
    • Transition support
    • Local capacity built

Decision Matrix

Score Recommendation
5/5 Must-Have + 0/5 Red Flags Proceed with pilot
4/5 Must-Have + 0-1 Red Flags Request modifications, re-evaluate
<4 Must-Have OR >1 Red Flag Do not proceed