aissemble-inference-core 1.5.0rc3__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.
- aissemble_inference_core/__init__.py +19 -0
- aissemble_inference_core/client/__init__.py +23 -0
- aissemble_inference_core/client/builder/__init__.py +36 -0
- aissemble_inference_core/client/builder/inference_builder.py +178 -0
- aissemble_inference_core/client/builder/object_detection_builder.py +190 -0
- aissemble_inference_core/client/builder/raw_inference_builder.py +95 -0
- aissemble_inference_core/client/builder/summarization_builder.py +213 -0
- aissemble_inference_core/client/inference_client.py +158 -0
- aissemble_inference_core/client/oip_adapter.py +211 -0
- aissemble_inference_core/client/predictor.py +75 -0
- aissemble_inference_core/client/registry.py +201 -0
- aissemble_inference_core/client/results/__init__.py +29 -0
- aissemble_inference_core/client/results/object_detection_result.py +155 -0
- aissemble_inference_core/client/results/summarization_result.py +78 -0
- aissemble_inference_core/client/translator.py +57 -0
- aissemble_inference_core/client/translators/__init__.py +34 -0
- aissemble_inference_core/client/translators/_image_utils.py +75 -0
- aissemble_inference_core/client/translators/_tensor_utils.py +89 -0
- aissemble_inference_core/client/translators/object_detection_translator.py +212 -0
- aissemble_inference_core/client/translators/summarization_translator.py +147 -0
- aissemble_inference_core/client/translators/tensorflow_object_detection_translator.py +231 -0
- aissemble_inference_core-1.5.0rc3.dist-info/METADATA +71 -0
- aissemble_inference_core-1.5.0rc3.dist-info/RECORD +26 -0
- aissemble_inference_core-1.5.0rc3.dist-info/WHEEL +4 -0
- aissemble_inference_core-1.5.0rc3.dist-info/entry_points.txt +5 -0
- aissemble_inference_core-1.5.0rc3.dist-info/licenses/LICENSE.txt +201 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
###
|
|
2
|
+
# #%L
|
|
3
|
+
# aiSSEMBLE::Open Inference Protocol::Core
|
|
4
|
+
# %%
|
|
5
|
+
# Copyright (C) 2024 Booz Allen Hamilton Inc.
|
|
6
|
+
# %%
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
# #L%
|
|
19
|
+
###
|
|
20
|
+
"""Module registry for dynamic OIP module discovery.
|
|
21
|
+
|
|
22
|
+
This module provides a registry that discovers and loads OIP modules
|
|
23
|
+
via Python entry points. Modules can register:
|
|
24
|
+
- Runtimes (MLServer-compatible model runtimes)
|
|
25
|
+
- Translators (OIP protocol translators)
|
|
26
|
+
- Builders (task-specific inference builders)
|
|
27
|
+
|
|
28
|
+
Entry point groups:
|
|
29
|
+
- inference.runtimes: Model runtime implementations
|
|
30
|
+
- inference.translators: Data format translators
|
|
31
|
+
- inference.builders: Inference builder implementations
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
import importlib.metadata
|
|
35
|
+
import logging
|
|
36
|
+
from typing import Any, Dict, List, Type
|
|
37
|
+
|
|
38
|
+
logger = logging.getLogger(__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ModuleRegistry:
|
|
42
|
+
"""Registry for dynamically discovered OIP modules.
|
|
43
|
+
|
|
44
|
+
This registry uses Python entry points to discover installed modules.
|
|
45
|
+
Modules register themselves by declaring entry points in their
|
|
46
|
+
pyproject.toml files.
|
|
47
|
+
|
|
48
|
+
Example pyproject.toml entry points:
|
|
49
|
+
[project.entry-points."inference.runtimes"]
|
|
50
|
+
yolo = "aissemble_inference_yolo:YOLORuntime"
|
|
51
|
+
|
|
52
|
+
[project.entry-points."inference.translators"]
|
|
53
|
+
yolo = "aissemble_inference_yolo:YOLOTranslator"
|
|
54
|
+
|
|
55
|
+
Usage:
|
|
56
|
+
registry = ModuleRegistry.instance()
|
|
57
|
+
registry.discover()
|
|
58
|
+
|
|
59
|
+
# Get a specific runtime
|
|
60
|
+
runtime_class = registry.get_runtime("yolo")
|
|
61
|
+
|
|
62
|
+
# List all available modules
|
|
63
|
+
available = registry.list_available()
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
_instance: "ModuleRegistry | None" = None
|
|
67
|
+
|
|
68
|
+
def __init__(self):
|
|
69
|
+
"""Initialize an empty registry."""
|
|
70
|
+
self._runtimes: Dict[str, Type[Any]] = {}
|
|
71
|
+
self._translators: Dict[str, Type[Any]] = {}
|
|
72
|
+
self._builders: Dict[str, Type[Any]] = {}
|
|
73
|
+
self._loaded = False
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def instance(cls) -> "ModuleRegistry":
|
|
77
|
+
"""Get the singleton registry instance.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
The global ModuleRegistry instance
|
|
81
|
+
"""
|
|
82
|
+
if cls._instance is None:
|
|
83
|
+
cls._instance = cls()
|
|
84
|
+
return cls._instance
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def reset(cls) -> None:
|
|
88
|
+
"""Reset the singleton instance (primarily for testing)."""
|
|
89
|
+
cls._instance = None
|
|
90
|
+
|
|
91
|
+
def discover(self) -> None:
|
|
92
|
+
"""Load all installed OIP modules via entry points.
|
|
93
|
+
|
|
94
|
+
This method scans for entry points in the following groups:
|
|
95
|
+
- inference.runtimes: Model runtime implementations
|
|
96
|
+
- inference.translators: Data format translators
|
|
97
|
+
- inference.builders: Inference builder implementations
|
|
98
|
+
|
|
99
|
+
Entry points are loaded lazily - the actual class is only
|
|
100
|
+
imported when accessed via get_* methods.
|
|
101
|
+
"""
|
|
102
|
+
if self._loaded:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
entry_point_groups = [
|
|
106
|
+
("inference.runtimes", self._runtimes),
|
|
107
|
+
("inference.translators", self._translators),
|
|
108
|
+
("inference.builders", self._builders),
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
for group, registry in entry_point_groups:
|
|
112
|
+
try:
|
|
113
|
+
eps = importlib.metadata.entry_points(group=group)
|
|
114
|
+
for ep in eps:
|
|
115
|
+
try:
|
|
116
|
+
registry[ep.name] = ep.load()
|
|
117
|
+
logger.debug(f"Loaded {group} entry point: {ep.name}")
|
|
118
|
+
except Exception as e:
|
|
119
|
+
logger.warning(
|
|
120
|
+
f"Failed to load {group} entry point '{ep.name}': {e}"
|
|
121
|
+
)
|
|
122
|
+
except Exception as e:
|
|
123
|
+
logger.warning(f"Failed to scan entry points for group '{group}': {e}")
|
|
124
|
+
|
|
125
|
+
self._loaded = True
|
|
126
|
+
|
|
127
|
+
def get_runtime(self, name: str) -> Type[Any] | None:
|
|
128
|
+
"""Get a runtime class by name.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
name: The registered name of the runtime
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
The runtime class, or None if not found
|
|
135
|
+
"""
|
|
136
|
+
self.discover()
|
|
137
|
+
return self._runtimes.get(name)
|
|
138
|
+
|
|
139
|
+
def get_translator(self, name: str) -> Type[Any] | None:
|
|
140
|
+
"""Get a translator class by name.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
name: The registered name of the translator
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
The translator class, or None if not found
|
|
147
|
+
"""
|
|
148
|
+
self.discover()
|
|
149
|
+
return self._translators.get(name)
|
|
150
|
+
|
|
151
|
+
def get_builder(self, name: str) -> Type[Any] | None:
|
|
152
|
+
"""Get a builder class by name.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
name: The registered name of the builder
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
The builder class, or None if not found
|
|
159
|
+
"""
|
|
160
|
+
self.discover()
|
|
161
|
+
return self._builders.get(name)
|
|
162
|
+
|
|
163
|
+
def list_available(self) -> Dict[str, List[str]]:
|
|
164
|
+
"""List all discovered modules.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Dictionary mapping category to list of available module names
|
|
168
|
+
"""
|
|
169
|
+
self.discover()
|
|
170
|
+
return {
|
|
171
|
+
"runtimes": list(self._runtimes.keys()),
|
|
172
|
+
"translators": list(self._translators.keys()),
|
|
173
|
+
"builders": list(self._builders.keys()),
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
def register_runtime(self, name: str, runtime_class: Type[Any]) -> None:
|
|
177
|
+
"""Manually register a runtime class.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
name: Name to register the runtime under
|
|
181
|
+
runtime_class: The runtime class to register
|
|
182
|
+
"""
|
|
183
|
+
self._runtimes[name] = runtime_class
|
|
184
|
+
|
|
185
|
+
def register_translator(self, name: str, translator_class: Type[Any]) -> None:
|
|
186
|
+
"""Manually register a translator class.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
name: Name to register the translator under
|
|
190
|
+
translator_class: The translator class to register
|
|
191
|
+
"""
|
|
192
|
+
self._translators[name] = translator_class
|
|
193
|
+
|
|
194
|
+
def register_builder(self, name: str, builder_class: Type[Any]) -> None:
|
|
195
|
+
"""Manually register a builder class.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
name: Name to register the builder under
|
|
199
|
+
builder_class: The builder class to register
|
|
200
|
+
"""
|
|
201
|
+
self._builders[name] = builder_class
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
###
|
|
2
|
+
# #%L
|
|
3
|
+
# aiSSEMBLE::Open Inference Protocol::Core
|
|
4
|
+
# %%
|
|
5
|
+
# Copyright (C) 2024 Booz Allen Hamilton Inc.
|
|
6
|
+
# %%
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
# #L%
|
|
19
|
+
###
|
|
20
|
+
from aissemble_inference_core.client.results.object_detection_result import (
|
|
21
|
+
BoundingBox,
|
|
22
|
+
Detection,
|
|
23
|
+
ObjectDetectionResult,
|
|
24
|
+
)
|
|
25
|
+
from aissemble_inference_core.client.results.summarization_result import (
|
|
26
|
+
SummarizationResult,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
__all__ = ["BoundingBox", "Detection", "ObjectDetectionResult", "SummarizationResult"]
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
###
|
|
2
|
+
# #%L
|
|
3
|
+
# aiSSEMBLE::Open Inference Protocol::Core
|
|
4
|
+
# %%
|
|
5
|
+
# Copyright (C) 2024 Booz Allen Hamilton Inc.
|
|
6
|
+
# %%
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
# #L%
|
|
19
|
+
###
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class BoundingBox:
|
|
26
|
+
"""Represents a bounding box for object detection.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
x1: Left x-coordinate
|
|
30
|
+
y1: Top y-coordinate
|
|
31
|
+
x2: Right x-coordinate
|
|
32
|
+
y2: Bottom y-coordinate
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
x1: float
|
|
36
|
+
y1: float
|
|
37
|
+
x2: float
|
|
38
|
+
y2: float
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def width(self) -> float:
|
|
42
|
+
"""Calculate the width of the bounding box."""
|
|
43
|
+
return self.x2 - self.x1
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def height(self) -> float:
|
|
47
|
+
"""Calculate the height of the bounding box."""
|
|
48
|
+
return self.y2 - self.y1
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def area(self) -> float:
|
|
52
|
+
"""Calculate the area of the bounding box."""
|
|
53
|
+
return self.width * self.height
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def center(self) -> tuple[float, float]:
|
|
57
|
+
"""Calculate the center point of the bounding box."""
|
|
58
|
+
return ((self.x1 + self.x2) / 2, (self.y1 + self.y2) / 2)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class Detection:
|
|
63
|
+
"""Represents a single detected object.
|
|
64
|
+
|
|
65
|
+
Attributes:
|
|
66
|
+
bbox: Bounding box coordinates
|
|
67
|
+
label: Class label of the detected object
|
|
68
|
+
confidence: Confidence score (0-1)
|
|
69
|
+
label_id: Optional numeric ID for the label
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
bbox: BoundingBox
|
|
73
|
+
label: str
|
|
74
|
+
confidence: float
|
|
75
|
+
label_id: int | None = None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass
|
|
79
|
+
class ObjectDetectionResult:
|
|
80
|
+
"""Value object representing the result of an object detection inference.
|
|
81
|
+
|
|
82
|
+
Attributes:
|
|
83
|
+
detections: List of detected objects
|
|
84
|
+
image_width: Width of the input image
|
|
85
|
+
image_height: Height of the input image
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
detections: list[Detection]
|
|
89
|
+
image_width: int
|
|
90
|
+
image_height: int
|
|
91
|
+
|
|
92
|
+
def filter_by_confidence(self, threshold: float) -> "ObjectDetectionResult":
|
|
93
|
+
"""Filter detections by confidence threshold.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
threshold: Minimum confidence score (0-1)
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
New ObjectDetectionResult with filtered detections
|
|
100
|
+
"""
|
|
101
|
+
filtered = [d for d in self.detections if d.confidence >= threshold]
|
|
102
|
+
return ObjectDetectionResult(
|
|
103
|
+
detections=filtered,
|
|
104
|
+
image_width=self.image_width,
|
|
105
|
+
image_height=self.image_height,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def filter_by_label(self, labels: list[str]) -> "ObjectDetectionResult":
|
|
109
|
+
"""Filter detections by label.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
labels: List of labels to keep
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
New ObjectDetectionResult with filtered detections
|
|
116
|
+
"""
|
|
117
|
+
filtered = [d for d in self.detections if d.label in labels]
|
|
118
|
+
return ObjectDetectionResult(
|
|
119
|
+
detections=filtered,
|
|
120
|
+
image_width=self.image_width,
|
|
121
|
+
image_height=self.image_height,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def draw_on_image(self, image: Any) -> Any:
|
|
125
|
+
"""Draw bounding boxes on the image.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
image: PIL Image or numpy array
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Image with drawn bounding boxes
|
|
132
|
+
|
|
133
|
+
Raises:
|
|
134
|
+
ImportError: If PIL is not installed
|
|
135
|
+
"""
|
|
136
|
+
try:
|
|
137
|
+
from PIL import Image, ImageDraw
|
|
138
|
+
except ImportError as e:
|
|
139
|
+
raise ImportError(
|
|
140
|
+
"PIL (Pillow) is required for drawing. Install with: pip install Pillow"
|
|
141
|
+
) from e
|
|
142
|
+
|
|
143
|
+
if not isinstance(image, Image.Image):
|
|
144
|
+
image = Image.fromarray(image)
|
|
145
|
+
|
|
146
|
+
draw = ImageDraw.Draw(image)
|
|
147
|
+
for detection in self.detections:
|
|
148
|
+
bbox = detection.bbox
|
|
149
|
+
draw.rectangle(
|
|
150
|
+
[(bbox.x1, bbox.y1), (bbox.x2, bbox.y2)], outline="red", width=2
|
|
151
|
+
)
|
|
152
|
+
text = f"{detection.label}: {detection.confidence:.2f}"
|
|
153
|
+
draw.text((bbox.x1, bbox.y1 - 10), text, fill="red")
|
|
154
|
+
|
|
155
|
+
return image
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
###
|
|
2
|
+
# #%L
|
|
3
|
+
# aiSSEMBLE::Open Inference Protocol::Core
|
|
4
|
+
# %%
|
|
5
|
+
# Copyright (C) 2024 Booz Allen Hamilton Inc.
|
|
6
|
+
# %%
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
# #L%
|
|
19
|
+
###
|
|
20
|
+
"""Value objects for text summarization results."""
|
|
21
|
+
|
|
22
|
+
from dataclasses import dataclass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class SummarizationResult:
|
|
27
|
+
"""Result of a text summarization inference.
|
|
28
|
+
|
|
29
|
+
This class encapsulates the output from a summarization model, including
|
|
30
|
+
the generated summary text and optional metadata about the operation.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
summary: The generated summary text
|
|
34
|
+
original_length: Character count of the original input text
|
|
35
|
+
summary_length: Character count of the generated summary
|
|
36
|
+
model_name: Optional name of the model that generated the summary
|
|
37
|
+
input_tokens: Optional count of input tokens (for token-based models)
|
|
38
|
+
output_tokens: Optional count of output tokens (for token-based models)
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
summary: str
|
|
42
|
+
original_length: int
|
|
43
|
+
summary_length: int
|
|
44
|
+
model_name: str | None = None
|
|
45
|
+
input_tokens: int | None = None
|
|
46
|
+
output_tokens: int | None = None
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def compression_ratio(self) -> float:
|
|
50
|
+
"""Calculate the compression ratio (original length / summary length).
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Ratio of original to summary length. Higher values indicate more compression.
|
|
54
|
+
Returns 0.0 if summary is empty.
|
|
55
|
+
|
|
56
|
+
Example:
|
|
57
|
+
>>> result = SummarizationResult(
|
|
58
|
+
... summary="Short summary",
|
|
59
|
+
... original_length=1000,
|
|
60
|
+
... summary_length=100
|
|
61
|
+
... )
|
|
62
|
+
>>> result.compression_ratio
|
|
63
|
+
10.0
|
|
64
|
+
"""
|
|
65
|
+
if self.summary_length == 0:
|
|
66
|
+
return 0.0
|
|
67
|
+
return self.original_length / self.summary_length
|
|
68
|
+
|
|
69
|
+
def __repr__(self) -> str:
|
|
70
|
+
"""Return a detailed string representation."""
|
|
71
|
+
return (
|
|
72
|
+
f"SummarizationResult("
|
|
73
|
+
f"summary={self.summary[:50]!r}..., "
|
|
74
|
+
f"original_length={self.original_length}, "
|
|
75
|
+
f"summary_length={self.summary_length}, "
|
|
76
|
+
f"compression_ratio={self.compression_ratio:.2f}x"
|
|
77
|
+
f")"
|
|
78
|
+
)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
###
|
|
2
|
+
# #%L
|
|
3
|
+
# aiSSEMBLE::Open Inference Protocol::Core
|
|
4
|
+
# %%
|
|
5
|
+
# Copyright (C) 2024 Booz Allen Hamilton Inc.
|
|
6
|
+
# %%
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
# #L%
|
|
19
|
+
###
|
|
20
|
+
from abc import ABC, abstractmethod
|
|
21
|
+
from typing import Generic, TypeVar
|
|
22
|
+
|
|
23
|
+
from aissemble_inference_core.client.oip_adapter import OipRequest, OipResponse
|
|
24
|
+
|
|
25
|
+
I = TypeVar("I")
|
|
26
|
+
O = TypeVar("O")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Translator(ABC, Generic[I, O]):
|
|
30
|
+
"""
|
|
31
|
+
Directly inspired by DJL, this is the ONLY class that knows about the OIP json schema,
|
|
32
|
+
tensor shapes, inputs, parameters, framing, etc. It is intended to be pluggable and
|
|
33
|
+
testable in isolation. It also provides tolerable reader behavior, where unknown
|
|
34
|
+
fields can be ignored.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def preprocess(self, input: I) -> OipRequest:
|
|
39
|
+
"""
|
|
40
|
+
Preprocesses the input to create an OipRequest.
|
|
41
|
+
|
|
42
|
+
:param input: The input data of type I.
|
|
43
|
+
:return: An OipRequest object.
|
|
44
|
+
"""
|
|
45
|
+
# TODO: Implement OipRequest creation
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def postprocess(self, response: OipResponse) -> O:
|
|
50
|
+
"""
|
|
51
|
+
Postprocesses the OipResponse to produce the output.
|
|
52
|
+
|
|
53
|
+
:param response: The OipResponse object.
|
|
54
|
+
:return: The output data of type O.
|
|
55
|
+
"""
|
|
56
|
+
# TODO: Implement OipResponse creation
|
|
57
|
+
pass
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
###
|
|
2
|
+
# #%L
|
|
3
|
+
# aiSSEMBLE::Open Inference Protocol::Core
|
|
4
|
+
# %%
|
|
5
|
+
# Copyright (C) 2024 Booz Allen Hamilton Inc.
|
|
6
|
+
# %%
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
# #L%
|
|
19
|
+
###
|
|
20
|
+
from aissemble_inference_core.client.translators.object_detection_translator import (
|
|
21
|
+
DefaultObjectDetectionTranslator,
|
|
22
|
+
)
|
|
23
|
+
from aissemble_inference_core.client.translators.summarization_translator import (
|
|
24
|
+
DefaultSummarizationTranslator,
|
|
25
|
+
)
|
|
26
|
+
from aissemble_inference_core.client.translators.tensorflow_object_detection_translator import (
|
|
27
|
+
TensorFlowObjectDetectionTranslator,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"DefaultObjectDetectionTranslator",
|
|
32
|
+
"DefaultSummarizationTranslator",
|
|
33
|
+
"TensorFlowObjectDetectionTranslator",
|
|
34
|
+
]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
###
|
|
2
|
+
# #%L
|
|
3
|
+
# aiSSEMBLE::Open Inference Protocol::Core
|
|
4
|
+
# %%
|
|
5
|
+
# Copyright (C) 2024 Booz Allen Hamilton Inc.
|
|
6
|
+
# %%
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
# #L%
|
|
19
|
+
###
|
|
20
|
+
"""Shared utilities for image preprocessing in translators."""
|
|
21
|
+
|
|
22
|
+
import base64
|
|
23
|
+
from io import BytesIO
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def encode_image_for_oip(input_data: Any) -> tuple[str, int, int]:
|
|
28
|
+
"""Encode image to base64 string for OIP transport.
|
|
29
|
+
|
|
30
|
+
Accepts various input formats:
|
|
31
|
+
- PIL Image
|
|
32
|
+
- numpy array
|
|
33
|
+
- file path (string)
|
|
34
|
+
- bytes
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
input_data: Image in various formats
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Tuple of (base64_string, width, height)
|
|
41
|
+
|
|
42
|
+
Raises:
|
|
43
|
+
ImportError: If PIL is not installed
|
|
44
|
+
ValueError: If input type is not supported
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
from PIL import Image
|
|
48
|
+
except ImportError as e:
|
|
49
|
+
raise ImportError(
|
|
50
|
+
"PIL (Pillow) is required for image handling. "
|
|
51
|
+
"Install with: pip install Pillow"
|
|
52
|
+
) from e
|
|
53
|
+
|
|
54
|
+
if isinstance(input_data, str):
|
|
55
|
+
image = Image.open(input_data)
|
|
56
|
+
elif isinstance(input_data, bytes):
|
|
57
|
+
image = Image.open(BytesIO(input_data))
|
|
58
|
+
elif hasattr(input_data, "mode"):
|
|
59
|
+
image = input_data
|
|
60
|
+
else:
|
|
61
|
+
import numpy as np
|
|
62
|
+
|
|
63
|
+
if isinstance(input_data, np.ndarray):
|
|
64
|
+
image = Image.fromarray(input_data)
|
|
65
|
+
else:
|
|
66
|
+
raise ValueError(f"Unsupported input type: {type(input_data)}")
|
|
67
|
+
|
|
68
|
+
width, height = image.size
|
|
69
|
+
|
|
70
|
+
buffer = BytesIO()
|
|
71
|
+
image.save(buffer, format="PNG")
|
|
72
|
+
image_bytes = buffer.getvalue()
|
|
73
|
+
encoded = base64.b64encode(image_bytes).decode("utf-8")
|
|
74
|
+
|
|
75
|
+
return encoded, width, height
|