orient_express 2.3.1__tar.gz → 2.4.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.
- {orient_express-2.3.1 → orient_express-2.4.0}/PKG-INFO +26 -18
- {orient_express-2.3.1 → orient_express-2.4.0}/README.md +25 -17
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/__init__.py +1 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/predictor.py +1 -1
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/vector_index.py +37 -24
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/vertex.py +18 -11
- {orient_express-2.3.1 → orient_express-2.4.0}/pyproject.toml +1 -1
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/__init__.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/deployment.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/model_wrapper.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/classification.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/feature_extraction.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/instance_segmentation.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/multi_label_classification.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/object_detection.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/semantic_segmentation.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/sklearn_pipeline.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/utils/colors.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/utils/gs.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/utils/image_processor.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.0}/orient_express/utils/paths.py +0 -0
- {orient_express-2.3.1 → orient_express-2.4.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.
|
|
3
|
+
Version: 2.4.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
|
|
@@ -46,11 +46,13 @@ pip install orient_express
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
For local development:
|
|
49
|
+
|
|
49
50
|
```bash
|
|
50
51
|
pip install -e .
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
Or with Poetry:
|
|
55
|
+
|
|
54
56
|
```bash
|
|
55
57
|
poetry install
|
|
56
58
|
```
|
|
@@ -102,8 +104,8 @@ vertex_model.deploy_to_endpoint(
|
|
|
102
104
|
|
|
103
105
|
# remote prediction API depends on the endpoint container deployed with the model
|
|
104
106
|
predictions = vertex_model.remote_predict(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
"my-classifier-endpoint",
|
|
108
|
+
[{"image": "https://storage.googleapis.com/ssm-media-uploads/example.jpg"}],
|
|
107
109
|
)
|
|
108
110
|
```
|
|
109
111
|
|
|
@@ -179,19 +181,20 @@ predictions = local_predictor.predict(X_test)
|
|
|
179
181
|
### Platform Support Matrix
|
|
180
182
|
|
|
181
183
|
| Platform | Architecture | ONNX Runtime Package | CUDA Available |
|
|
182
|
-
|
|
183
|
-
| Linux | x86_64 | onnxruntime-gpu
|
|
184
|
-
| Linux | aarch64 | onnxruntime
|
|
185
|
-
| Windows | x64 (AMD64) | onnxruntime-gpu
|
|
186
|
-
| Windows | ARM64 | onnxruntime
|
|
187
|
-
| macOS | x86_64 | onnxruntime
|
|
188
|
-
| macOS | arm64 | onnxruntime
|
|
184
|
+
| -------- | ------------ | -------------------- | -------------- |
|
|
185
|
+
| Linux | x86_64 | onnxruntime-gpu | Yes |
|
|
186
|
+
| Linux | aarch64 | onnxruntime | No |
|
|
187
|
+
| Windows | x64 (AMD64) | onnxruntime-gpu | Yes |
|
|
188
|
+
| Windows | ARM64 | onnxruntime | No |
|
|
189
|
+
| macOS | x86_64 | onnxruntime | No |
|
|
190
|
+
| macOS | arm64 | onnxruntime | No |
|
|
189
191
|
|
|
190
192
|
The appropriate package is installed automatically based on your platform.
|
|
191
193
|
|
|
192
194
|
### Selecting CPU vs CUDA Execution
|
|
193
195
|
|
|
194
196
|
When loading a predictor, use the `device` parameter to specify the execution provider:
|
|
197
|
+
|
|
195
198
|
```python
|
|
196
199
|
from orient_express.predictors import ObjectDetectionPredictor
|
|
197
200
|
|
|
@@ -203,6 +206,7 @@ predictor = ObjectDetectionPredictor("/path/to/model", classes, device="cuda")
|
|
|
203
206
|
```
|
|
204
207
|
|
|
205
208
|
When using a Vertex AI model:
|
|
209
|
+
|
|
206
210
|
```python
|
|
207
211
|
# CPU inference
|
|
208
212
|
predictor = model.get_local_predictor(device="cpu")
|
|
@@ -540,11 +544,8 @@ index = build_vector_index(
|
|
|
540
544
|
num_workers=8, # parallel image loading
|
|
541
545
|
)
|
|
542
546
|
|
|
543
|
-
# Aggregate to one centroid per label
|
|
544
|
-
centroid_index = index.aggregate()
|
|
545
|
-
|
|
546
547
|
# Save and load
|
|
547
|
-
|
|
548
|
+
index.dump("/path/to/artifact_dir")
|
|
548
549
|
|
|
549
550
|
from orient_express.predictors import get_predictor
|
|
550
551
|
loaded_index = get_predictor("/path/to/artifact_dir")
|
|
@@ -560,16 +561,23 @@ batch_results = loaded_index.search_batch(query_matrix, k=5)
|
|
|
560
561
|
|
|
561
562
|
#### Multi-label support
|
|
562
563
|
|
|
563
|
-
Vectors can have
|
|
564
|
+
Vectors can have composite labels (use tuples). This is useful when a single visual cluster maps to multiple things:
|
|
564
565
|
|
|
565
566
|
```python
|
|
566
567
|
index = VectorIndex(
|
|
567
568
|
vectors=feature_matrix,
|
|
568
|
-
labels=[
|
|
569
|
+
labels=[("sku_101", "sku_102"), ("sku_103",)],
|
|
569
570
|
)
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
#### Per-label aggregation
|
|
570
574
|
|
|
571
|
-
|
|
572
|
-
|
|
575
|
+
Vector indices in which labels are not unique can be aggregated so that each label has a single centroid.
|
|
576
|
+
If `per_label=True` and the labels are composite (tuples), then the labels will be unpacked and aggregated separately.
|
|
577
|
+
|
|
578
|
+
```python
|
|
579
|
+
aggregated = index.aggregate(per_label=True) # 3 vectors, one per label element ["sku_101", "sku_102", "sku_103"]
|
|
580
|
+
aggregated = index.aggregate(per_label=False) # 2 vectors, one per composite label [("sku_101", "sku_102"), ("sku_103")]
|
|
573
581
|
```
|
|
574
582
|
|
|
575
583
|
#### Output Structure
|
|
@@ -19,11 +19,13 @@ pip install orient_express
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
For local development:
|
|
22
|
+
|
|
22
23
|
```bash
|
|
23
24
|
pip install -e .
|
|
24
25
|
```
|
|
25
26
|
|
|
26
27
|
Or with Poetry:
|
|
28
|
+
|
|
27
29
|
```bash
|
|
28
30
|
poetry install
|
|
29
31
|
```
|
|
@@ -75,8 +77,8 @@ vertex_model.deploy_to_endpoint(
|
|
|
75
77
|
|
|
76
78
|
# remote prediction API depends on the endpoint container deployed with the model
|
|
77
79
|
predictions = vertex_model.remote_predict(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
"my-classifier-endpoint",
|
|
81
|
+
[{"image": "https://storage.googleapis.com/ssm-media-uploads/example.jpg"}],
|
|
80
82
|
)
|
|
81
83
|
```
|
|
82
84
|
|
|
@@ -152,19 +154,20 @@ predictions = local_predictor.predict(X_test)
|
|
|
152
154
|
### Platform Support Matrix
|
|
153
155
|
|
|
154
156
|
| Platform | Architecture | ONNX Runtime Package | CUDA Available |
|
|
155
|
-
|
|
156
|
-
| Linux | x86_64 | onnxruntime-gpu
|
|
157
|
-
| Linux | aarch64 | onnxruntime
|
|
158
|
-
| Windows | x64 (AMD64) | onnxruntime-gpu
|
|
159
|
-
| Windows | ARM64 | onnxruntime
|
|
160
|
-
| macOS | x86_64 | onnxruntime
|
|
161
|
-
| macOS | arm64 | onnxruntime
|
|
157
|
+
| -------- | ------------ | -------------------- | -------------- |
|
|
158
|
+
| Linux | x86_64 | onnxruntime-gpu | Yes |
|
|
159
|
+
| Linux | aarch64 | onnxruntime | No |
|
|
160
|
+
| Windows | x64 (AMD64) | onnxruntime-gpu | Yes |
|
|
161
|
+
| Windows | ARM64 | onnxruntime | No |
|
|
162
|
+
| macOS | x86_64 | onnxruntime | No |
|
|
163
|
+
| macOS | arm64 | onnxruntime | No |
|
|
162
164
|
|
|
163
165
|
The appropriate package is installed automatically based on your platform.
|
|
164
166
|
|
|
165
167
|
### Selecting CPU vs CUDA Execution
|
|
166
168
|
|
|
167
169
|
When loading a predictor, use the `device` parameter to specify the execution provider:
|
|
170
|
+
|
|
168
171
|
```python
|
|
169
172
|
from orient_express.predictors import ObjectDetectionPredictor
|
|
170
173
|
|
|
@@ -176,6 +179,7 @@ predictor = ObjectDetectionPredictor("/path/to/model", classes, device="cuda")
|
|
|
176
179
|
```
|
|
177
180
|
|
|
178
181
|
When using a Vertex AI model:
|
|
182
|
+
|
|
179
183
|
```python
|
|
180
184
|
# CPU inference
|
|
181
185
|
predictor = model.get_local_predictor(device="cpu")
|
|
@@ -513,11 +517,8 @@ index = build_vector_index(
|
|
|
513
517
|
num_workers=8, # parallel image loading
|
|
514
518
|
)
|
|
515
519
|
|
|
516
|
-
# Aggregate to one centroid per label
|
|
517
|
-
centroid_index = index.aggregate()
|
|
518
|
-
|
|
519
520
|
# Save and load
|
|
520
|
-
|
|
521
|
+
index.dump("/path/to/artifact_dir")
|
|
521
522
|
|
|
522
523
|
from orient_express.predictors import get_predictor
|
|
523
524
|
loaded_index = get_predictor("/path/to/artifact_dir")
|
|
@@ -533,16 +534,23 @@ batch_results = loaded_index.search_batch(query_matrix, k=5)
|
|
|
533
534
|
|
|
534
535
|
#### Multi-label support
|
|
535
536
|
|
|
536
|
-
Vectors can have
|
|
537
|
+
Vectors can have composite labels (use tuples). This is useful when a single visual cluster maps to multiple things:
|
|
537
538
|
|
|
538
539
|
```python
|
|
539
540
|
index = VectorIndex(
|
|
540
541
|
vectors=feature_matrix,
|
|
541
|
-
labels=[
|
|
542
|
+
labels=[("sku_101", "sku_102"), ("sku_103",)],
|
|
542
543
|
)
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
#### Per-label aggregation
|
|
543
547
|
|
|
544
|
-
|
|
545
|
-
|
|
548
|
+
Vector indices in which labels are not unique can be aggregated so that each label has a single centroid.
|
|
549
|
+
If `per_label=True` and the labels are composite (tuples), then the labels will be unpacked and aggregated separately.
|
|
550
|
+
|
|
551
|
+
```python
|
|
552
|
+
aggregated = index.aggregate(per_label=True) # 3 vectors, one per label element ["sku_101", "sku_102", "sku_103"]
|
|
553
|
+
aggregated = index.aggregate(per_label=False) # 2 vectors, one per composite label [("sku_101", "sku_102"), ("sku_103")]
|
|
546
554
|
```
|
|
547
555
|
|
|
548
556
|
#### Output Structure
|
|
@@ -99,6 +99,7 @@ def load_vector_index(dir: str, metadata: dict | None = None):
|
|
|
99
99
|
data = np.load(artifact_path, allow_pickle=False)
|
|
100
100
|
vectors = data["vectors"]
|
|
101
101
|
labels = json.loads(str(data["labels_json"]))
|
|
102
|
+
labels = [tuple(label) if isinstance(label, list) else label for label in labels]
|
|
102
103
|
index = VectorIndex(vectors=vectors, labels=labels)
|
|
103
104
|
index.model_path = artifact_path
|
|
104
105
|
return index
|
|
@@ -46,7 +46,7 @@ class ImagePredictor(Predictor):
|
|
|
46
46
|
self.model_path = model_path
|
|
47
47
|
|
|
48
48
|
def get_serving_container_image_uri(self):
|
|
49
|
-
return "us-west1-docker.pkg.dev/shiftsmart-api/orient-express/image-onnx:v2.
|
|
49
|
+
return "us-west1-docker.pkg.dev/shiftsmart-api/orient-express/image-onnx:v2.4.0"
|
|
50
50
|
|
|
51
51
|
def get_serving_container_health_route(self, model_name):
|
|
52
52
|
return f"/v1/models/{model_name}"
|
|
@@ -2,6 +2,7 @@ import os
|
|
|
2
2
|
import json
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
import warnings
|
|
5
|
+
from typing import Any
|
|
5
6
|
|
|
6
7
|
import yaml
|
|
7
8
|
import numpy as np
|
|
@@ -37,7 +38,7 @@ class VectorIndex(Predictor):
|
|
|
37
38
|
def __init__(
|
|
38
39
|
self,
|
|
39
40
|
vectors: np.ndarray,
|
|
40
|
-
labels: list[
|
|
41
|
+
labels: list[int | str | tuple],
|
|
41
42
|
normalize: bool = False,
|
|
42
43
|
):
|
|
43
44
|
if vectors.ndim != 2:
|
|
@@ -53,8 +54,16 @@ class VectorIndex(Predictor):
|
|
|
53
54
|
# Avoid division by zero for zero vectors
|
|
54
55
|
norms = np.where(norms == 0, 1, norms)
|
|
55
56
|
vectors = vectors / norms
|
|
57
|
+
|
|
56
58
|
self.vectors = vectors
|
|
57
59
|
self.labels = labels
|
|
60
|
+
self.label_to_idx = {}
|
|
61
|
+
|
|
62
|
+
for i, label in enumerate(labels):
|
|
63
|
+
if label not in self.label_to_idx:
|
|
64
|
+
self.label_to_idx[label] = []
|
|
65
|
+
self.label_to_idx[label].append(i)
|
|
66
|
+
|
|
58
67
|
self.model_path = None
|
|
59
68
|
|
|
60
69
|
def search(self, query: np.ndarray, k: int = 1) -> list[SearchResult]:
|
|
@@ -86,21 +95,36 @@ class VectorIndex(Predictor):
|
|
|
86
95
|
)
|
|
87
96
|
return all_results
|
|
88
97
|
|
|
98
|
+
def get_by_idx(self, idx: int) -> np.ndarray:
|
|
99
|
+
return self.vectors[idx]
|
|
100
|
+
|
|
101
|
+
def get_by_idxs(self, idxs: list[int]) -> np.ndarray:
|
|
102
|
+
return self.vectors[idxs]
|
|
103
|
+
|
|
104
|
+
def get_by_label(self, label: Any) -> np.ndarray:
|
|
105
|
+
return self.vectors[self.label_to_idx[label]]
|
|
106
|
+
|
|
107
|
+
def get_by_labels(self, labels: list[Any]) -> np.ndarray:
|
|
108
|
+
idxs = []
|
|
109
|
+
for label in labels:
|
|
110
|
+
idxs.extend(self.label_to_idx[label])
|
|
111
|
+
return self.vectors[idxs]
|
|
112
|
+
|
|
89
113
|
def aggregate(self, per_label: bool = False) -> "VectorIndex":
|
|
90
114
|
"""
|
|
91
115
|
Aggregate the vectors into a single centroid per unique label group.
|
|
92
116
|
|
|
93
117
|
Args:
|
|
94
118
|
per_label: if True, create one centroid per individual label
|
|
95
|
-
(splitting label groups apart). If False (default),
|
|
96
|
-
one centroid per unique label group.
|
|
119
|
+
(splitting label groups (tuples) apart). If False (default),
|
|
120
|
+
create one centroid per unique label group.
|
|
97
121
|
"""
|
|
98
122
|
key_to_indices: dict = {}
|
|
99
|
-
for i,
|
|
100
|
-
if per_label:
|
|
101
|
-
keys =
|
|
123
|
+
for i, label in enumerate(self.labels):
|
|
124
|
+
if per_label and isinstance(label, tuple):
|
|
125
|
+
keys = label
|
|
102
126
|
else:
|
|
103
|
-
keys = [
|
|
127
|
+
keys = [label]
|
|
104
128
|
for key in keys:
|
|
105
129
|
if key not in key_to_indices:
|
|
106
130
|
key_to_indices[key] = []
|
|
@@ -119,7 +143,7 @@ class VectorIndex(Predictor):
|
|
|
119
143
|
if norm > 0:
|
|
120
144
|
centroid = centroid / norm
|
|
121
145
|
centroids[i] = centroid
|
|
122
|
-
new_labels.append(
|
|
146
|
+
new_labels.append(key)
|
|
123
147
|
|
|
124
148
|
return VectorIndex(vectors=centroids, labels=new_labels)
|
|
125
149
|
|
|
@@ -161,12 +185,9 @@ class VectorIndex(Predictor):
|
|
|
161
185
|
return self.vectors.shape[0]
|
|
162
186
|
|
|
163
187
|
def __repr__(self) -> str:
|
|
164
|
-
unique_labels = set()
|
|
165
|
-
for group in self.labels:
|
|
166
|
-
unique_labels.update(group)
|
|
167
188
|
return (
|
|
168
189
|
f"VectorIndex({len(self)} vectors, dim={self.dim}, "
|
|
169
|
-
f"{len(
|
|
190
|
+
f"{len(set(self.labels))} unique labels)"
|
|
170
191
|
)
|
|
171
192
|
|
|
172
193
|
|
|
@@ -197,11 +218,10 @@ def _collate_pil(batch):
|
|
|
197
218
|
|
|
198
219
|
def build_vector_index(
|
|
199
220
|
crops: list[Image.Image | str | CropSpec],
|
|
200
|
-
labels: list,
|
|
221
|
+
labels: list[int | str | tuple],
|
|
201
222
|
feature_extractor,
|
|
202
223
|
batch_size: int = 128,
|
|
203
224
|
normalize: bool = True,
|
|
204
|
-
multi_label: bool = False,
|
|
205
225
|
num_workers: int = 0,
|
|
206
226
|
) -> VectorIndex:
|
|
207
227
|
"""Build a VectorIndex by extracting features from crops.
|
|
@@ -210,14 +230,12 @@ def build_vector_index(
|
|
|
210
230
|
crops: images to extract features from. Each element can be a PIL
|
|
211
231
|
Image (used directly), a file path string (loaded as a whole
|
|
212
232
|
image), or a CropSpec (loaded and cropped to the specified bbox).
|
|
213
|
-
labels: one label per crop.
|
|
214
|
-
|
|
215
|
-
of labels.
|
|
233
|
+
labels: one label per crop. labels can be any hashable type, includeing
|
|
234
|
+
iterables like tuples.
|
|
216
235
|
feature_extractor: anything with a .predict(list[Image]) method that
|
|
217
236
|
returns objects with a .feature attribute (e.g. FeatureExtractionPredictor).
|
|
218
237
|
batch_size: number of crops to process at once.
|
|
219
238
|
normalize: whether to L2-normalize the resulting feature vectors.
|
|
220
|
-
multi_label: if True, labels are already lists of labels per crop.
|
|
221
239
|
num_workers: number of DataLoader workers for parallel image loading.
|
|
222
240
|
"""
|
|
223
241
|
if len(crops) != len(labels):
|
|
@@ -225,11 +243,6 @@ def build_vector_index(
|
|
|
225
243
|
f"crops length ({len(crops)}) must match labels length ({len(labels)})"
|
|
226
244
|
)
|
|
227
245
|
|
|
228
|
-
if multi_label:
|
|
229
|
-
index_labels = [list(group) for group in labels]
|
|
230
|
-
else:
|
|
231
|
-
index_labels = [[label] for label in labels]
|
|
232
|
-
|
|
233
246
|
loader = DataLoader(
|
|
234
247
|
_CropDataset(crops),
|
|
235
248
|
batch_size=batch_size,
|
|
@@ -243,4 +256,4 @@ def build_vector_index(
|
|
|
243
256
|
all_features.extend([r.feature for r in results])
|
|
244
257
|
|
|
245
258
|
vectors = np.vstack(all_features)
|
|
246
|
-
return VectorIndex(vectors=vectors, labels=
|
|
259
|
+
return VectorIndex(vectors=vectors, labels=labels, normalize=normalize)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import tempfile
|
|
3
|
+
import warnings
|
|
3
4
|
|
|
4
5
|
import yaml
|
|
5
6
|
import joblib
|
|
@@ -287,7 +288,6 @@ def get_vertex_model(
|
|
|
287
288
|
):
|
|
288
289
|
vertex_init(project_name, region)
|
|
289
290
|
models = aiplatform.Model.list(filter=f"display_name={model_name}")
|
|
290
|
-
|
|
291
291
|
if not models:
|
|
292
292
|
if raise_exception:
|
|
293
293
|
raise Exception(
|
|
@@ -295,19 +295,26 @@ def get_vertex_model(
|
|
|
295
295
|
)
|
|
296
296
|
else:
|
|
297
297
|
return None
|
|
298
|
+
if len(models) > 1:
|
|
299
|
+
warnings.warn(
|
|
300
|
+
f"Multiple models found with name '{model_name}'. Using the latest one."
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
latest_model = sorted(models, key=lambda x: x.update_time, reverse=True)[0]
|
|
304
|
+
resource_name = latest_model.resource_name
|
|
298
305
|
|
|
299
306
|
if version is None:
|
|
300
|
-
latest_model = sorted(models, key=lambda x: x.update_time, reverse=True)[0]
|
|
301
307
|
return VertexModel(
|
|
302
308
|
latest_model, model_name, project_name, region, int(latest_model.version_id)
|
|
303
309
|
)
|
|
304
310
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
311
|
+
if version is not None:
|
|
312
|
+
try:
|
|
313
|
+
model = aiplatform.Model(model_name=resource_name, version=str(version))
|
|
314
|
+
except Exception:
|
|
315
|
+
if raise_exception:
|
|
316
|
+
raise Exception(
|
|
317
|
+
f"Failed to fetch model '{model_name}' with version '{version}' in registry for project '{project_name}' region '{region}'"
|
|
318
|
+
)
|
|
319
|
+
return None
|
|
320
|
+
return VertexModel(model, model_name, project_name, region, version)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "orient_express"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.4.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/feature_extraction.py
RENAMED
|
File without changes
|
{orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/instance_segmentation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{orient_express-2.3.1 → orient_express-2.4.0}/orient_express/predictors/semantic_segmentation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|