Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework template to better use MCP capabilities #17

Merged
merged 29 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9f63906
hide mlflow complexity and show MCP more
avishniakov Nov 3, 2023
5a0f0b4
hide mlflow complexity and show MCP more
avishniakov Nov 3, 2023
825c48f
brush up
avishniakov Nov 3, 2023
3b1fbea
black
avishniakov Nov 3, 2023
d7a4a42
add comments
avishniakov Nov 3, 2023
727130c
fix renaming issue
avishniakov Nov 3, 2023
d8a24d1
Merge branch 'feature/OSS-2598-simplify-promotion-logic' of https://g…
avishniakov Nov 3, 2023
e17f9a7
more MCP
avishniakov Nov 3, 2023
745859b
update docstring
avishniakov Nov 3, 2023
6f42d4a
update readme
avishniakov Nov 3, 2023
661f60b
get rid of deployer
avishniakov Nov 6, 2023
2202ae3
don't rely on MR versions anymore
avishniakov Nov 6, 2023
146a1bd
rename
avishniakov Nov 6, 2023
1d9ff86
rename
avishniakov Nov 6, 2023
dec25ec
typo
avishniakov Nov 6, 2023
f75972f
use step level configs in yaml
avishniakov Nov 6, 2023
689ca5a
move configs around
avishniakov Nov 6, 2023
67ef035
typo
avishniakov Nov 6, 2023
dcfb09c
add deployment pipeline
avishniakov Nov 6, 2023
04c3701
black a bit
avishniakov Nov 6, 2023
1bf0024
update readme
avishniakov Nov 6, 2023
42a2404
fix naming issue
avishniakov Nov 6, 2023
60a2b11
fix template
avishniakov Nov 6, 2023
44932e5
fix template
avishniakov Nov 6, 2023
bc81c5e
try fix tests for macos
avishniakov Nov 7, 2023
bc5ec6a
try fix tests for macos
avishniakov Nov 7, 2023
7965112
add cool pics
avishniakov Nov 8, 2023
f275b4c
add image optimizer here
avishniakov Nov 8, 2023
c7d318c
Optimised images with calibre/image-actions
github-actions[bot] Nov 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ jobs:
ZENML_DEBUG: true
ZENML_ANALYTICS_OPT_IN: false
ZENML_LOGGING_VERBOSITY: INFO
# fork fix for macos
OBJC_DISABLE_INITIALIZE_FORK_SAFETY: YES
steps:
- name: Check out repository code
uses: actions/checkout@v3
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/image-optimizer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Compress Images
on:
pull_request:
# Run Image Actions when JPG, JPEG, PNG or WebP files are added or changed.
# See https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#onpushpull_requestpaths for reference.
paths:
- '**.jpg'
- '**.jpeg'
- '**.png'
- '**.webp'
jobs:
build:
# Only run on non-draft PRs within the same repository.
if: github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.draft == false
name: calibreapp/image-actions
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3

- name: Compress Images
uses: calibreapp/image-actions@main
with:
# The `GITHUB_TOKEN` is automatically generated by GitHub and scoped only to the repository that is currently running the action. By default, the action can’t update Pull Requests initiated from forked repositories.
# See https://docs.github.com/en/actions/reference/authentication-in-a-workflow and https://help.github.com/en/articles/virtual-environments-for-github-actions#token-permissions
githubToken: ${{ secrets.GITHUB_TOKEN }}
113 changes: 91 additions & 22 deletions README.md

Large diffs are not rendered by default.

Binary file modified assets/01_etl.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/02_hp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/03_train.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/04_promotion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/05_batch_inference.png
Binary file not shown.
Binary file added assets/05_deployment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/06_batch_inference.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified template/.assets/00_pipelines_composition.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 27 additions & 21 deletions template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,21 @@ This template uses
to demonstrate how to perform major critical steps for Continuous Training (CT)
and Continuous Delivery (CD).

It consists of two pipelines with the following high-level setup:
It consists of three pipelines with the following high-level setup:
<p align="center">
<img height=300 src=".assets/00_pipelines_composition.png">
<img height=800 src=".assets/00_pipelines_composition.png">
</p>

