orient_express 2.1.2__tar.gz → 2.2.0__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.
Files changed (21) hide show
  1. {orient_express-2.1.2 → orient_express-2.2.0}/PKG-INFO +1 -1
  2. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/predictors/__init__.py +8 -0
  3. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/predictors/classification.py +0 -4
  4. orient_express-2.2.0/orient_express/predictors/feature_extraction.py +59 -0
  5. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/predictors/multi_label_classification.py +0 -4
  6. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/vertex.py +9 -8
  7. {orient_express-2.1.2 → orient_express-2.2.0}/pyproject.toml +1 -1
  8. {orient_express-2.1.2 → orient_express-2.2.0}/README.md +0 -0
  9. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/__init__.py +0 -0
  10. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/deployment.py +0 -0
  11. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/model_wrapper.py +0 -0
  12. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/predictors/instance_segmentation.py +0 -0
  13. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/predictors/object_detection.py +0 -0
  14. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/predictors/predictor.py +0 -0
  15. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/predictors/semantic_segmentation.py +0 -0
  16. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/sklearn_pipeline.py +0 -0
  17. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/utils/colors.py +0 -0
  18. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/utils/gs.py +0 -0
  19. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/utils/image_processor.py +0 -0
  20. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/utils/paths.py +0 -0
  21. {orient_express-2.1.2 → orient_express-2.2.0}/orient_express/utils/retry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orient_express
3
- Version: 2.1.2
3
+ Version: 2.2.0
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
@@ -21,6 +21,7 @@ from .multi_label_classification import (
21
21
  MultiLabelClassificationPredictor,
22
22
  MultiLabelClassificationPrediction,
23
23
  )
24
+ from .feature_extraction import FeatureExtractionPredictor, FeaturePrediction
24
25
 
25
26
 
26
27
  def get_predictor(dir: str, device: str = "cpu"):
@@ -62,6 +63,8 @@ def get_predictor(dir: str, device: str = "cpu"):
62
63
  return load_image_predictor(
63
64
  MultiLabelClassificationPredictor, dir, metadata, device
64
65
  )
66
+ elif model_type == FeatureExtractionPredictor.model_type:
67
+ return load_feature_extractor(dir, metadata, device)
65
68
  else:
66
69
  raise Exception(f"Unknown model_type '{model_type}'")
67
70
 
