gimlet-api 0.0.1__py3-none-any.whl → 0.0.4__py3-none-any.whl
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.
- gimlet_api-0.0.4.dist-info/METADATA +16 -0
- gimlet_api-0.0.4.dist-info/RECORD +43 -0
- {gimlet_api-0.0.1.dist-info → gimlet_api-0.0.4.dist-info}/WHEEL +1 -2
- gml/__init__.py +18 -0
- gml/_utils.py +42 -0
- gml/client.py +308 -0
- gml/compile.py +44 -8
- gml/model.py +150 -0
- gml/model_utils.py +33 -0
- gml/pipelines.py +149 -0
- gml/preprocessing.py +78 -0
- gml/proto/gogoproto/gogo_pb2.py +101 -0
- gml/proto/mediapipe/framework/calculator_contract_test_pb2.py +32 -0
- gml/proto/mediapipe/framework/calculator_options_pb2.py +28 -0
- gml/proto/mediapipe/framework/calculator_pb2.py +56 -0
- gml/proto/mediapipe/framework/calculator_profile_pb2.py +47 -0
- gml/proto/mediapipe/framework/mediapipe_options_pb2.py +26 -0
- gml/proto/mediapipe/framework/packet_factory_pb2.py +30 -0
- gml/proto/mediapipe/framework/packet_generator_pb2.py +32 -0
- gml/proto/mediapipe/framework/packet_test_pb2.py +32 -0
- gml/proto/mediapipe/framework/status_handler_pb2.py +27 -0
- gml/proto/mediapipe/framework/stream_handler_pb2.py +29 -0
- gml/proto/mediapipe/framework/test_calculators_pb2.py +32 -0
- gml/proto/mediapipe/framework/thread_pool_executor_pb2.py +30 -0
- gml/proto/opentelemetry/proto/common/v1/common_pb2.py +34 -0
- gml/proto/opentelemetry/proto/metrics/v1/metrics_pb2.py +62 -0
- gml/proto/opentelemetry/proto/resource/v1/resource_pb2.py +27 -0
- gml/proto/src/api/corepb/v1/controlplane_pb2.py +60 -0
- gml/proto/src/api/corepb/v1/cp_edge_pb2.py +117 -0
- gml/proto/src/api/corepb/v1/mediastream_pb2.py +66 -0
- gml/proto/src/api/corepb/v1/model_exec_pb2.py +167 -0
- gml/proto/src/common/typespb/jwt_pb2.py +61 -0
- gml/proto/src/common/typespb/status_pb2.py +29 -0
- gml/proto/src/common/typespb/uuid_pb2.py +26 -0
- gml/proto/src/controlplane/directory/directorypb/v1/directory_pb2.py +115 -0
- gml/proto/src/controlplane/directory/directorypb/v1/directory_pb2_grpc.py +452 -0
- gml/proto/src/controlplane/filetransfer/ftpb/v1/ftpb_pb2.py +70 -0
- gml/proto/src/controlplane/filetransfer/ftpb/v1/ftpb_pb2_grpc.py +231 -0
- gml/proto/src/controlplane/logicalpipeline/lppb/v1/lppb_pb2.py +57 -0
- gml/proto/src/controlplane/logicalpipeline/lppb/v1/lppb_pb2_grpc.py +132 -0
- gml/proto/src/controlplane/model/mpb/v1/mpb_pb2.py +47 -0
- gml/proto/src/controlplane/model/mpb/v1/mpb_pb2_grpc.py +99 -0
- gml/tensor.py +333 -0
- gimlet_api-0.0.1.dist-info/METADATA +0 -6
- gimlet_api-0.0.1.dist-info/RECORD +0 -6
- gimlet_api-0.0.1.dist-info/top_level.txt +0 -1
gml/tensor.py
ADDED
@@ -0,0 +1,333 @@
|
|
1
|
+
# Copyright 2023- Gimlet Labs, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
#
|
15
|
+
# SPDX-License-Identifier: Apache-2.0
|
16
|
+
|
17
|
+
import abc
|
18
|
+
from typing import List, Literal, Optional, Tuple
|
19
|
+
|
20
|
+
import gml.proto.src.api.corepb.v1.model_exec_pb2 as modelexecpb
|
21
|
+
import google.protobuf.wrappers_pb2 as wrapperspb
|
22
|
+
|
23
|
+
|
24
|
+
def box_format_str_to_proto(box_format: str):
|
25
|
+
match box_format.lower():
|
26
|
+
case "cxcywh":
|
27
|
+
return modelexecpb.BoundingBoxInfo.BOUNDING_BOX_FORMAT_CXCYWH
|
28
|
+
case "xyxy":
|
29
|
+
return modelexecpb.BoundingBoxInfo.BOUNDING_BOX_FORMAT_XYXY
|
30
|
+
case "yxyx":
|
31
|
+
return modelexecpb.BoundingBoxInfo.BOUNDING_BOX_FORMAT_YXYX
|
32
|
+
case _:
|
33
|
+
raise ValueError("Invalid bounding box format: {}".format(box_format))
|
34
|
+
|
35
|
+
|
36
|
+
class BoundingBoxFormat:
|
37
|
+
def __init__(self, box_format: str = "cxcywh", is_normalized: bool = True):
|
38
|
+
self.box_format = box_format_str_to_proto(box_format)
|
39
|
+
self.is_normalized = is_normalized
|
40
|
+
|
41
|
+
def to_proto(self) -> modelexecpb.BoundingBoxInfo:
|
42
|
+
return modelexecpb.BoundingBoxInfo(
|
43
|
+
box_format=self.box_format,
|
44
|
+
box_normalized=self.is_normalized,
|
45
|
+
)
|
46
|
+
|
47
|
+
|
48
|
+
class DimensionSemantics(abc.ABC):
|
49
|
+
@abc.abstractmethod
|
50
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
51
|
+
pass
|
52
|
+
|
53
|
+
|
54
|
+
class BatchDimension(DimensionSemantics):
|
55
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
56
|
+
return modelexecpb.DimensionSemantics(
|
57
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_BATCH,
|
58
|
+
)
|
59
|
+
|
60
|
+
|
61
|
+
class IgnoreDimension(DimensionSemantics):
|
62
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
63
|
+
return modelexecpb.DimensionSemantics(
|
64
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_IGNORE,
|
65
|
+
)
|
66
|
+
|
67
|
+
|
68
|
+
def chan_format_str_to_proto(chan_format: str):
|
69
|
+
match chan_format.lower():
|
70
|
+
case "rgb":
|
71
|
+
return (
|
72
|
+
modelexecpb.DimensionSemantics.ImageChannelParams.IMAGE_CHANNEL_FORMAT_RGB
|
73
|
+
)
|
74
|
+
case "bgr":
|
75
|
+
return (
|
76
|
+
modelexecpb.DimensionSemantics.ImageChannelParams.IMAGE_CHANNEL_FORMAT_BGR
|
77
|
+
)
|
78
|
+
case _:
|
79
|
+
raise ValueError("Invalid channel_format format: {}".format(chan_format))
|
80
|
+
|
81
|
+
|
82
|
+
class ImageChannelDimension(DimensionSemantics):
|
83
|
+
def __init__(self, channel_format="rgb"):
|
84
|
+
self.channel_format = chan_format_str_to_proto(channel_format)
|
85
|
+
|
86
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
87
|
+
return modelexecpb.DimensionSemantics(
|
88
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_IMAGE_CHANNEL,
|
89
|
+
image_channel_params=modelexecpb.DimensionSemantics.ImageChannelParams(
|
90
|
+
format=self.channel_format,
|
91
|
+
),
|
92
|
+
)
|
93
|
+
|
94
|
+
|
95
|
+
class ImageHeightDimension(DimensionSemantics):
|
96
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
97
|
+
return modelexecpb.DimensionSemantics(
|
98
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_IMAGE_HEIGHT,
|
99
|
+
)
|
100
|
+
|
101
|
+
|
102
|
+
class ImageWidthDimension(DimensionSemantics):
|
103
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
104
|
+
return modelexecpb.DimensionSemantics(
|
105
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_IMAGE_WIDTH,
|
106
|
+
)
|
107
|
+
|
108
|
+
|
109
|
+
class DetectionNumCandidatesDimension(DimensionSemantics):
|
110
|
+
def __init__(self, is_nms: bool = False):
|
111
|
+
self.is_nms = is_nms
|
112
|
+
|
113
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
114
|
+
return modelexecpb.DimensionSemantics(
|
115
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_DETECTION_CANDIDATES,
|
116
|
+
detection_candidates_params=modelexecpb.DimensionSemantics.DetectionCandidatesParams(
|
117
|
+
is_nms_boxes=self.is_nms
|
118
|
+
),
|
119
|
+
)
|
120
|
+
|
121
|
+
|
122
|
+
class DetectionOutputDimension(DimensionSemantics):
|
123
|
+
def __init__(
|
124
|
+
self,
|
125
|
+
coordinates_start_index: int,
|
126
|
+
box_format: BoundingBoxFormat,
|
127
|
+
box_confidence_index: Optional[int] = None,
|
128
|
+
class_index: Optional[int] = None,
|
129
|
+
scores_range: Optional[Tuple[int, int]] = None,
|
130
|
+
):
|
131
|
+
self.coordinates_range = (coordinates_start_index, 4)
|
132
|
+
self.box_format = box_format
|
133
|
+
self.box_confidence_index = box_confidence_index
|
134
|
+
self.class_index = class_index
|
135
|
+
self.scores_range = scores_range
|
136
|
+
|
137
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
138
|
+
scores_range = None
|
139
|
+
if self.scores_range is not None:
|
140
|
+
scores_range = (
|
141
|
+
modelexecpb.DimensionSemantics.DetectionOutputParams.IndexRange(
|
142
|
+
start=self.scores_range[0],
|
143
|
+
size=self.scores_range[1],
|
144
|
+
)
|
145
|
+
)
|
146
|
+
box_confidence_index = -1
|
147
|
+
if self.box_confidence_index is not None:
|
148
|
+
box_confidence_index = self.box_confidence_index
|
149
|
+
return modelexecpb.DimensionSemantics(
|
150
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_DETECTION_OUTPUT,
|
151
|
+
detection_output_params=modelexecpb.DimensionSemantics.DetectionOutputParams(
|
152
|
+
box_coordinate_range=modelexecpb.DimensionSemantics.DetectionOutputParams.IndexRange(
|
153
|
+
start=self.coordinates_range[0],
|
154
|
+
size=self.coordinates_range[1],
|
155
|
+
),
|
156
|
+
box_format=self.box_format.to_proto(),
|
157
|
+
box_confidence_index=box_confidence_index,
|
158
|
+
class_index=self.class_index,
|
159
|
+
scores_range=scores_range,
|
160
|
+
),
|
161
|
+
)
|
162
|
+
|
163
|
+
|
164
|
+
def _segmentation_mask_kind_to_proto(kind: str):
|
165
|
+
match kind.lower():
|
166
|
+
case "bool_masks":
|
167
|
+
return (
|
168
|
+
modelexecpb.DimensionSemantics.SegmentationMaskParams.SEGMENTATION_MASK_KIND_BOOL
|
169
|
+
)
|
170
|
+
case "int_label_masks":
|
171
|
+
return (
|
172
|
+
modelexecpb.DimensionSemantics.SegmentationMaskParams.SEGMENTATION_MASK_KIND_CLASS_LABEL
|
173
|
+
)
|
174
|
+
case "score_masks":
|
175
|
+
return (
|
176
|
+
modelexecpb.DimensionSemantics.SegmentationMaskParams.SEGMENTATION_MASK_KIND_SCORE
|
177
|
+
)
|
178
|
+
case _:
|
179
|
+
raise ValueError("Invalid segmentation mask kind: {}".format(kind))
|
180
|
+
|
181
|
+
|
182
|
+
class SegmentationMaskChannel(DimensionSemantics):
|
183
|
+
def __init__(self, kind: Literal["bool_masks", "int_label_masks", "score_masks"]):
|
184
|
+
self.kind = _segmentation_mask_kind_to_proto(kind)
|
185
|
+
|
186
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
187
|
+
return modelexecpb.DimensionSemantics(
|
188
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_SEGMENTATION_MASK_CHANNEL,
|
189
|
+
segmentation_mask_params=modelexecpb.DimensionSemantics.SegmentationMaskParams(
|
190
|
+
kind=self.kind,
|
191
|
+
),
|
192
|
+
)
|
193
|
+
|
194
|
+
|
195
|
+
class LabelsDimension(DimensionSemantics):
|
196
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
197
|
+
return modelexecpb.DimensionSemantics(
|
198
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_CLASS_LABELS
|
199
|
+
)
|
200
|
+
|
201
|
+
|
202
|
+
class ScoresDimension(DimensionSemantics):
|
203
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
204
|
+
return modelexecpb.DimensionSemantics(
|
205
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_CLASS_SCORES
|
206
|
+
)
|
207
|
+
|
208
|
+
|
209
|
+
class RegressionValueDimension(DimensionSemantics):
|
210
|
+
def __init__(self, label: str, scale: Optional[float] = None):
|
211
|
+
self.label = label
|
212
|
+
self.scale = scale
|
213
|
+
|
214
|
+
def to_proto(self) -> modelexecpb.DimensionSemantics:
|
215
|
+
scale = None
|
216
|
+
if self.scale is not None:
|
217
|
+
scale = wrapperspb.DoubleValue(value=self.scale)
|
218
|
+
return modelexecpb.DimensionSemantics(
|
219
|
+
kind=modelexecpb.DimensionSemantics.DIMENSION_SEMANTICS_KIND_REGRESSION_VALUE,
|
220
|
+
regression_params=modelexecpb.DimensionSemantics.RegressionParams(
|
221
|
+
label=self.label,
|
222
|
+
scale=scale,
|
223
|
+
),
|
224
|
+
)
|
225
|
+
|
226
|
+
|
227
|
+
class TensorSemantics:
|
228
|
+
def __init__(self, dimensions: List[DimensionSemantics]):
|
229
|
+
self.dimensions = dimensions
|
230
|
+
|
231
|
+
def to_proto(self) -> modelexecpb.TensorSemantics:
|
232
|
+
return modelexecpb.TensorSemantics(
|
233
|
+
dimensions=[dim.to_proto() for dim in self.dimensions],
|
234
|
+
)
|
235
|
+
|
236
|
+
|
237
|
+
class RGBImage(TensorSemantics):
|
238
|
+
"""RGBImage is an image tensor input with channels in RGB order."""
|
239
|
+
|
240
|
+
def __init__(self, channels_first=True):
|
241
|
+
if channels_first:
|
242
|
+
dimensions = [
|
243
|
+
BatchDimension(),
|
244
|
+
ImageChannelDimension(channel_format="rgb"),
|
245
|
+
ImageHeightDimension(),
|
246
|
+
ImageWidthDimension(),
|
247
|
+
]
|
248
|
+
else:
|
249
|
+
dimensions = [
|
250
|
+
BatchDimension(),
|
251
|
+
ImageHeightDimension(),
|
252
|
+
ImageWidthDimension(),
|
253
|
+
ImageChannelDimension(channel_format="rgb"),
|
254
|
+
]
|
255
|
+
super().__init__(dimensions)
|
256
|
+
|
257
|
+
|
258
|
+
class BGRImage(TensorSemantics):
|
259
|
+
"""BGRImage is an image tensor input with channels in BGR order."""
|
260
|
+
|
261
|
+
def __init__(self, channels_first=True):
|
262
|
+
if channels_first:
|
263
|
+
dimensions = [
|
264
|
+
BatchDimension(),
|
265
|
+
ImageChannelDimension(channel_format="bgr"),
|
266
|
+
ImageHeightDimension(),
|
267
|
+
ImageWidthDimension(),
|
268
|
+
]
|
269
|
+
else:
|
270
|
+
dimensions = [
|
271
|
+
BatchDimension(),
|
272
|
+
ImageHeightDimension(),
|
273
|
+
ImageWidthDimension(),
|
274
|
+
ImageChannelDimension(channel_format="bgr"),
|
275
|
+
]
|
276
|
+
super().__init__(dimensions)
|
277
|
+
|
278
|
+
|
279
|
+
class BinarySegmentationMasks(TensorSemantics):
|
280
|
+
"""BinarySegmentationMasks represents the output of a segmentation model with binary masks.
|
281
|
+
|
282
|
+
The expected tensor shape is [B, NUM_CLASSES, H, W].
|
283
|
+
For example, a segmentation model with 4 classes would output a tensor of shape [B, 4, H, W],
|
284
|
+
where each channel is a binary mask per-pixel.
|
285
|
+
"""
|
286
|
+
|
287
|
+
def __init__(self):
|
288
|
+
dimensions = [
|
289
|
+
BatchDimension(),
|
290
|
+
SegmentationMaskChannel("bool_masks"),
|
291
|
+
ImageHeightDimension(),
|
292
|
+
ImageWidthDimension(),
|
293
|
+
]
|
294
|
+
super().__init__(dimensions)
|
295
|
+
|
296
|
+
|
297
|
+
class YOLOOutput(TensorSemantics):
|
298
|
+
"""YOLOOutput represents a detection output from a YOLO model.
|
299
|
+
|
300
|
+
The YOLO model should output a tensor of shape [B, N_BOXES, (4 or 5) + NUM_CLASSES].
|
301
|
+
"""
|
302
|
+
|
303
|
+
def __init__(self, has_box_conf=True):
|
304
|
+
dimensions = [
|
305
|
+
BatchDimension(),
|
306
|
+
DetectionNumCandidatesDimension(is_nms=False),
|
307
|
+
]
|
308
|
+
|
309
|
+
if has_box_conf:
|
310
|
+
dimensions.append(
|
311
|
+
DetectionOutputDimension(
|
312
|
+
coordinates_start_index=0,
|
313
|
+
box_format=BoundingBoxFormat(
|
314
|
+
box_format="cxcywh",
|
315
|
+
is_normalized=False,
|
316
|
+
),
|
317
|
+
box_confidence_index=4,
|
318
|
+
scores_range=(5, -1),
|
319
|
+
)
|
320
|
+
)
|
321
|
+
else:
|
322
|
+
dimensions.append(
|
323
|
+
DetectionOutputDimension(
|
324
|
+
coordinates_start_index=0,
|
325
|
+
box_format=BoundingBoxFormat(
|
326
|
+
box_format="cxcywh",
|
327
|
+
is_normalized=False,
|
328
|
+
),
|
329
|
+
scores_range=(4, -1),
|
330
|
+
)
|
331
|
+
)
|
332
|
+
|
333
|
+
super().__init__(dimensions)
|
@@ -1,6 +0,0 @@
|
|
1
|
-
gml/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
gml/compile.py,sha256=VzNVLojb8D8lISLYxazR3-YkJ6HzscP0juP7yWAltfg,869
|
3
|
-
gimlet_api-0.0.1.dist-info/METADATA,sha256=F7JACoU323q1pnbZD-KQfdJTpd_yKFBS8sXhSHhx-M4,106
|
4
|
-
gimlet_api-0.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
5
|
-
gimlet_api-0.0.1.dist-info/top_level.txt,sha256=wSbIUt3C0p7m2JMxpjK6M83pB9pqGe274eF3qgIxzS8,4
|
6
|
-
gimlet_api-0.0.1.dist-info/RECORD,,
|
@@ -1 +0,0 @@
|
|
1
|
-
gml
|