orient_express 0.3.4__tar.gz → 0.4.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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: orient_express
3
- Version: 0.3.4
3
+ Version: 0.4.2
4
4
  Summary: A library to simplify model deployment to Vertex AI
5
5
  Author: Alexey Zankevich
6
6
  Author-email: alex.zankevich@shiftsmart.com
@@ -12,7 +12,6 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Requires-Dist: google-cloud-aiplatform
14
14
  Requires-Dist: google-cloud-storage
15
- Requires-Dist: jupyter (>=1.1.1,<2.0.0)
16
15
  Requires-Dist: pandas
17
16
  Description-Content-Type: text/markdown
18
17
 
@@ -172,3 +171,81 @@ df = pd.DataFrame(titanic_data)
172
171
  model_wrapper.remote_predict(df)
173
172
  ```
174
173
 
174
+ ## Pipeline Deployment Function
175
+
176
+ Orient express library also have a helper function to simplify Vertex AI pipeline deployment.
177
+
178
+ Create `deploy.py` script
179
+ ```python
180
+
181
+ from orient_express.deployment import deploy_pipeline
182
+
183
+ import argparse
184
+ import conf
185
+
186
+ from pipeline import pipeline
187
+ from orient_express.deployment import deploy_pipeline
188
+
189
+
190
+ if __name__ == "__main__":
191
+ parser = argparse.ArgumentParser()
192
+ parser.add_argument("--run-type", required=True)
193
+
194
+ args = parser.parse_args()
195
+ deploy_pipeline(run_type=args.run_type,
196
+ pipeline_dsl=pipeline,
197
+ pipeline_root=conf.PIPELINE_ROOT,
198
+ pipeline_name=conf.PIPELINE_NAME,
199
+ pipeline_display_name=conf.PIPELINE_DISPLAY_NAME,
200
+ pipeline_schedule_name=conf.SCHEDULE_NAME,
201
+ gcp_project=conf.PROJECT_ID,
202
+ gcp_location='us-central1',
203
+ gcp_service_account=conf.SERVICE_ACCOUNT,
204
+ gcp_network=conf.NETWORK_NAME,
205
+ gcp_labels={"team": "ml"})
206
+ ```
207
+
208
+ And conf.py, make sure to replace the sample values with yours.
209
+ ```python
210
+
211
+ import os
212
+
213
+ BASE_PATH = "gs://pipelines-bucket/vertex-ai/pipelines"
214
+
215
+ PIPELINE_NAME = "my-pipeline"
216
+ PIPELINE_ROOT = f"{BASE_PATH}/{PIPELINE_NAME}"
217
+ PIPELINE_TEMP_ROOT = f"{BASE_PATH}/{PIPELINE_NAME}-temp"
218
+
219
+ PIPELINE_DISPLAY_NAME = "My Pipeline"
220
+ PIPELINE_DESCRIPTION = "My example pipeline"
221
+
222
+ NETWORK_NAME = "project network id"
223
+
224
+ DOCKER_IMAGE = "us-docker.pkg.dev/my-project/my-artifactory/my-pipeline:latest
225
+ BASE_IMAGE = "python:3.11"
226
+ PROJECT_ID = "my-project"
227
+ PROJECT_REGION = "us-central1"
228
+
229
+ SERVICE_ACCOUNT = "my-service-account@my-project.iam.gserviceaccount.com"
230
+ SCHEDULE_NAME = "My Pipeline"
231
+ ```
232
+
233
+ For testing it on a local machine, make sure to authorize to GCP first
234
+ ```shell
235
+
236
+ gcloud auth application-default login
237
+
238
+ ```
239
+
240
+ Finally, run the pipeline (it will execute once)
241
+ ```shell
242
+
243
+ python deploy.py --run-type single-run
244
+ ```
245
+
246
+ Or, create a scheduler to run continuously
247
+ ```shell
248
+
249
+ python deploy.py --run-type scheduled
250
+ ```
251
+
@@ -153,3 +153,81 @@ df = pd.DataFrame(titanic_data)
153
153
 
154
154
  model_wrapper.remote_predict(df)
155
155
  ```