@@ -74,3 +77,8 @@ def load_image_predictor(
74
77
  raise Exception("No classes defined in metadata.yaml")
75
78
  classes = metadata["classes"]
76
79
  return model_type(onnx_path, classes, device)
80
+
81
+
82
+ def load_feature_extractor(dir: str, metadata: dict, device: str = "cpu"):
83
+ onnx_path = os.path.join(dir, metadata["model_file"])
84
+ return FeatureExtractionPredictor(onnx_path, device)
@@ -1,7 +1,5 @@
1
1
  from dataclasses import dataclass
2
2
 
3
- import cv2
4
- import numpy as np
5
3
  from PIL import Image
6
4
 
7
5
  from .predictor import OnnxSessionWrapper, ImagePredictor
@@ -24,9 +22,7 @@ class ClassificationPrediction:
24
22
  class OnnxClassifier(OnnxSessionWrapper):
25
23
  def __call__(self, pil_images: list[Image.Image]):
26
24
  images_array = self.collate_images(pil_images)
27
-
28
25
  input_dict = {self.input_names[0]: images_array}
29
-
30
26
  scores = self.session.run(None, input_dict)[0]
31
27
  return scores
32
28
 
@@ -0,0 +1,59 @@
1
+ import os
2
+ from dataclasses import dataclass
3
+
4
+ import yaml
5
+ import numpy as np
6
+ from PIL import Image
7
+
8
+ from .predictor import OnnxSessionWrapper, ImagePredictor
9
+ from ..utils.paths import get_metadata_path
10
+
11
+
12
+ @dataclass
13
+ class FeaturePrediction:
14
+ feature: np.ndarray
15
+
16
+ def to_dict(self):
17
+ return {
18
+ "feature": self.feature.tolist(),
19
+ }
20
+
21
+
22
+ class OnnxFeatureExtractor(OnnxSessionWrapper):
23
+ def __call__(self, pil_images: list[Image.Image]):
24
+ images_array = self.collate_images(pil_images)
25
+ input_dict = {self.input_names[0]: images_array}
26
+ features = self.session.run(None, input_dict)[0]
27
+ return features
28
+
29
+
30
+ class FeatureExtractionPredictor(ImagePredictor):
31
+ model_type = "feature-extraction-onnx"
32
+ backend_model = OnnxFeatureExtractor
33
+
34
+ def __init__(self, model_path: str, device: str = "cpu"):
35
+ self.model = self.backend_model(model_path, device)
36
+ self.model_path = model_path
37
+
38
+ def predict(self, images: list[Image.Image]) -> list[FeaturePrediction]:
39
+ if not images:
40
+ return []
41
+ raw_outputs = self.model(images)
42
+ outputs = []
43
+ for feature in raw_outputs:
44
+ outputs.append(FeaturePrediction(feature=feature))
45
+ return outputs
46
+
47
+ def get_annotated_image(self, image: Image.Image, predictions: FeaturePrediction):
48
+ return None
49
+
50
+ def dump(self, dir: str):
51
+ metadata = {
52
+ "model_type": self.model_type,
53
+ "model_file": os.path.basename(self.model_path),
54
+ }
55
+ metadata_path = get_metadata_path(dir)
56
+ with open(metadata_path, "w") as f:
57
+ yaml.dump(metadata, f)
58
+ # model is already saved in the model_path
59
+ return [metadata_path, self.model_path]
@@ -1,7 +1,5 @@
1
1
  from dataclasses import dataclass
2
2
 
3
- import cv2
4
- import numpy as np
5
3
  from PIL import Image
6
4
 
7
5
  from .predictor import OnnxSessionWrapper, ImagePredictor
@@ -22,9 +20,7 @@ class MultiLabelClassificationPrediction:
22
20
  class OnnxMultiLabelClassifier(OnnxSessionWrapper):
23
21
  def __call__(self, pil_images: list[Image.Image]):
24
22
  images_array = self.collate_images(pil_images)
25
-
26
23
  input_dict = {self.input_names[0]: images_array}
27
-
28
24
  scores = self.session.run(None, input_dict)[0]
29
25
  return scores
30
26
 
@@ -76,13 +76,15 @@ class VertexModel:
76
76
  predictions = self.endpoint.predict(instances=instances, parameters=parameters)
77
77
  return predictions.predictions
78
78
 
79
- def get_local_predictor(self, device: str = "cpu"):
79
+ def get_local_predictor(self, device: str = "cpu", force_download: bool = False):
80
80
  dir = os.path.join(ARTIFACT_DIR, self.model_name + "-" + str(self.version))
81
- self.download_artifacts(dir)
81
+ self.download_artifacts(dir, force_download=force_download)
82
82
  return get_predictor(dir, device)
83
83
 
84
- def download_artifacts(self, dir: str):
85
- download_artifacts(dir, self.vertex_model.gca_resource.artifact_uri)
84
+ def download_artifacts(self, dir: str, force_download: bool = True):
85
+ download_artifacts(
86
+ dir, self.vertex_model.gca_resource.artifact_uri, force_download
87
+ )
86
88
 
87
89
 
88
90
  def vertex_init(project_name: str, region: str):
@@ -92,18 +94,17 @@ def vertex_init(project_name: str, region: str):
92
94
  _vertex_initialized = True
93
95
 
94
96
 
95
- def download_artifacts(dir: str, artifact_uri: str):
97
+ def download_artifacts(dir: str, artifact_uri: str, force_download: bool = True):
96
98
  storage_client = storage.Client()
97
-
98
99
  bucket_name, artifact_path = artifact_uri.replace("gs://", "").split("/", 1)
99
100
  bucket = storage_client.bucket(bucket_name)
100
-
101
101
  os.makedirs(dir, exist_ok=True)
102
-
103
102
  blobs = bucket.list_blobs(prefix=artifact_path)
104
103
  for blob in blobs:
105
104
  filename = blob.name.split("/")[-1]
106
105
  download_path = os.path.join(dir, filename)
106
+ if not force_download and os.path.exists(download_path):
107
+ continue
107
108
  blob.download_to_filename(download_path)
108
109
 
109
110
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "orient_express"
3
- version = "2.1.2"
3
+ version = "2.2.0"
4
4
  description = "A library to simplify model deployment to Vertex AI"
5
5
  authors = ["Alexey Zankevich <alex.zankevich@shiftsmart.com>", "Ian Myers <ian.myers@shiftsmart.com>"]
6
6
  readme = "README.md"
File without changes