chapkit 0.11.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chapkit-0.11.2/PKG-INFO +241 -0
- chapkit-0.11.2/README.md +203 -0
- chapkit-0.11.2/pyproject.toml +174 -0
- chapkit-0.11.2/src/chapkit/__init__.py +128 -0
- chapkit-0.11.2/src/chapkit/alembic/__init__.py +1 -0
- chapkit-0.11.2/src/chapkit/alembic/env.py +76 -0
- chapkit-0.11.2/src/chapkit/alembic/script.py.mako +26 -0
- chapkit-0.11.2/src/chapkit/alembic/versions/20251010_0927_4d869b5fb06e_initial_schema.py +34 -0
- chapkit-0.11.2/src/chapkit/alembic/versions/__init__.py +1 -0
- chapkit-0.11.2/src/chapkit/alembic_helpers.py +138 -0
- chapkit-0.11.2/src/chapkit/api/__init__.py +64 -0
- chapkit-0.11.2/src/chapkit/api/dependencies.py +32 -0
- chapkit-0.11.2/src/chapkit/api/service_builder.py +370 -0
- chapkit-0.11.2/src/chapkit/artifact/__init__.py +39 -0
- chapkit-0.11.2/src/chapkit/artifact/manager.py +132 -0
- chapkit-0.11.2/src/chapkit/artifact/models.py +36 -0
- chapkit-0.11.2/src/chapkit/artifact/repository.py +48 -0
- chapkit-0.11.2/src/chapkit/artifact/router.py +235 -0
- chapkit-0.11.2/src/chapkit/artifact/schemas.py +154 -0
- chapkit-0.11.2/src/chapkit/cli/__init__.py +5 -0
- chapkit-0.11.2/src/chapkit/cli/__main__.py +6 -0
- chapkit-0.11.2/src/chapkit/cli/cli.py +47 -0
- chapkit-0.11.2/src/chapkit/cli/init.py +211 -0
- chapkit-0.11.2/src/chapkit/cli/templates/.gitignore +152 -0
- chapkit-0.11.2/src/chapkit/cli/templates/Dockerfile.jinja2 +86 -0
- chapkit-0.11.2/src/chapkit/cli/templates/README.md.jinja2 +176 -0
- chapkit-0.11.2/src/chapkit/cli/templates/compose.monitoring.yml.jinja2 +91 -0
- chapkit-0.11.2/src/chapkit/cli/templates/compose.yml.jinja2 +35 -0
- chapkit-0.11.2/src/chapkit/cli/templates/main.py.jinja2 +146 -0
- chapkit-0.11.2/src/chapkit/cli/templates/main_shell.py.jinja2 +99 -0
- chapkit-0.11.2/src/chapkit/cli/templates/main_task.py.jinja2 +126 -0
- chapkit-0.11.2/src/chapkit/cli/templates/monitoring/grafana/dashboards/chapkit-service-metrics.json +1232 -0
- chapkit-0.11.2/src/chapkit/cli/templates/monitoring/grafana/provisioning/dashboards/dashboard.yml +13 -0
- chapkit-0.11.2/src/chapkit/cli/templates/monitoring/grafana/provisioning/datasources/prometheus.yml +25 -0
- chapkit-0.11.2/src/chapkit/cli/templates/monitoring/prometheus/prometheus.yml.jinja2 +13 -0
- chapkit-0.11.2/src/chapkit/cli/templates/postman_collection_ml.json.jinja2 +391 -0
- chapkit-0.11.2/src/chapkit/cli/templates/postman_collection_ml_shell.json.jinja2 +414 -0
- chapkit-0.11.2/src/chapkit/cli/templates/postman_collection_task.json.jinja2 +607 -0
- chapkit-0.11.2/src/chapkit/cli/templates/pyproject.toml.jinja2 +15 -0
- chapkit-0.11.2/src/chapkit/cli/templates/scripts/predict_model.py.jinja2 +72 -0
- chapkit-0.11.2/src/chapkit/cli/templates/scripts/train_model.py.jinja2 +64 -0
- chapkit-0.11.2/src/chapkit/config/__init__.py +20 -0
- chapkit-0.11.2/src/chapkit/config/manager.py +63 -0
- chapkit-0.11.2/src/chapkit/config/models.py +60 -0
- chapkit-0.11.2/src/chapkit/config/repository.py +76 -0
- chapkit-0.11.2/src/chapkit/config/router.py +137 -0
- chapkit-0.11.2/src/chapkit/config/schemas.py +63 -0
- chapkit-0.11.2/src/chapkit/data/__init__.py +22 -0
- chapkit-0.11.2/src/chapkit/data/dataframe.py +1189 -0
- chapkit-0.11.2/src/chapkit/ml/__init__.py +29 -0
- chapkit-0.11.2/src/chapkit/ml/manager.py +335 -0
- chapkit-0.11.2/src/chapkit/ml/router.py +114 -0
- chapkit-0.11.2/src/chapkit/ml/runner.py +652 -0
- chapkit-0.11.2/src/chapkit/ml/schemas.py +123 -0
- chapkit-0.11.2/src/chapkit/py.typed +0 -0
- chapkit-0.11.2/src/chapkit/scheduler.py +169 -0
- chapkit-0.11.2/src/chapkit/task/__init__.py +16 -0
- chapkit-0.11.2/src/chapkit/task/executor.py +152 -0
- chapkit-0.11.2/src/chapkit/task/registry.py +145 -0
- chapkit-0.11.2/src/chapkit/task/router.py +99 -0
- chapkit-0.11.2/src/chapkit/task/schemas.py +41 -0
- chapkit-0.11.2/src/chapkit/utils.py +64 -0
chapkit-0.11.2/PKG-INFO
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: chapkit
|
|
3
|
+
Version: 0.11.2
|
|
4
|
+
Summary: ML and data service modules built on servicekit - config, artifacts, tasks, and ML workflows
|
|
5
|
+
Keywords: ml,machine-learning,data-science,artifacts,tasks,config,servicekit
|
|
6
|
+
Author: Morten Hansen
|
|
7
|
+
Author-email: Morten Hansen <morten@dhis2.org>
|
|
8
|
+
License: AGPL-3.0-or-later
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Framework :: FastAPI
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Requires-Dist: geojson-pydantic>=2.1.0
|
|
18
|
+
Requires-Dist: typer>=0.21.0
|
|
19
|
+
Requires-Dist: jinja2>=3.1.6
|
|
20
|
+
Requires-Dist: servicekit>=0.5.3
|
|
21
|
+
Requires-Dist: pandas>=2.3.3 ; extra == 'dataframe'
|
|
22
|
+
Requires-Dist: polars>=1.34.0 ; extra == 'dataframe'
|
|
23
|
+
Requires-Dist: xarray>=2025.10.1 ; extra == 'dataframe'
|
|
24
|
+
Requires-Dist: pandas>=2.3.3 ; extra == 'pandas'
|
|
25
|
+
Requires-Dist: polars>=1.34.0 ; extra == 'polars'
|
|
26
|
+
Requires-Dist: xarray>=2025.10.1 ; extra == 'xarray'
|
|
27
|
+
Requires-Dist: pandas>=2.3.3 ; extra == 'xarray'
|
|
28
|
+
Requires-Python: >=3.13
|
|
29
|
+
Project-URL: Documentation, https://dhis2-chap.github.io/chapkit
|
|
30
|
+
Project-URL: Homepage, https://github.com/dhis2-chap/chapkit
|
|
31
|
+
Project-URL: Issues, https://github.com/dhis2-chap/chapkit/issues
|
|
32
|
+
Project-URL: Repository, https://github.com/dhis2-chap/chapkit
|
|
33
|
+
Provides-Extra: dataframe
|
|
34
|
+
Provides-Extra: pandas
|
|
35
|
+
Provides-Extra: polars
|
|
36
|
+
Provides-Extra: xarray
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# Chapkit
|
|
40
|
+
|
|
41
|
+
[](https://github.com/dhis2-chap/chapkit/actions/workflows/ci.yml)
|
|
42
|
+
[](https://pypi.org/project/chapkit/)
|
|
43
|
+
[](https://codecov.io/gh/dhis2-chap/chapkit)
|
|
44
|
+
[](https://www.python.org/downloads/)
|
|
45
|
+
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
46
|
+
[](https://dhis2-chap.github.io/chapkit/)
|
|
47
|
+
|
|
48
|
+
> ML service modules built on servicekit - config, artifact, task, and ML workflows
|
|
49
|
+
|
|
50
|
+
Chapkit provides domain-specific modules for building machine learning services on top of servicekit's core framework. Includes artifact storage, task execution, configuration management, and ML train/predict workflows.
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- **Artifact Module**: Hierarchical storage for models, data, and experiment tracking with parent-child relationships
|
|
55
|
+
- **Task Module**: Reusable command templates for shell and Python task execution with parameter injection
|
|
56
|
+
- **Config Module**: Key-value configuration with JSON data and Pydantic validation
|
|
57
|
+
- **ML Module**: Train/predict workflows with artifact-based model storage and timing metadata
|
|
58
|
+
- **Config-Artifact Linking**: Connect configurations to artifact hierarchies for experiment tracking
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
Using uv (recommended):
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
uv add chapkit
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or using pip:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install chapkit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Chapkit automatically installs servicekit as a dependency.
|
|
75
|
+
|
|
76
|
+
## CLI Usage
|
|
77
|
+
|
|
78
|
+
Quickly scaffold a new ML service project using `uvx`:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
uvx chapkit init <project-name>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
```bash
|
|
86
|
+
uvx chapkit init my-ml-service
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Options:
|
|
90
|
+
- `--path <directory>` - Target directory (default: current directory)
|
|
91
|
+
- `--with-monitoring` - Include Prometheus and Grafana monitoring stack
|
|
92
|
+
- `--template <type>` - Template type: `ml` (default), `ml-shell`, or `task`
|
|
93
|
+
|
|
94
|
+
This creates a ready-to-run service with configuration, artifacts, and API endpoints pre-configured.
|
|
95
|
+
|
|
96
|
+
**Template Types:**
|
|
97
|
+
- **ml**: Define training/prediction as Python functions in `main.py` (simpler, best for Python-only ML workflows)
|
|
98
|
+
- **ml-shell**: Use external scripts for training/prediction (language-agnostic, supports Python/R/Julia/etc.)
|
|
99
|
+
- **task**: General-purpose task execution with Python functions and shell commands (not ML-specific)
|
|
100
|
+
|
|
101
|
+
## Quick Start
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from chapkit import ArtifactHierarchy, BaseConfig
|
|
105
|
+
from chapkit.api import ServiceBuilder, ServiceInfo
|
|
106
|
+
|
|
107
|
+
class MyConfig(BaseConfig):
|
|
108
|
+
model_name: str
|
|
109
|
+
threshold: float
|
|
110
|
+
|
|
111
|
+
app = (
|
|
112
|
+
ServiceBuilder(info=ServiceInfo(display_name="ML Service"))
|
|
113
|
+
.with_health()
|
|
114
|
+
.with_config(MyConfig)
|
|
115
|
+
.with_artifacts(hierarchy=ArtifactHierarchy(name="ml", level_labels={0: "ml_training_workspace", 1: "ml_prediction"}))
|
|
116
|
+
.with_jobs()
|
|
117
|
+
.build()
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Modules
|
|
122
|
+
|
|
123
|
+
### Config
|
|
124
|
+
|
|
125
|
+
Key-value configuration storage with Pydantic schema validation:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from chapkit import BaseConfig, ConfigManager
|
|
129
|
+
|
|
130
|
+
class AppConfig(BaseConfig):
|
|
131
|
+
api_url: str
|
|
132
|
+
timeout: int = 30
|
|
133
|
+
|
|
134
|
+
# Automatic validation and CRUD endpoints
|
|
135
|
+
app.with_config(AppConfig)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Artifacts
|
|
139
|
+
|
|
140
|
+
Hierarchical storage for models, data, and experiment tracking:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from chapkit import ArtifactHierarchy, ArtifactManager, ArtifactIn
|
|
144
|
+
|
|
145
|
+
hierarchy = ArtifactHierarchy(
|
|
146
|
+
name="ml_pipeline",
|
|
147
|
+
level_labels={0: "experiment", 1: "model", 2: "evaluation"}
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# Store pandas DataFrames, models, any Python object
|
|
151
|
+
artifact = await artifact_manager.save(
|
|
152
|
+
ArtifactIn(data=trained_model, parent_id=experiment_id)
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### ML
|
|
157
|
+
|
|
158
|
+
Train and predict workflows with automatic model storage:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from chapkit.data import DataFrame
|
|
162
|
+
from chapkit.ml import FunctionalModelRunner
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
async def train_model(config: MyConfig, data: DataFrame, geo=None) -> dict:
|
|
166
|
+
"""Train your model - returns trained model object."""
|
|
167
|
+
df = data.to_pandas()
|
|
168
|
+
# Your training logic here
|
|
169
|
+
return {"trained": True}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
async def predict(config: MyConfig, model: dict, historic: DataFrame, future: DataFrame, geo=None) -> DataFrame:
|
|
173
|
+
"""Make predictions - returns DataFrame with predictions."""
|
|
174
|
+
future_df = future.to_pandas()
|
|
175
|
+
future_df["sample_0"] = 0.0 # Your predictions here
|
|
176
|
+
return DataFrame.from_pandas(future_df)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# Wrap functions in runner
|
|
180
|
+
runner = FunctionalModelRunner(on_train=train_model, on_predict=predict)
|
|
181
|
+
app.with_ml(runner=runner)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Architecture
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
chapkit/
|
|
188
|
+
├── config/ # Configuration management with Pydantic validation
|
|
189
|
+
├── artifact/ # Hierarchical storage for models and data
|
|
190
|
+
├── task/ # Reusable task templates (Python functions, shell commands)
|
|
191
|
+
├── ml/ # ML train/predict workflows
|
|
192
|
+
├── cli/ # CLI scaffolding tools
|
|
193
|
+
├── scheduler.py # Job scheduling integration
|
|
194
|
+
└── api/ # ServiceBuilder with ML integration
|
|
195
|
+
└── service_builder.py # .with_config(), .with_artifacts(), .with_ml()
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Chapkit extends servicekit's `BaseServiceBuilder` with ML-specific features and domain modules for configuration, artifacts, tasks, and ML workflows.
|
|
199
|
+
|
|
200
|
+
## Examples
|
|
201
|
+
|
|
202
|
+
See the `examples/` directory for complete working examples:
|
|
203
|
+
|
|
204
|
+
- `quickstart/` - Complete ML service with config, artifacts, and ML endpoints
|
|
205
|
+
- `config_artifact/` - Config with artifact linking
|
|
206
|
+
- `ml_functional/`, `ml_class/`, `ml_shell/` - ML workflow patterns (ML template, class-based, ML-shell template)
|
|
207
|
+
- `ml_pipeline/` - Multi-stage ML pipeline with hierarchical artifacts
|
|
208
|
+
- `artifact/` - Read-only artifact API with hierarchical storage
|
|
209
|
+
- `task_execution/` - Task execution with Python functions and shell commands
|
|
210
|
+
- `full_featured/` - Comprehensive example with monitoring, custom routers, and hooks
|
|
211
|
+
- `library_usage/` - Using chapkit as a library with custom models
|
|
212
|
+
- `custom_migrations/` - Database migrations with custom models
|
|
213
|
+
|
|
214
|
+
## Documentation
|
|
215
|
+
|
|
216
|
+
See `docs/guides/` for comprehensive guides:
|
|
217
|
+
|
|
218
|
+
- [ML Workflows](docs/guides/ml-workflows.md) - Train/predict patterns and model runners
|
|
219
|
+
- [Configuration Management](docs/guides/configuration-management.md) - Config schemas and validation
|
|
220
|
+
- [Artifact Storage](docs/guides/artifact-storage.md) - Hierarchical data storage for ML artifacts
|
|
221
|
+
- [Task Execution](docs/guides/task-execution.md) - Python functions and shell command templates
|
|
222
|
+
- [CLI Scaffolding](docs/guides/cli-scaffolding.md) - Project scaffolding with `chapkit init`
|
|
223
|
+
- [Database Migrations](docs/guides/database-migrations.md) - Custom models and Alembic migrations
|
|
224
|
+
|
|
225
|
+
Full documentation: https://dhis2-chap.github.io/chapkit/
|
|
226
|
+
|
|
227
|
+
## Testing
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
make test # Run tests
|
|
231
|
+
make lint # Run linter
|
|
232
|
+
make coverage # Test coverage
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
AGPL-3.0-or-later
|
|
238
|
+
|
|
239
|
+
## Related Projects
|
|
240
|
+
|
|
241
|
+
- **[servicekit](https://github.com/winterop-com/servicekit)** - Core framework foundation (FastAPI, SQLAlchemy, CRUD, auth, etc.) ([docs](https://winterop-com.github.io/servicekit))
|
chapkit-0.11.2/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Chapkit
|
|
2
|
+
|
|
3
|
+
[](https://github.com/dhis2-chap/chapkit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/chapkit/)
|
|
5
|
+
[](https://codecov.io/gh/dhis2-chap/chapkit)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
8
|
+
[](https://dhis2-chap.github.io/chapkit/)
|
|
9
|
+
|
|
10
|
+
> ML service modules built on servicekit - config, artifact, task, and ML workflows
|
|
11
|
+
|
|
12
|
+
Chapkit provides domain-specific modules for building machine learning services on top of servicekit's core framework. Includes artifact storage, task execution, configuration management, and ML train/predict workflows.
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- **Artifact Module**: Hierarchical storage for models, data, and experiment tracking with parent-child relationships
|
|
17
|
+
- **Task Module**: Reusable command templates for shell and Python task execution with parameter injection
|
|
18
|
+
- **Config Module**: Key-value configuration with JSON data and Pydantic validation
|
|
19
|
+
- **ML Module**: Train/predict workflows with artifact-based model storage and timing metadata
|
|
20
|
+
- **Config-Artifact Linking**: Connect configurations to artifact hierarchies for experiment tracking
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
Using uv (recommended):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv add chapkit
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or using pip:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install chapkit
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Chapkit automatically installs servicekit as a dependency.
|
|
37
|
+
|
|
38
|
+
## CLI Usage
|
|
39
|
+
|
|
40
|
+
Quickly scaffold a new ML service project using `uvx`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uvx chapkit init <project-name>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
```bash
|
|
48
|
+
uvx chapkit init my-ml-service
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Options:
|
|
52
|
+
- `--path <directory>` - Target directory (default: current directory)
|
|
53
|
+
- `--with-monitoring` - Include Prometheus and Grafana monitoring stack
|
|
54
|
+
- `--template <type>` - Template type: `ml` (default), `ml-shell`, or `task`
|
|
55
|
+
|
|
56
|
+
This creates a ready-to-run service with configuration, artifacts, and API endpoints pre-configured.
|
|
57
|
+
|
|
58
|
+
**Template Types:**
|
|
59
|
+
- **ml**: Define training/prediction as Python functions in `main.py` (simpler, best for Python-only ML workflows)
|
|
60
|
+
- **ml-shell**: Use external scripts for training/prediction (language-agnostic, supports Python/R/Julia/etc.)
|
|
61
|
+
- **task**: General-purpose task execution with Python functions and shell commands (not ML-specific)
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from chapkit import ArtifactHierarchy, BaseConfig
|
|
67
|
+
from chapkit.api import ServiceBuilder, ServiceInfo
|
|
68
|
+
|
|
69
|
+
class MyConfig(BaseConfig):
|
|
70
|
+
model_name: str
|
|
71
|
+
threshold: float
|
|
72
|
+
|
|
73
|
+
app = (
|
|
74
|
+
ServiceBuilder(info=ServiceInfo(display_name="ML Service"))
|
|
75
|
+
.with_health()
|
|
76
|
+
.with_config(MyConfig)
|
|
77
|
+
.with_artifacts(hierarchy=ArtifactHierarchy(name="ml", level_labels={0: "ml_training_workspace", 1: "ml_prediction"}))
|
|
78
|
+
.with_jobs()
|
|
79
|
+
.build()
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Modules
|
|
84
|
+
|
|
85
|
+
### Config
|
|
86
|
+
|
|
87
|
+
Key-value configuration storage with Pydantic schema validation:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from chapkit import BaseConfig, ConfigManager
|
|
91
|
+
|
|
92
|
+
class AppConfig(BaseConfig):
|
|
93
|
+
api_url: str
|
|
94
|
+
timeout: int = 30
|
|
95
|
+
|
|
96
|
+
# Automatic validation and CRUD endpoints
|
|
97
|
+
app.with_config(AppConfig)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Artifacts
|
|
101
|
+
|
|
102
|
+
Hierarchical storage for models, data, and experiment tracking:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from chapkit import ArtifactHierarchy, ArtifactManager, ArtifactIn
|
|
106
|
+
|
|
107
|
+
hierarchy = ArtifactHierarchy(
|
|
108
|
+
name="ml_pipeline",
|
|
109
|
+
level_labels={0: "experiment", 1: "model", 2: "evaluation"}
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Store pandas DataFrames, models, any Python object
|
|
113
|
+
artifact = await artifact_manager.save(
|
|
114
|
+
ArtifactIn(data=trained_model, parent_id=experiment_id)
|
|
115
|
+
)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### ML
|
|
119
|
+
|
|
120
|
+
Train and predict workflows with automatic model storage:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from chapkit.data import DataFrame
|
|
124
|
+
from chapkit.ml import FunctionalModelRunner
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
async def train_model(config: MyConfig, data: DataFrame, geo=None) -> dict:
|
|
128
|
+
"""Train your model - returns trained model object."""
|
|
129
|
+
df = data.to_pandas()
|
|
130
|
+
# Your training logic here
|
|
131
|
+
return {"trained": True}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
async def predict(config: MyConfig, model: dict, historic: DataFrame, future: DataFrame, geo=None) -> DataFrame:
|
|
135
|
+
"""Make predictions - returns DataFrame with predictions."""
|
|
136
|
+
future_df = future.to_pandas()
|
|
137
|
+
future_df["sample_0"] = 0.0 # Your predictions here
|
|
138
|
+
return DataFrame.from_pandas(future_df)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# Wrap functions in runner
|
|
142
|
+
runner = FunctionalModelRunner(on_train=train_model, on_predict=predict)
|
|
143
|
+
app.with_ml(runner=runner)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Architecture
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
chapkit/
|
|
150
|
+
├── config/ # Configuration management with Pydantic validation
|
|
151
|
+
├── artifact/ # Hierarchical storage for models and data
|
|
152
|
+
├── task/ # Reusable task templates (Python functions, shell commands)
|
|
153
|
+
├── ml/ # ML train/predict workflows
|
|
154
|
+
├── cli/ # CLI scaffolding tools
|
|
155
|
+
├── scheduler.py # Job scheduling integration
|
|
156
|
+
└── api/ # ServiceBuilder with ML integration
|
|
157
|
+
└── service_builder.py # .with_config(), .with_artifacts(), .with_ml()
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Chapkit extends servicekit's `BaseServiceBuilder` with ML-specific features and domain modules for configuration, artifacts, tasks, and ML workflows.
|
|
161
|
+
|
|
162
|
+
## Examples
|
|
163
|
+
|
|
164
|
+
See the `examples/` directory for complete working examples:
|
|
165
|
+
|
|
166
|
+
- `quickstart/` - Complete ML service with config, artifacts, and ML endpoints
|
|
167
|
+
- `config_artifact/` - Config with artifact linking
|
|
168
|
+
- `ml_functional/`, `ml_class/`, `ml_shell/` - ML workflow patterns (ML template, class-based, ML-shell template)
|
|
169
|
+
- `ml_pipeline/` - Multi-stage ML pipeline with hierarchical artifacts
|
|
170
|
+
- `artifact/` - Read-only artifact API with hierarchical storage
|
|
171
|
+
- `task_execution/` - Task execution with Python functions and shell commands
|
|
172
|
+
- `full_featured/` - Comprehensive example with monitoring, custom routers, and hooks
|
|
173
|
+
- `library_usage/` - Using chapkit as a library with custom models
|
|
174
|
+
- `custom_migrations/` - Database migrations with custom models
|
|
175
|
+
|
|
176
|
+
## Documentation
|
|
177
|
+
|
|
178
|
+
See `docs/guides/` for comprehensive guides:
|
|
179
|
+
|
|
180
|
+
- [ML Workflows](docs/guides/ml-workflows.md) - Train/predict patterns and model runners
|
|
181
|
+
- [Configuration Management](docs/guides/configuration-management.md) - Config schemas and validation
|
|
182
|
+
- [Artifact Storage](docs/guides/artifact-storage.md) - Hierarchical data storage for ML artifacts
|
|
183
|
+
- [Task Execution](docs/guides/task-execution.md) - Python functions and shell command templates
|
|
184
|
+
- [CLI Scaffolding](docs/guides/cli-scaffolding.md) - Project scaffolding with `chapkit init`
|
|
185
|
+
- [Database Migrations](docs/guides/database-migrations.md) - Custom models and Alembic migrations
|
|
186
|
+
|
|
187
|
+
Full documentation: https://dhis2-chap.github.io/chapkit/
|
|
188
|
+
|
|
189
|
+
## Testing
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
make test # Run tests
|
|
193
|
+
make lint # Run linter
|
|
194
|
+
make coverage # Test coverage
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
AGPL-3.0-or-later
|
|
200
|
+
|
|
201
|
+
## Related Projects
|
|
202
|
+
|
|
203
|
+
- **[servicekit](https://github.com/winterop-com/servicekit)** - Core framework foundation (FastAPI, SQLAlchemy, CRUD, auth, etc.) ([docs](https://winterop-com.github.io/servicekit))
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "chapkit"
|
|
3
|
+
version = "0.11.2"
|
|
4
|
+
description = "ML and data service modules built on servicekit - config, artifacts, tasks, and ML workflows"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "Morten Hansen", email = "morten@dhis2.org" }]
|
|
7
|
+
license = { text = "AGPL-3.0-or-later" }
|
|
8
|
+
requires-python = ">=3.13"
|
|
9
|
+
keywords = [
|
|
10
|
+
"ml",
|
|
11
|
+
"machine-learning",
|
|
12
|
+
"data-science",
|
|
13
|
+
"artifacts",
|
|
14
|
+
"tasks",
|
|
15
|
+
"config",
|
|
16
|
+
"servicekit",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 3 - Alpha",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Framework :: FastAPI",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"geojson-pydantic>=2.1.0",
|
|
30
|
+
"typer>=0.21.0",
|
|
31
|
+
"jinja2>=3.1.6",
|
|
32
|
+
"servicekit>=0.5.3",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
pandas = ["pandas>=2.3.3"]
|
|
37
|
+
polars = ["polars>=1.34.0"]
|
|
38
|
+
xarray = ["xarray>=2025.10.1", "pandas>=2.3.3"]
|
|
39
|
+
dataframe = ["pandas>=2.3.3", "polars>=1.34.0", "xarray>=2025.10.1"]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Homepage = "https://github.com/dhis2-chap/chapkit"
|
|
43
|
+
Repository = "https://github.com/dhis2-chap/chapkit"
|
|
44
|
+
Issues = "https://github.com/dhis2-chap/chapkit/issues"
|
|
45
|
+
Documentation = "https://dhis2-chap.github.io/chapkit"
|
|
46
|
+
|
|
47
|
+
[project.scripts]
|
|
48
|
+
chapkit = "chapkit.cli.cli:main"
|
|
49
|
+
|
|
50
|
+
[dependency-groups]
|
|
51
|
+
dev = [
|
|
52
|
+
"coverage[toml]>=7.13.1",
|
|
53
|
+
"mypy>=1.18.2",
|
|
54
|
+
"pandas-stubs>=2.3.3.251219",
|
|
55
|
+
"pytest>=8.4.2",
|
|
56
|
+
"pytest-cov>=5.0.0",
|
|
57
|
+
"pytest-asyncio>=1.2.0",
|
|
58
|
+
"ruff>=0.14.10",
|
|
59
|
+
"pyright>=1.1.407",
|
|
60
|
+
"scikit-learn>=1.7.2",
|
|
61
|
+
"mkdocs>=1.6.0",
|
|
62
|
+
"mkdocs-material>=9.7.1",
|
|
63
|
+
"mkdocstrings[python]>=0.26.0",
|
|
64
|
+
"types-pyyaml>=6.0.12.20250915",
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
[build-system]
|
|
68
|
+
requires = ["uv_build>=0.9.0,<0.10.0"]
|
|
69
|
+
build-backend = "uv_build"
|
|
70
|
+
|
|
71
|
+
[tool.ruff]
|
|
72
|
+
target-version = "py313"
|
|
73
|
+
line-length = 120
|
|
74
|
+
|
|
75
|
+
[tool.ruff.lint]
|
|
76
|
+
fixable = ["ALL"]
|
|
77
|
+
select = ["E", "W", "F", "I", "D"]
|
|
78
|
+
ignore = ["D203", "D213"]
|
|
79
|
+
|
|
80
|
+
[tool.ruff.lint.pydocstyle]
|
|
81
|
+
convention = "google"
|
|
82
|
+
|
|
83
|
+
[tool.ruff.lint.per-file-ignores]
|
|
84
|
+
"tests/**/*.py" = ["D"]
|
|
85
|
+
"src/chapkit/alembic/**/*.py" = ["D"]
|
|
86
|
+
"**/__init__.py" = ["D104"]
|
|
87
|
+
"src/**/*.py" = ["D102", "D105", "D107"]
|
|
88
|
+
"examples/**/*.py" = []
|
|
89
|
+
|
|
90
|
+
[tool.ruff.format]
|
|
91
|
+
quote-style = "double"
|
|
92
|
+
indent-style = "space"
|
|
93
|
+
skip-magic-trailing-comma = false
|
|
94
|
+
docstring-code-format = true
|
|
95
|
+
docstring-code-line-length = "dynamic"
|
|
96
|
+
|
|
97
|
+
[tool.pytest.ini_options]
|
|
98
|
+
asyncio_mode = "auto"
|
|
99
|
+
testpaths = ["tests"]
|
|
100
|
+
norecursedirs = ["examples", ".git", ".venv", "__pycache__"]
|
|
101
|
+
filterwarnings = [
|
|
102
|
+
"ignore:Pydantic serializer warnings:UserWarning",
|
|
103
|
+
"ignore:Remove.*format_exc_info.*:UserWarning",
|
|
104
|
+
]
|
|
105
|
+
markers = [
|
|
106
|
+
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
[tool.coverage.run]
|
|
110
|
+
branch = true
|
|
111
|
+
dynamic_context = "test_function"
|
|
112
|
+
relative_files = true
|
|
113
|
+
source = ["chapkit"]
|
|
114
|
+
omit = ["*/alembic/*", "*/cli/*"]
|
|
115
|
+
|
|
116
|
+
[tool.coverage.report]
|
|
117
|
+
exclude_also = ["if TYPE_CHECKING:"]
|
|
118
|
+
precision = 2
|
|
119
|
+
show_missing = true
|
|
120
|
+
skip_covered = true
|
|
121
|
+
|
|
122
|
+
[tool.mypy]
|
|
123
|
+
python_version = "3.13"
|
|
124
|
+
warn_return_any = true
|
|
125
|
+
warn_unused_configs = true
|
|
126
|
+
disallow_untyped_defs = true
|
|
127
|
+
check_untyped_defs = true
|
|
128
|
+
no_implicit_optional = true
|
|
129
|
+
warn_unused_ignores = true
|
|
130
|
+
strict_equality = true
|
|
131
|
+
mypy_path = ["src", "typings"]
|
|
132
|
+
|
|
133
|
+
[[tool.mypy.overrides]]
|
|
134
|
+
module = "tests.*"
|
|
135
|
+
disallow_untyped_defs = false
|
|
136
|
+
|
|
137
|
+
[[tool.mypy.overrides]]
|
|
138
|
+
module = "servicekit.*"
|
|
139
|
+
ignore_missing_imports = true
|
|
140
|
+
disallow_any_unimported = false
|
|
141
|
+
|
|
142
|
+
[[tool.mypy.overrides]]
|
|
143
|
+
module = [
|
|
144
|
+
"chapkit.artifact.*",
|
|
145
|
+
"chapkit.config.*",
|
|
146
|
+
"chapkit.task.*",
|
|
147
|
+
"examples.*",
|
|
148
|
+
]
|
|
149
|
+
warn_return_any = false
|
|
150
|
+
|
|
151
|
+
[[tool.mypy.overrides]]
|
|
152
|
+
module = "examples.custom_migrations.*"
|
|
153
|
+
ignore_missing_imports = true
|
|
154
|
+
ignore_errors = true
|
|
155
|
+
|
|
156
|
+
[[tool.mypy.overrides]]
|
|
157
|
+
module = "examples.artifact_manager.*"
|
|
158
|
+
ignore_errors = true
|
|
159
|
+
|
|
160
|
+
[tool.pyright]
|
|
161
|
+
include = ["src", "tests", "examples"]
|
|
162
|
+
exclude = ["examples/artifact_manager", "**/.venv"]
|
|
163
|
+
pythonVersion = "3.13"
|
|
164
|
+
typeCheckingMode = "strict"
|
|
165
|
+
useLibraryCodeForTypes = true
|
|
166
|
+
reportPrivateUsage = false
|
|
167
|
+
reportUnusedFunction = false
|
|
168
|
+
reportUnknownMemberType = false
|
|
169
|
+
reportUnknownArgumentType = false
|
|
170
|
+
reportUnknownParameterType = false
|
|
171
|
+
reportUnknownVariableType = false
|
|
172
|
+
reportMissingTypeArgument = false
|
|
173
|
+
reportMissingTypeStubs = false
|
|
174
|
+
reportUnknownLambdaType = false
|