156
+
157
+ ## Pipeline Deployment Function
158
+
159
+ Orient express library also have a helper function to simplify Vertex AI pipeline deployment.
160
+
161
+ Create `deploy.py` script
162
+ ```python
163
+
164
+ from orient_express.deployment import deploy_pipeline
165
+
166
+ import argparse
167
+ import conf
168
+
169
+ from pipeline import pipeline
170
+ from orient_express.deployment import deploy_pipeline
171
+
172
+
173
+ if __name__ == "__main__":
174
+ parser = argparse.ArgumentParser()
175
+ parser.add_argument("--run-type", required=True)
176
+
177
+ args = parser.parse_args()
178
+ deploy_pipeline(run_type=args.run_type,
179
+ pipeline_dsl=pipeline,
180
+ pipeline_root=conf.PIPELINE_ROOT,
181
+ pipeline_name=conf.PIPELINE_NAME,
182
+ pipeline_display_name=conf.PIPELINE_DISPLAY_NAME,
183
+ pipeline_schedule_name=conf.SCHEDULE_NAME,
184
+ gcp_project=conf.PROJECT_ID,
185
+ gcp_location='us-central1',
186
+ gcp_service_account=conf.SERVICE_ACCOUNT,
187
+ gcp_network=conf.NETWORK_NAME,
188
+ gcp_labels={"team": "ml"})
189
+ ```
190
+
191
+ And conf.py, make sure to replace the sample values with yours.
192
+ ```python
193
+
194
+ import os
195
+
196
+ BASE_PATH = "gs://pipelines-bucket/vertex-ai/pipelines"
197
+
198
+ PIPELINE_NAME = "my-pipeline"
199
+ PIPELINE_ROOT = f"{BASE_PATH}/{PIPELINE_NAME}"
200
+ PIPELINE_TEMP_ROOT = f"{BASE_PATH}/{PIPELINE_NAME}-temp"
201
+
202
+ PIPELINE_DISPLAY_NAME = "My Pipeline"
203
+ PIPELINE_DESCRIPTION = "My example pipeline"
204
+
205
+ NETWORK_NAME = "project network id"
206
+
207
+ DOCKER_IMAGE = "us-docker.pkg.dev/my-project/my-artifactory/my-pipeline:latest
208
+ BASE_IMAGE = "python:3.11"
209
+ PROJECT_ID = "my-project"
210
+ PROJECT_REGION = "us-central1"
211
+
212
+ SERVICE_ACCOUNT = "my-service-account@my-project.iam.gserviceaccount.com"
213
+ SCHEDULE_NAME = "My Pipeline"
214
+ ```
215
+
216
+ For testing it on a local machine, make sure to authorize to GCP first
217
+ ```shell
218
+
219
+ gcloud auth application-default login
220
+
221
+ ```
222
+
223
+ Finally, run the pipeline (it will execute once)
224
+ ```shell
225
+
226
+ python deploy.py --run-type single-run
227
+ ```
228
+
229
+ Or, create a scheduler to run continuously
230
+ ```shell
231
+
232
+ python deploy.py --run-type scheduled
233
+ ```
@@ -0,0 +1,99 @@
1
+ import logging
2
+ import argparse
3
+ from typing import Optional
4
+
5
+ from kfp import compiler, dsl
6
+
7
+ import conf
8
+ import google.cloud.aiplatform as aip
9
+
10
+
11
+ def delete_old_schedules(schedule_name):
12
+ for schedule in aip.PipelineJobSchedule.list(
13
+ filter=f'display_name="{schedule_name}"', order_by="create_time desc"
14
+ ):
15
+ logging.info(f"Deleting the old schedule {schedule}")
16
+ schedule.delete()
17
+
18
+
19
+ def deploy_pipeline(
20
+ run_type: str,
21
+ pipeline_dsl: str,
22
+ pipeline_root: str,
23
+ pipeline_name: str,
24
+ pipeline_display_name: str,
25
+ pipeline_schedule_name: str,
26
+ gcp_project: str,
27
+ gcp_location: str,
28
+ gcp_service_account: str,
29
+ gcp_network: str,
30
+ gcp_labels: Optional[dict[str, str]] = {},
31
+ cron_string: Optional[str] = "*/15 * * * *",
32
+ template_path: Optional[str] = "pipeline.yaml",
33
+ pipeline_job_parameters: Optional[dict] = {},
34
+ max_concurrent_run_count: Optional[int] = 1,
35
+ ):
36
+ """
37
+ :param run_type: "single-run" or "scheduled"
38
+ :param pipeline_dsl: pipeline DSL object
39
+ :param pipeline_root: a root folder for the pipelines to keep their intermediate data
40
+ :param pipeline_name: pipeline name
41
+ :param pipeline_display_name: human readable name of the pipeline
42
+ :param cron_string: a string that defines how often the pipeline should run
43
+ :param template_path: a path to a template yaml file (pipeline.yaml by default)
44
+ :param gcp_labels: additional labels to add to the pipeline
45
+ :param pipeline_job_parameters: additional parameters to pass to the pipeline.
46
+ Make sure to set the correct signatures of the pipeline function
47
+ :param max_concurrent_run_count: maximum number of concurrent runs
48
+ """
49
+ if run_type == "scheduled":
50
+ is_scheduled_run = True
51
+ elif run_type == "single-run":
52
+ is_scheduled_run = False
53
+ else:
54
+ raise Exception(f"Unknown run type {run_type}")
55
+
56
+ print("### Deployment Summary")
57
+ compiler.Compiler().compile(pipeline_dsl, package_path=template_path)
58
+
59
+ aip.init(
60
+ project=gcp_project,
61
+ location=gcp_location,
62
+ service_account=gcp_service_account,
63
+ )
64
+
65
+ labels = {"run_type": run_type, "service": pipeline_name}
66
+ labels.update(gcp_labels)
67
+
68
+ # Prepare the pipeline job
69
+ job = aip.PipelineJob(
70
+ enable_caching=False,
71
+ display_name=pipeline_display_name,
72
+ template_path=template_path,
73
+ pipeline_root=pipeline_root,
74
+ location=gcp_location,
75
+ labels=labels,
76
+ parameter_values=pipeline_job_parameters,
77
+ )
78
+ if is_scheduled_run:
79
+ delete_old_schedules(pipeline_schedule_name)
80
+
81
+ pipeline_job_schedule = aip.PipelineJobSchedule(
82
+ pipeline_job=job, display_name=pipeline_schedule_name
83
+ )
84
+
85
+ pipeline_job_schedule.create(
86
+ cron=cron_string,
87
+ max_concurrent_run_count=max_concurrent_run_count,
88
+ service_account=gcp_service_account,
89
+ network=gcp_network,
90
+ )
91
+ else:
92
+ job.submit(
93
+ service_account=gcp_service_account,
94
+ network=gcp_network,
95
+ )
96
+
97
+
98
+ def validate_pipeline(pipeline_dsl, package_path="pipeline.yaml"):
99
+ compiler.Compiler().compile(pipeline_dsl, package_path=package_path)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "orient_express"
3
- version = "0.3.4"
3
+ version = "0.4.2"
4
4
  description = "A library to simplify model deployment to Vertex AI"
5
5
  authors = ["Alexey Zankevich <alex.zankevich@shiftsmart.com>"]
6
6
  readme = "README.md"
@@ -10,7 +10,6 @@ python = ">=3.9,<3.13"
10
10
  google-cloud-aiplatform = "*"
11
11
  google-cloud-storage = "*"
12
12
  pandas = "*"
13
- jupyter = "^1.1.1"
14
13
 
15
14
  [tool.poetry.dev-dependencies]
16
15
  black = "24.10.0"