From b75a901303037e5e6e70785947a314f4d4136f8c Mon Sep 17 00:00:00 2001 From: Morten Hansen Date: Wed, 17 Jun 2026 13:07:59 +0200 Subject: [PATCH] chore: release 0.29.0 Finalize 0.29.0 (drop .dev0) and fix documentation accuracy bugs. - MLServiceInfo Quick Start snippets now include the required model_metadata and period_type fields. - Correct ML route paths to /api/v1/ml/$train, /$predict, /$validate. - Drop the unsupported max_concurrency arg from MLServiceBuilder examples. - Move config-artifact linking to with_artifacts(enable_config_linking=True). - Correct the artifact tree endpoint to GET /api/v1/artifacts/{id}/$tree. - Fix DataFrame import path, sort(ascending=) usage, and mlproject run port. --- docs/guides/artifact-storage.md | 16 +++------------- docs/guides/configuration-management.md | 8 ++++---- docs/guides/dataframe.md | 2 +- docs/guides/ml-workflows.md | 15 +++++++++------ docs/guides/mlproject-runner.md | 2 +- docs/index.md | 14 ++++++++++---- pyproject.toml | 2 +- uv.lock | 2 +- 8 files changed, 30 insertions(+), 31 deletions(-) diff --git a/docs/guides/artifact-storage.md b/docs/guides/artifact-storage.md index 7d36ede..7383575 100644 --- a/docs/guides/artifact-storage.md +++ b/docs/guides/artifact-storage.md @@ -267,17 +267,9 @@ Update artifact data. Delete artifact (fails if artifact has children). -### POST /api/v1/artifacts/$tree +### GET /api/v1/artifacts/{id}/$tree -Get artifact tree structure. - -**Request:** -```json -{ - "root_id": "01ARTIFACT456...", - "max_depth": 3 -} -``` +Get artifact tree structure rooted at the given artifact (no request body). **Response:** ```json @@ -615,9 +607,7 @@ CHILD_ID=$(curl -s -X POST http://localhost:9090/api/v1/artifacts \ }' | jq -r '.id') # Get tree -curl -X POST http://localhost:9090/api/v1/artifacts/\$tree \ - -H "Content-Type: application/json" \ - -d '{"root_id": "'$ROOT_ID'"}' | jq +curl http://localhost:9090/api/v1/artifacts/$ROOT_ID/\$tree | jq ``` --- diff --git a/docs/guides/configuration-management.md b/docs/guides/configuration-management.md index bf6630a..4ab1d5a 100644 --- a/docs/guides/configuration-management.md +++ b/docs/guides/configuration-management.md @@ -238,8 +238,8 @@ Enable artifact operations when building the service: ```python app = ( ServiceBuilder(info=info) - .with_config(MLConfig, enable_artifact_operations=True) - .with_artifacts(hierarchy=hierarchy) + .with_config(MLConfig) + .with_artifacts(hierarchy=hierarchy, enable_config_linking=True) .build() ) ``` @@ -486,11 +486,11 @@ class WeatherModelConfig(BaseConfig): app = ( ServiceBuilder(info=ServiceInfo(id="weather-model-service", display_name="Weather Model Service")) .with_health() - .with_config(WeatherModelConfig, enable_artifact_operations=True) + .with_config(WeatherModelConfig) .with_artifacts(hierarchy=ArtifactHierarchy( name="weather_models", level_labels={0: "ml_training_workspace", 1: "ml_prediction"} - )) + ), enable_config_linking=True) .build() ) ``` diff --git a/docs/guides/dataframe.md b/docs/guides/dataframe.md index b84659e..41dda09 100644 --- a/docs/guides/dataframe.md +++ b/docs/guides/dataframe.md @@ -1362,7 +1362,7 @@ high_sales = df.filter(lambda r: r['sales'] > 1000) summary = high_sales.groupby('region').count() # Chain with other operations -df.groupby('product').sum('sales').sort('sales_sum', reverse=True).head(5) +df.groupby('product').sum('sales').sort('sales_sum', ascending=False).head(5) ``` **Design notes:** diff --git a/docs/guides/ml-workflows.md b/docs/guides/ml-workflows.md index 61a01dd..fb89912 100644 --- a/docs/guides/ml-workflows.md +++ b/docs/guides/ml-workflows.md @@ -10,7 +10,7 @@ Chapkit provides a complete ML workflow system for training models and making pr from chapkit.artifact import ArtifactHierarchy from chapkit import BaseConfig -from chapkit.api import MLServiceBuilder, MLServiceInfo +from chapkit.api import MLServiceBuilder, MLServiceInfo, AssessedStatus, ModelMetadata, PeriodType from chapkit.ml import FunctionalModelRunner import pandas as pd from sklearn.linear_model import LinearRegression @@ -34,7 +34,12 @@ runner = FunctionalModelRunner(on_train=on_train, on_predict=on_predict) app = ( MLServiceBuilder( - info=MLServiceInfo(id="my-ml-service", display_name="My ML Service"), + info=MLServiceInfo( + id="my-ml-service", + display_name="My ML Service", + model_metadata=ModelMetadata(author="ML Team", author_assessed_status=AssessedStatus.green), + period_type=PeriodType.monthly, + ), config_schema=ModelConfig, hierarchy=ArtifactHierarchy(name="ml", level_labels={0: "ml_training_workspace", 1: "ml_prediction"}), runner=runner, @@ -403,7 +408,6 @@ MLServiceBuilder( config_schema=YourConfig, hierarchy=hierarchy, runner=runner, - max_concurrency=5, # Limit concurrent jobs (default: unlimited) database_url="ml.db", # Persistent storage (default: in-memory) ) ``` @@ -729,7 +733,7 @@ All tabular data uses the `DataFrame` schema: **Python Usage:** ```python -from servicekit.data import DataFrame +from chapkit.data import DataFrame # Create from DataFrame df = pd.DataFrame({"a": [1, 2], "b": [3, 4]}) @@ -1316,7 +1320,6 @@ MLServiceBuilder( config_schema=config_schema, hierarchy=hierarchy, runner=runner, - max_concurrency=3, # Limit concurrent training jobs ) ``` @@ -1708,7 +1711,7 @@ curl http://localhost:9090/api/v1/jobs/$JOB_ID | jq '.error' **Solution:** ```python # Limit concurrent jobs -MLServiceBuilder(..., max_concurrency=2) +MLServiceBuilder(...) # Implement artifact cleanup async def cleanup_old_artifacts(app): diff --git a/docs/guides/mlproject-runner.md b/docs/guides/mlproject-runner.md index c465a59..98acd85 100644 --- a/docs/guides/mlproject-runner.md +++ b/docs/guides/mlproject-runner.md @@ -12,7 +12,7 @@ chapkit mlproject run . # same chapkit mlproject run /path/to/my_mlproject ``` -This parses the `MLproject` file, translates the entry-point commands to chapkit's workspace conventions, builds a FastAPI service with `/api/v1/ml/$train` and `/$predict` endpoints, and serves on `127.0.0.1:8000` by default. Override host/port with `--host` and `--port`. +This parses the `MLproject` file, translates the entry-point commands to chapkit's workspace conventions, builds a FastAPI service with `/api/v1/ml/$train` and `/$predict` endpoints, and serves on `127.0.0.1:9090` by default. Override host/port with `--host` and `--port`. A minimal R MLproject like `dhis2-chap/minimalist_example_r`: diff --git a/docs/index.md b/docs/index.md index d404e2a..24b75ac 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,7 +13,7 @@ Build production-ready ML services with train/predict workflows, artifact storag from geojson_pydantic import FeatureCollection from chapkit import BaseConfig -from chapkit.api import MLServiceBuilder, MLServiceInfo +from chapkit.api import MLServiceBuilder, MLServiceInfo, AssessedStatus, ModelMetadata, PeriodType from chapkit.artifact import ArtifactHierarchy from chapkit.data import DataFrame from chapkit.ml import FunctionalModelRunner @@ -55,7 +55,12 @@ async def predict( app = ( MLServiceBuilder( - info=MLServiceInfo(id="disease-prediction-service", display_name="Disease Prediction Service"), + info=MLServiceInfo( + id="disease-prediction-service", + display_name="Disease Prediction Service", + model_metadata=ModelMetadata(author="ML Team", author_assessed_status=AssessedStatus.green), + period_type=PeriodType.monthly, + ), config_schema=MyMLConfig, hierarchy=ArtifactHierarchy( name="ml", @@ -69,8 +74,9 @@ app = ( ``` **What you get:** -- `POST /api/v1/ml/train` - Train models with versioning -- `POST /api/v1/ml/predict` - Make predictions +- `POST /api/v1/ml/$train` - Train models with versioning +- `POST /api/v1/ml/$predict` - Make predictions +- `POST /api/v1/ml/$validate` - Validate model configurations - `GET /api/v1/configs` - Manage model configurations - `GET /api/v1/artifacts` - Browse trained models and predictions - `GET /api/v1/jobs` - Monitor training/prediction jobs diff --git a/pyproject.toml b/pyproject.toml index 0b3285a..6aa43ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "chapkit" -version = "0.29.0.dev0" +version = "0.29.0" description = "ML and data service modules built on servicekit - config, artifacts, and ML workflows" readme = "README.md" authors = [{ name = "Morten Hansen", email = "morten@dhis2.org" }] diff --git a/uv.lock b/uv.lock index 88abdec..b55c353 100644 --- a/uv.lock +++ b/uv.lock @@ -148,7 +148,7 @@ wheels = [ [[package]] name = "chapkit" -version = "0.29.0.dev0" +version = "0.29.0" source = { editable = "." } dependencies = [ { name = "geojson-pydantic" },