Running models with chapkit¶
Chapkit is one of two ways chap runs models. Chap is gradually migrating models to chapkit; both chapkit and the older approach are supported.
In contrast to the older approach, where models are run directly through docker and pyenv wrappers inside chap, chapkit models are separate REST API services that chap interacts with through HTTP requests.
This has several advantages:
- There are no docker-in-docker problems where chap (which is inside docker) has to run docker commands to start model containers.
- We have a strict and clear API for how chap interacts with models, which makes it easier to develop and maintain.
- Models can easily be distributed through docker images or other means, as long as they implement the chapkit API. It is up to the model to define how it is deployed and run, but chapkit makes it easy to spin up a rest api and make a docker image for a model.
This document describes very briefly how to make a model compatible with chapkit, and how to use chapkit models in chap.
How to make a model compatible with chapkit¶
The simplest way is to describe the model in an MLproject file and let chapkit serve it, with no service code. See Bring your existing model to Chap or Build a new model from a template. For writing a chapkit service directly, see the chapkit documentation: https://dhis2-chap.github.io/chapkit/.
Three ways to make a model¶
| MLproject, built-in Chap runner | MLproject served by chapkit (recommended) | chapkit service | |
|---|---|---|---|
| You write | Train and predict scripts, and an MLproject file |
The same files | Train and predict code, a main.py that defines the service, and a Dockerfile |
| How Chap runs it | Chap reads the MLproject and runs the train and predict commands itself |
chapkit reads the MLproject and serves the model as a REST service. Chap sends it data over HTTP |
Your service runs on its own. Chap sends it data over HTTP |
| Evaluate with | chap eval --model-name <directory or GitHub URL> |
chap eval --model-name <directory or GitHub URL> --run-config.as-chapkit |
chap eval --model-name <service URL> --run-config.is-chapkit-model |
| Add to a Chap installation | Chap fetches the model from GitHub, see Getting new models into the modeling app | Run a Docker image built from a chapkit base image. It registers itself with Chap | Run the service's Docker image. It registers itself with Chap |
| Where to start | Connect your model to the Chap standard | Bring your existing model to Chap or Build a new model from a template | The chapkit documentation |
The first two use the same MLproject format, so a model written for one usually runs with the other. The exception is the environment: chapkit sets up uv_env and renv_env, but not docker_env, conda_env or python_env. What differs is who runs the model: Chap itself, or chapkit as a separate service. The second and third run the same way in Chap. The difference is whether chapkit builds the service from your MLproject, or you write the service code. A model can move from the second to the third with chapkit mlproject migrate, see MLproject Migrate in the chapkit docs.
Data format sent to chapkit models¶
Chap sends data to chapkit models via the REST API in a standardized format. The data is sent as JSON with a columns array and a data array (column-oriented format).
Required columns¶
The following columns are always present in the training and prediction data:
| Column | Description |
|---|---|
time_period |
Time period identifier (see format below) |
location |
Location identifier |
disease_cases |
Number of disease cases (training data only) |
rainfall |
Rainfall measurement |
mean_temperature |
Mean temperature |
population |
Population count |
Time period format¶
The time_period column uses ISO-like string formats:
Weekly data:
The format is YYYY-Wnn where:
- YYYY is the ISO week year
- W indicates weekly data
- nn is the zero-padded week number (01-53)
Monthly data:
The format is YYYY-MM where:
- YYYY is the year
- MM is the zero-padded month number (01-12)
Example training data (weekly)¶
{
"columns": ["time_period", "location", "disease_cases", "rainfall", "mean_temperature", "population"],
"data": [
["2020-W01", "district_a", 150, 45.2, 28.5, 50000],
["2020-W02", "district_a", 142, 52.1, 27.8, 50000],
["2020-W01", "district_b", 89, 38.7, 29.1, 35000],
["2020-W02", "district_b", 95, 41.3, 28.9, 35000]
]
}
Example training data (monthly)¶
{
"columns": ["time_period", "location", "disease_cases", "rainfall", "mean_temperature", "population"],
"data": [
["2020-01", "district_a", 580, 180.5, 28.2, 50000],
["2020-02", "district_a", 620, 165.3, 27.9, 50000],
["2020-01", "district_b", 340, 155.8, 29.0, 35000],
["2020-02", "district_b", 365, 148.2, 28.7, 35000]
]
}
Run info¶
Along with the data, Chap sends a run_info object containing runtime parameters:
| Field | Description |
|---|---|
prediction_periods |
Number of future periods to predict |
additional_continuous_covariates |
List of additional covariate columns in the data |
run_info is sent on both $train and $predict. At train time
prediction_periods is the horizon the model is going to be asked for, clamped to the
min_prediction_periods and max_prediction_periods the service declares; at predict
time it is the length of the future frame. Chap leaves the field out when it does not
know the horizon, and the service then falls back to the value in its stored
configuration.
Chapkit resolves the horizon from run_info first, then the future frame, then the
stored configuration, so your model reads it from config.prediction_periods as usual.
This requires chapkit 2.1.0 or newer; older versions ignore run_info at train time.
Chap sent the horizon as prediction_length before chapkit 2.1.0, and chapkit still
accepts that spelling.
How to run a chapkit model from the command line¶
To test that the model works with Chap, use the chap eval command. Give the model's container image with docker:// in front, and Chap starts the image as a container for the duration of the command and removes it afterwards. This needs Docker.
Example:
First save this model configuration to a file called testconfig.yaml:
Then evaluate the chtorch model from its image:
chap eval --model-name docker://ghcr.io/dhis2-chap/chtorch:chapkit2-8f17ee3 --dataset-csv https://raw.githubusercontent.com/dhis2/climate-health-data/refs/heads/main/lao/chap_LAO_admin1_monthly.csv --output-file eval.nc --plot --backtest-params.n-splits 2 --backtest-params.n-periods 3 --model-configuration-yaml testconfig.yaml
If the model is already running as a service, for example one you started yourself with docker run -p 5001:8000 <image>, give its URL instead and add --run-config.is-chapkit-model:
chap eval --model-name http://localhost:5001 --run-config.is-chapkit-model --dataset-csv ./data.csv --output-file eval.nc
A model from Chap Marketplace can also be set up once in a Chap project, which stores its verified image so that chap eval runs without options.
How to use chapkit models in chap with the modeling app¶
Model services from the Chap Marketplace
are installed with chap-admin install-all, which starts the services and
registers their templates and configurations with chap, so they appear in the
modeling app. See
Install the Models
for the commands.
To add a model service that is not in the marketplace, see Running Your Own Model.