orient_express 0.3.3__tar.gz → 0.3.4__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.
- {orient_express-0.3.3 → orient_express-0.3.4}/PKG-INFO +2 -1
- {orient_express-0.3.3 → orient_express-0.3.4}/orient_express/model_wrapper.py +21 -19
- orient_express-0.3.4/orient_express/sklearn_pipeline.py +81 -0
- {orient_express-0.3.3 → orient_express-0.3.4}/pyproject.toml +2 -1
- {orient_express-0.3.3 → orient_express-0.3.4}/README.md +0 -0
- {orient_express-0.3.3 → orient_express-0.3.4}/orient_express/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: orient_express
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
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,6 +12,7 @@ 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)
|
|
15
16
|
Requires-Dist: pandas
|
|
16
17
|
Description-Content-Type: text/markdown
|
|
17
18
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
2
4
|
import joblib
|
|
3
5
|
import logging
|
|
4
6
|
import pandas as pd
|
|
@@ -9,20 +11,20 @@ from google.cloud import aiplatform
|
|
|
9
11
|
class ModelExpress:
|
|
10
12
|
def __init__(
|
|
11
13
|
self,
|
|
12
|
-
model_name,
|
|
13
|
-
project_name,
|
|
14
|
-
bucket_name,
|
|
15
|
-
model_version=None,
|
|
16
|
-
model=None,
|
|
17
|
-
region="us-central1",
|
|
18
|
-
serialized_model_path="model.joblib",
|
|
19
|
-
serving_container_image_uri="us-west1-docker.pkg.dev/shiftsmart-api/orient-express/xgboost-scikit-learn:latest",
|
|
20
|
-
serving_container_predict_route="/v1/models/orient-express-model:predict",
|
|
21
|
-
serving_container_health_route="/v1/models/orient-express-model",
|
|
22
|
-
endpoint_name=None,
|
|
14
|
+
model_name: str,
|
|
15
|
+
project_name: str,
|
|
16
|
+
bucket_name: str,
|
|
17
|
+
model_version: Optional[int] = None,
|
|
18
|
+
model: object = None,
|
|
19
|
+
region: str = "us-central1",
|
|
20
|
+
serialized_model_path: str = "model.joblib",
|
|
21
|
+
serving_container_image_uri: str = "us-west1-docker.pkg.dev/shiftsmart-api/orient-express/xgboost-scikit-learn:latest",
|
|
22
|
+
serving_container_predict_route: str = "/v1/models/orient-express-model:predict",
|
|
23
|
+
serving_container_health_route: str = "/v1/models/orient-express-model",
|
|
24
|
+
endpoint_name: Optional[str] = None,
|
|
23
25
|
machine_type="n1-standard-4",
|
|
24
|
-
min_replica_count=1,
|
|
25
|
-
max_replica_count=1,
|
|
26
|
+
min_replica_count: int = 1,
|
|
27
|
+
max_replica_count: int = 1,
|
|
26
28
|
):
|
|
27
29
|
self.model = model
|
|
28
30
|
self.model_name = model_name
|
|
@@ -56,7 +58,7 @@ class ModelExpress:
|
|
|
56
58
|
aiplatform.init(project=self.project_name, location=self.region)
|
|
57
59
|
self._vertex_initialized = True
|
|
58
60
|
|
|
59
|
-
def get_latest_vertex_model(self, model_name):
|
|
61
|
+
def get_latest_vertex_model(self, model_name: str):
|
|
60
62
|
"""If there are a few models with the same name, load the most recent one.
|
|
61
63
|
It's highly recommended to keep only 1 model with the same name to avoid the confusion
|
|
62
64
|
"""
|
|
@@ -96,7 +98,7 @@ class ModelExpress:
|
|
|
96
98
|
|
|
97
99
|
return self.create_model_version(new_version, last_model)
|
|
98
100
|
|
|
99
|
-
def get_artifacts_path(self, version, file_name=None):
|
|
101
|
+
def get_artifacts_path(self, version: int, file_name: str = None):
|
|
100
102
|
dir_name = f"models/{self.model_name}/{version}"
|
|
101
103
|
if file_name:
|
|
102
104
|
return f"{dir_name}/{file_name}"
|
|
@@ -159,7 +161,7 @@ class ModelExpress:
|
|
|
159
161
|
traffic_percentage=100,
|
|
160
162
|
)
|
|
161
163
|
|
|
162
|
-
def remote_predict(self, input_df):
|
|
164
|
+
def remote_predict(self, input_df: pd.DataFrame):
|
|
163
165
|
self._vertex_init()
|
|
164
166
|
|
|
165
167
|
if not self.endpoint:
|
|
@@ -174,7 +176,7 @@ class ModelExpress:
|
|
|
174
176
|
predictions = self.endpoint.predict(instances=instances)
|
|
175
177
|
return predictions.predictions
|
|
176
178
|
|
|
177
|
-
def local_predict(self, input_df):
|
|
179
|
+
def local_predict(self, input_df: pd.DataFrame):
|
|
178
180
|
self._vertex_init()
|
|
179
181
|
|
|
180
182
|
if not self.model:
|
|
@@ -182,7 +184,7 @@ class ModelExpress:
|
|
|
182
184
|
|
|
183
185
|
return self.model.predict(input_df)
|
|
184
186
|
|
|
185
|
-
def local_predict_proba(self, input_df):
|
|
187
|
+
def local_predict_proba(self, input_df: pd.DataFrame):
|
|
186
188
|
if not self.model:
|
|
187
189
|
self.load_model_from_registry()
|
|
188
190
|
|
|
@@ -207,7 +209,7 @@ class ModelExpress:
|
|
|
207
209
|
|
|
208
210
|
self.model = joblib.load(self.serialized_model_path)
|
|
209
211
|
|
|
210
|
-
def download_artifacts(self, artifact_uri):
|
|
212
|
+
def download_artifacts(self, artifact_uri: str):
|
|
211
213
|
storage_client = storage.Client()
|
|
212
214
|
bucket_name, artifact_path = artifact_uri.replace("gs://", "").split("/", 1)
|
|
213
215
|
bucket = storage_client.bucket(bucket_name)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from sklearn.base import BaseEstimator, TransformerMixin
|
|
2
|
+
from sklearn.preprocessing import LabelEncoder
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class LabelEncoderTransformer(BaseEstimator, TransformerMixin):
|
|
6
|
+
"""
|
|
7
|
+
A wrapper class that integrates a model and a label encoder to handle
|
|
8
|
+
encoded predictions and their corresponding probabilities.
|
|
9
|
+
|
|
10
|
+
Attributes:
|
|
11
|
+
model (object): A machine learning model with `fit`, `predict`, and `predict_proba` methods.
|
|
12
|
+
label_encoder (object): A label encoder that maps encoded class labels to their original string labels.
|
|
13
|
+
|
|
14
|
+
Methods:
|
|
15
|
+
fit(X, y):
|
|
16
|
+
Trains the model on the provided features and labels.
|
|
17
|
+
predict(X):
|
|
18
|
+
Predicts the classes for the given features and returns the original string labels.
|
|
19
|
+
predict_proba(X):
|
|
20
|
+
Returns the probabilities for each class for the given features, along with their original class labels.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, model: BaseEstimator, label_encoder: LabelEncoder):
|
|
24
|
+
"""
|
|
25
|
+
Initializes the LabelEncoderTransformer.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
model (BaseEstimator): A machine learning model.
|
|
29
|
+
label_encoder (LabelEncoder): A label encoder with `fit` and `inverse_transform` methods.
|
|
30
|
+
"""
|
|
31
|
+
self.model = model
|
|
32
|
+
self.label_encoder = label_encoder
|
|
33
|
+
|
|
34
|
+
def fit(self, X, y):
|
|
35
|
+
"""
|
|
36
|
+
Fits the model to the training data.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
X (array-like): Feature matrix.
|
|
40
|
+
y (array-like): Target labels.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
self: Fitted LabelEncoderTransformer instance.
|
|
44
|
+
"""
|
|
45
|
+
self.model.fit(X, y)
|
|
46
|
+
return self
|
|
47
|
+
|
|
48
|
+
def predict(self, X):
|
|
49
|
+
"""
|
|
50
|
+
Predicts the target labels and returns the original string labels.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
X (array-like): Feature matrix for predictions.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
array-like: Predicted class labels in their original form.
|
|
57
|
+
"""
|
|
58
|
+
encoded_predictions = self.model.predict(X)
|
|
59
|
+
return self.label_encoder.inverse_transform(encoded_predictions)
|
|
60
|
+
|
|
61
|
+
def predict_proba(self, X):
|
|
62
|
+
"""
|
|
63
|
+
Returns class probabilities along with their original labels.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
X (array-like): Feature matrix for predictions.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
list: A list of lists, where each inner list contains `[class_name, probability]` pairs.
|
|
70
|
+
"""
|
|
71
|
+
# Get raw probabilities
|
|
72
|
+
probabilities = self.model.predict_proba(X)
|
|
73
|
+
|
|
74
|
+
# Get all class labels
|
|
75
|
+
class_names = self.label_encoder.classes_
|
|
76
|
+
# Combine class names with probabilities
|
|
77
|
+
combined_output = [
|
|
78
|
+
[[class_name, prob] for class_name, prob in zip(class_names, sample_probs)]
|
|
79
|
+
for sample_probs in probabilities
|
|
80
|
+
]
|
|
81
|
+
return combined_output
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "orient_express"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.4"
|
|
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,6 +10,7 @@ python = ">=3.9,<3.13"
|
|
|
10
10
|
google-cloud-aiplatform = "*"
|
|
11
11
|
google-cloud-storage = "*"
|
|
12
12
|
pandas = "*"
|
|
13
|
+
jupyter = "^1.1.1"
|
|
13
14
|
|
|
14
15
|
[tool.poetry.dev-dependencies]
|
|
15
16
|
black = "24.10.0"
|
|
File without changes
|
|
File without changes
|