Both pipelines are inside a shared Model Control Plane model context - training pipeline creates and promotes new Model Control Plane version and inference pipeline is reading from inference Model Control Plane version. This makes those pipelines closely connected, while ensuring that only quality-assured Model Control Plane versions are used to produce predictions delivered to stakeholders.
All pipelines are leveraging the Model Control Plane to bring all parts together - the training pipeline creates and promotes a new Model Control Plane version with a trained model object in it, deployment pipeline uses the inference Model Control Plane version (the one promoted during training) to create a deployment service and inference pipeline using deployment service from the inference Model Control Plane version and store back new set of predictions as a versioned data artifact for future use. This makes those pipelines closely connected while ensuring that only quality-assured Model Control Plane versions are used to produce predictions delivered to stakeholders.
* [CT] Training
* Load, split, and preprocess the training dataset
* Search for an optimal model object architecture and tune its hyperparameters
* Train the model object and evaluate its performance on the holdout set
* Compare a recently trained model object with one promoted earlier
* If a recently trained model object performs better - stage it as a new inference model object in model registry
* On success of the current model object - stage newly created Model Control Plane version as the one used for inference
* [CD] Deployment
* Deploy a new prediction service based on the model object connected to the inference Model Control Plane version.
* [CD] Batch Inference
* Load the inference dataset and preprocess it reusing object fitted during training
* Perform data drift analysis reusing training dataset of the inference Model Control Plane version as a reference
Expand All @@ -142,23 +144,27 @@ The project loosely follows [the recommended ZenML project structure](https://do

```
.
├── pipelines # `zenml.pipeline` implementations
│ ├── batch_inference.py # [CD] Batch Inference pipeline
│ └── training.py # [CT] Training Pipeline
├── steps # logically grouped `zenml.steps` implementations
│ ├── alerts # alert developer on pipeline status
│ ├── data_quality # quality gates built on top of drift report
│ ├── etl # ETL logic for dataset
│ ├── hp_tuning # tune hyperparameters and model architectures
│ ├── inference # inference on top of the model from the registry
│ ├── promotion # find if a newly trained model will be new inference
│ └── training # train and evaluate model
├── utils # helper functions
├── configs # pipelines configuration files
│ ├── deployer_config.yaml # the configuration of the deployment pipeline
│ ├── inference_config.yaml # the configuration of the batch inference pipeline
│ └── train_config.yaml # the configuration of the training pipeline
├── pipelines # `zenml.pipeline` implementations
│ ├── batch_inference.py # [CD] Batch Inference pipeline
│ ├── deployment.py # [CD] Deployment pipeline
│ └── training.py # [CT] Training Pipeline
├── steps # logically grouped `zenml.steps` implementations
│ ├── alerts # alert developer on pipeline status
│ ├── deployment # deploy trained model objects
│ ├── data_quality # quality gates built on top of drift report
│ ├── etl # ETL logic for dataset
│ ├── hp_tuning # tune hyperparameters and model architectures
│ ├── inference # inference on top of the model from the registry
│ ├── promotion # find if a newly trained model will be new inference
│ └── training # train and evaluate model
├── utils # helper functions
├── .dockerignore
├── inference_config.yaml # the configuration of the batch inference pipeline
├── Makefile # helper scripts for quick start with integrations
├── README.md # this file
├── requirements.txt # extra Python dependencies
├── run.py # CLI tool to run pipelines on ZenML Stack
└── train_config.yaml # the configuration of the training pipeline
├── Makefile # helper scripts for quick start with integrations
├── README.md # this file
├── requirements.txt # extra Python dependencies
└── run.py # CLI tool to run pipelines on ZenML Stack
```
31 changes: 31 additions & 0 deletions template/configs/deployer_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# {% include 'template/license_header' %}

# environment configuration
settings:
docker:
required_integrations:
- aws
{%- if data_quality_checks %}
- evidently
{%- endif %}
- kubeflow
- kubernetes
- mlflow
- sklearn
- slack

# configuration of steps
steps:
notify_on_success:
parameters:
notify_on_success: False

# configuration of the Model Control Plane
model_config:
name: {{ product_name }}
version: {{ target_environment }}

# pipeline level extra configurations
extra:
notify_on_failure: True

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# {% include 'template/license_header' %}

# environment configuration
settings:
docker:
required_integrations:
Expand All @@ -12,15 +13,19 @@ settings:
- mlflow
- sklearn
- slack
extra:
mlflow_model_name: {{ product_name }}
{%- if target_environment == 'production' %}
target_env: Production
{%- else %}
target_env: Staging
{%- endif %}
notify_on_success: False
notify_on_failure: True

# configuration of steps
steps:
notify_on_success:
parameters:
notify_on_success: False

# configuration of the Model Control Plane
model_config:
name: {{ product_name }}
version: {{ target_environment }}

# pipeline level extra configurations
extra:
notify_on_failure: True

74 changes: 46 additions & 28 deletions template/train_config.yaml → template/configs/train_config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# {% include 'template/license_header' %}

# environment configuration
settings:
docker:
required_integrations:
Expand All @@ -12,18 +13,53 @@ settings:
- mlflow
- sklearn
- slack
extra:
mlflow_model_name: {{ product_name }}
{%- if target_environment == 'production' %}
target_env: Production

# configuration of steps
steps:
model_trainer:
parameters:
name: {{ product_name }}
{%- if metric_compare_promotion %}
compute_performance_metrics_on_current_data:
parameters:
target_env: {{ target_environment }}
promote_with_metric_compare:
{%- else %}
target_env: Staging
promote_latest_version:
{%- endif %}
notify_on_success: False
parameters:
mlflow_model_name: {{ product_name }}
target_env: {{ target_environment }}
notify_on_success:
parameters:
notify_on_success: False

# configuration of the Model Control Plane
model_config:
name: {{ product_name }}
license: {{ open_source_license }}
description: {{ product_name }} E2E Batch Use Case
audience: All ZenML users
use_cases: |
The {{project_name}} project demonstrates how the most important steps of
the ML Production Lifecycle can be implemented in a reusable way remaining
agnostic to the underlying infrastructure, and shows how to integrate them together
into pipelines for Training and Batch Inference purposes.
ethics: No impact.
tags:
- e2e
- batch
- sklearn
- from template
- ZenML delivered
create_new_model_version: true

# pipeline level extra configurations
extra:
notify_on_failure: True
{%- if hyperparameters_tuning %}
# This set contains all the models that you want to evaluate
# during hyperparameter tuning stage.
# This set contains all the model configurations that you want
# to evaluate during hyperparameter tuning stage.
model_search_space:
random_forest:
model_package: sklearn.ensemble
Expand Down Expand Up @@ -67,30 +103,12 @@ extra:
start: 1
end: 10
{%- else %}
# This model configuration will be used for the training stage.
# This model configuration will be used for the training stage.
model_configuration:
model_package: sklearn.tree
model_class: DecisionTreeClassifier
params:
criterion: gini
max_depth: 5
min_samples_leaf: 3
{%- endif %}
model_config:
name: {{ product_name }}
license: {{ open_source_license }}
description: {{ product_name }} E2E Batch Use Case
audience: All ZenML users
use_cases: |
The {{project_name}} project demonstrates how the most important steps of
the ML Production Lifecycle can be implemented in a reusable way remaining
agnostic to the underlying infrastructure, and shows how to integrate them together
into pipelines for Training and Batch Inference purposes.
ethics: No impact.
tags:
- e2e
- batch
- sklearn
- from template
- ZenML delivered
create_new_model_version: true
{%- endif %}
1 change: 1 addition & 0 deletions template/pipelines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

from .batch_inference import {{product_name}}_batch_inference
from .training import {{product_name}}_training
from .deployment import {{product_name}}_deployment
23 changes: 8 additions & 15 deletions template/pipelines/batch_inference.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
# {% include 'template/license_header' %}


from steps import (
data_loader,
{%- if data_quality_checks %}
drift_quality_gate,
{%- endif %}
inference_data_preprocessor,
inference_get_current_version,
inference_predict,
notify_on_failure,
notify_on_success,
)
from zenml import get_pipeline_context, pipeline
from zenml import pipeline
from zenml.integrations.evidently.metrics import EvidentlyMetricConfig
from zenml.integrations.evidently.steps import evidently_report_step
from zenml.integrations.mlflow.steps.mlflow_deployer import (
mlflow_model_registry_deployer_step,
)
from zenml.logger import get_logger
from zenml.artifacts.external_artifact import ExternalArtifact

Expand All @@ -36,7 +31,13 @@ def {{product_name}}_batch_inference():
# Link all the steps together by calling them and passing the output
# of one step as the input of the next step.
########## ETL stage ##########
df_inference, target = data_loader(is_inference=True)
df_inference, target, _ = data_loader(
random_state=ExternalArtifact(
model_artifact_pipeline_name="{{product_name}}_training",
model_artifact_name="random_state",
),
is_inference=True
)
df_inference = inference_data_preprocessor(
dataset_inf=df_inference,
preprocess_pipeline=ExternalArtifact(
Expand All @@ -60,15 +61,7 @@ def {{product_name}}_batch_inference():
drift_quality_gate(report)
{%- endif %}
########## Inference stage ##########
deployment_service = mlflow_model_registry_deployer_step(
registry_model_name=get_pipeline_context().extra["mlflow_model_name"],
registry_model_version=ExternalArtifact(
model_artifact_name="promoted_version",
),
replace_existing=True,
)
inference_predict(
deployment_service=deployment_service,
dataset_inf=df_inference,
{%- if data_quality_checks %}
after=["drift_quality_gate"],
Expand Down
22 changes: 22 additions & 0 deletions template/pipelines/deployment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# {% include 'template/license_header' %}

from steps import deployment_deploy,notify_on_success,notify_on_failure

from zenml import pipeline


@pipeline(on_failure=notify_on_failure)
def {{product_name}}_deployment():
"""
Model deployment pipeline.

This is a pipeline deploys trained model for future inference.
"""
### ADD YOUR OWN CODE HERE - THIS IS JUST AN EXAMPLE ###
# Link all the steps together by calling them and passing the output
# of one step as the input of the next step.
########## Deployment stage ##########
deployment_deploy()

notify_on_success(after=["deployment_deploy"])
### YOUR CODE ENDS HERE ###
Loading
Loading