code-loader 1.0.139.dev2__tar.gz → 1.0.139.dev4__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.
Potentially problematic release.
This version of code-loader might be problematic. Click here for more details.
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/PKG-INFO +4 -3
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/datasetclasses.py +1 -9
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/inner_leap_binder/leapbinder_decorators.py +116 -448
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/mixpanel_tracker.py +41 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/pyproject.toml +1 -1
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/LICENSE +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/README.md +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/__init__.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/__init__.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/enums.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/exceptions.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/mapping.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/responsedataclasses.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/visualizer_classes.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/default_losses.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/default_metrics.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/__init__.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/api.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/cli_config_utils.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/client.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/epoch.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/experiment.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/experiment_context.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/types.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/utils.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/inner_leap_binder/__init__.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/inner_leap_binder/leapbinder.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/leaploader.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/leaploaderbase.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/plot_functions/__init__.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/plot_functions/plot_functions.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/plot_functions/visualize.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/utils.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/visualizers/__init__.py +0 -0
- {code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/visualizers/default_visualizers.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: code-loader
|
|
3
|
-
Version: 1.0.139.
|
|
3
|
+
Version: 1.0.139.dev4
|
|
4
4
|
Summary:
|
|
5
|
-
Home-page: https://github.com/tensorleap/code-loader
|
|
6
5
|
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
7
|
Author: dorhar
|
|
8
8
|
Author-email: doron.harnoy@tensorleap.ai
|
|
9
9
|
Requires-Python: >=3.8,<3.13
|
|
@@ -20,6 +20,7 @@ Requires-Dist: numpy (>=2.3.2,<3.0.0) ; python_version >= "3.11" and python_vers
|
|
|
20
20
|
Requires-Dist: psutil (>=5.9.5,<6.0.0)
|
|
21
21
|
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
|
|
22
22
|
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
|
23
|
+
Project-URL: Homepage, https://github.com/tensorleap/code-loader
|
|
23
24
|
Project-URL: Repository, https://github.com/tensorleap/code-loader
|
|
24
25
|
Description-Content-Type: text/markdown
|
|
25
26
|
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/datasetclasses.py
RENAMED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import warnings
|
|
2
1
|
from dataclasses import dataclass, field
|
|
3
2
|
from typing import Any, Callable, List, Optional, Dict, Union, Type
|
|
4
3
|
import re
|
|
@@ -57,14 +56,7 @@ class PreprocessResponse:
|
|
|
57
56
|
for sample_id in self.sample_ids:
|
|
58
57
|
assert isinstance(sample_id, str), f"Sample id should be of type str. Got: {type(sample_id)}"
|
|
59
58
|
else:
|
|
60
|
-
raise Exception("length is deprecated
|
|
61
|
-
|
|
62
|
-
if self.state is None:
|
|
63
|
-
warnings.warn(
|
|
64
|
-
"PreprocessResponse.state is not set. For best practice, assign a unique `state` value to each PreprocessResponse instance."
|
|
65
|
-
)
|
|
66
|
-
else:
|
|
67
|
-
assert isinstance(self.state, DataStateType), f"PreprocessResponse.state must be of type {DataStateType.__name__} but got {type(self.state)}"
|
|
59
|
+
raise Exception("length is deprecated.")
|
|
68
60
|
|
|
69
61
|
def __hash__(self) -> int:
|
|
70
62
|
return id(self)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# mypy: ignore-errors
|
|
2
2
|
import os
|
|
3
|
-
import warnings
|
|
4
3
|
from collections import defaultdict
|
|
5
4
|
from functools import lru_cache
|
|
6
5
|
from pathlib import Path
|
|
7
|
-
from typing import Optional, Union, Callable, List, Dict,
|
|
6
|
+
from typing import Optional, Union, Callable, List, Dict, Set, Any
|
|
8
7
|
|
|
9
8
|
import numpy as np
|
|
10
9
|
import numpy.typing as npt
|
|
@@ -26,116 +25,9 @@ import functools
|
|
|
26
25
|
|
|
27
26
|
_called_from_inside_tl_decorator = 0
|
|
28
27
|
_called_from_inside_tl_integration_test_decorator = False
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def validate_args_structure(*args, types_order, func_name, expected_names, **kwargs):
|
|
35
|
-
def _type_to_str(t):
|
|
36
|
-
origin = get_origin(t)
|
|
37
|
-
if origin is Union:
|
|
38
|
-
return " | ".join(tt.__name__ for tt in get_args(t))
|
|
39
|
-
elif hasattr(t, "__name__"):
|
|
40
|
-
return t.__name__
|
|
41
|
-
else:
|
|
42
|
-
return str(t)
|
|
43
|
-
|
|
44
|
-
def _format_types(types, names=None):
|
|
45
|
-
return ", ".join(
|
|
46
|
-
f"{(names[i] + ': ') if names else f'arg{i}: '}{_type_to_str(ty)}"
|
|
47
|
-
for i, ty in enumerate(types)
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
if expected_names:
|
|
51
|
-
normalized_args = []
|
|
52
|
-
for i, name in enumerate(expected_names):
|
|
53
|
-
if i < len(args):
|
|
54
|
-
normalized_args.append(args[i])
|
|
55
|
-
elif name in kwargs:
|
|
56
|
-
normalized_args.append(kwargs[name])
|
|
57
|
-
else:
|
|
58
|
-
raise AssertionError(
|
|
59
|
-
f"{func_name} validation failed: "
|
|
60
|
-
f"Missing required argument '{name}'. "
|
|
61
|
-
f"Expected arguments: {expected_names}."
|
|
62
|
-
)
|
|
63
|
-
else:
|
|
64
|
-
normalized_args = list(args)
|
|
65
|
-
if len(normalized_args) != len(types_order):
|
|
66
|
-
expected = _format_types(types_order, expected_names)
|
|
67
|
-
got_types = ", ".join(type(arg).__name__ for arg in normalized_args)
|
|
68
|
-
raise AssertionError(
|
|
69
|
-
f"{func_name} validation failed: "
|
|
70
|
-
f"Expected exactly {len(types_order)} arguments ({expected}), "
|
|
71
|
-
f"but got {len(normalized_args)} argument(s) of type(s): ({got_types}). "
|
|
72
|
-
f"Correct usage example: {func_name}({expected})"
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
for i, (arg, expected_type) in enumerate(zip(normalized_args, types_order)):
|
|
76
|
-
origin = get_origin(expected_type)
|
|
77
|
-
if origin is Union:
|
|
78
|
-
allowed_types = get_args(expected_type)
|
|
79
|
-
else:
|
|
80
|
-
allowed_types = (expected_type,)
|
|
81
|
-
|
|
82
|
-
if not isinstance(arg, allowed_types):
|
|
83
|
-
allowed_str = " | ".join(t.__name__ for t in allowed_types)
|
|
84
|
-
raise AssertionError(
|
|
85
|
-
f"{func_name} validation failed: "
|
|
86
|
-
f"Argument '{expected_names[i] if expected_names else f'arg{i}'}' "
|
|
87
|
-
f"expected type {allowed_str}, but got {type(arg).__name__}. "
|
|
88
|
-
f"Correct usage example: {func_name}({_format_types(types_order, expected_names)})"
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def validate_output_structure(result, func_name: str, expected_type_name="np.ndarray",gt_flag=False):
|
|
93
|
-
if result is None or (isinstance(result, float) and np.isnan(result)):
|
|
94
|
-
if gt_flag:
|
|
95
|
-
raise AssertionError(
|
|
96
|
-
f"{func_name} validation failed: "
|
|
97
|
-
f"The function returned {result!r}. "
|
|
98
|
-
f"If you are working with an unlabeled dataset and no ground truth is available, "
|
|
99
|
-
f"use 'return np.array([], dtype=np.float32)' instead. "
|
|
100
|
-
f"Otherwise, {func_name} expected a single {expected_type_name} object. "
|
|
101
|
-
f"Make sure the function ends with 'return <{expected_type_name}>'."
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
raise AssertionError(
|
|
105
|
-
f"{func_name} validation failed: "
|
|
106
|
-
f"The function returned None. "
|
|
107
|
-
f"Expected a single {expected_type_name} object. "
|
|
108
|
-
f"Make sure the function ends with 'return <{expected_type_name}>'."
|
|
109
|
-
)
|
|
110
|
-
if isinstance(result, tuple):
|
|
111
|
-
element_descriptions = [
|
|
112
|
-
f"[{i}] type: {type(r).__name__}"
|
|
113
|
-
for i, r in enumerate(result)
|
|
114
|
-
]
|
|
115
|
-
element_summary = "\n ".join(element_descriptions)
|
|
116
|
-
|
|
117
|
-
raise AssertionError(
|
|
118
|
-
f"{func_name} validation failed: "
|
|
119
|
-
f"The function returned multiple outputs ({len(result)} values), "
|
|
120
|
-
f"but only a single {expected_type_name} is allowed.\n\n"
|
|
121
|
-
f"Returned elements:\n"
|
|
122
|
-
f" {element_summary}\n\n"
|
|
123
|
-
f"Correct usage example:\n"
|
|
124
|
-
f" def {func_name}(...):\n"
|
|
125
|
-
f" return <{expected_type_name}>\n\n"
|
|
126
|
-
f"If you intended to return multiple values, combine them into a single "
|
|
127
|
-
f"{expected_type_name} (e.g., by concatenation or stacking)."
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
def batch_warning(result, func_name):
|
|
131
|
-
if result.shape[0] == 1:
|
|
132
|
-
warnings.warn(
|
|
133
|
-
f"{func_name} warning: Tensorleap will add a batch dimension at axis 0 to the output of {func_name}, "
|
|
134
|
-
f"although the detected size of axis 0 is already 1. "
|
|
135
|
-
f"This may lead to an extra batch dimension (e.g., shape (1, 1, ...)). "
|
|
136
|
-
f"Please ensure that the output of '{func_name}' is not already batched "
|
|
137
|
-
f"to avoid computation errors."
|
|
138
|
-
)
|
|
28
|
+
_integration_events_emitted: Set[str] = set()
|
|
29
|
+
|
|
30
|
+
|
|
139
31
|
def _add_mapping_connection(user_unique_name, connection_destinations, arg_names, name, node_mapping_type):
|
|
140
32
|
connection_destinations = [connection_destination for connection_destination in connection_destinations
|
|
141
33
|
if not isinstance(connection_destination, SamplePreprocessResponse)]
|
|
@@ -158,23 +50,12 @@ def tensorleap_integration_test():
|
|
|
158
50
|
def decorating_function(integration_test_function: Callable):
|
|
159
51
|
leap_binder.integration_test_func = integration_test_function
|
|
160
52
|
|
|
161
|
-
def _validate_input_args(*args, **kwargs):
|
|
162
|
-
sample_id,preprocess_response=args
|
|
163
|
-
assert type(sample_id) == preprocess_response.sample_id_type, (
|
|
164
|
-
f"tensorleap_integration_test validation failed: "
|
|
165
|
-
f"sample_id type ({type(sample_id).__name__}) does not match the expected "
|
|
166
|
-
f"type ({preprocess_response.sample_id_type}) from the PreprocessResponse."
|
|
167
|
-
)
|
|
168
|
-
|
|
169
53
|
def inner(*args, **kwargs):
|
|
170
|
-
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
171
|
-
func_name='integration_test',expected_names=["idx", "preprocess"],**kwargs)
|
|
172
|
-
_validate_input_args(*args, **kwargs)
|
|
173
|
-
|
|
174
54
|
global _called_from_inside_tl_integration_test_decorator
|
|
55
|
+
global _integration_events_emitted
|
|
56
|
+
_integration_events_emitted.clear() # Clear events for new test
|
|
175
57
|
try:
|
|
176
58
|
_called_from_inside_tl_integration_test_decorator = True
|
|
177
|
-
_update_env_status("tensorleap_integration_test", "v")#put here because otherwise it will become v only if it finishes all the script
|
|
178
59
|
ret = integration_test_function(*args, **kwargs)
|
|
179
60
|
|
|
180
61
|
try:
|
|
@@ -187,7 +68,7 @@ def tensorleap_integration_test():
|
|
|
187
68
|
line_number = first_tb.lineno
|
|
188
69
|
if isinstance(e, TypeError) and 'is not subscriptable' in str(e):
|
|
189
70
|
print(f'Invalid integration code. File {file_name}, line {line_number}: '
|
|
190
|
-
f
|
|
71
|
+
f'Please remove this indexing operation usage from the integration test code.')
|
|
191
72
|
else:
|
|
192
73
|
print(f'Invalid integration code. File {file_name}, line {line_number}: '
|
|
193
74
|
f'Integration test is only allowed to call Tensorleap decorators. '
|
|
@@ -199,8 +80,8 @@ def tensorleap_integration_test():
|
|
|
199
80
|
_called_from_inside_tl_integration_test_decorator = False
|
|
200
81
|
|
|
201
82
|
leap_binder.check()
|
|
202
|
-
return inner
|
|
203
83
|
|
|
84
|
+
return inner
|
|
204
85
|
|
|
205
86
|
return decorating_function
|
|
206
87
|
|
|
@@ -210,52 +91,31 @@ def _safe_get_item(key):
|
|
|
210
91
|
except ValueError:
|
|
211
92
|
raise Exception(f'Tensorleap currently supports models with no more then 10 inputs')
|
|
212
93
|
|
|
94
|
+
def _emit_integration_event_once(event_name: str, props: Dict[str, Any]) -> None:
|
|
95
|
+
"""Emit an integration test event only once per test run."""
|
|
96
|
+
if event_name in _integration_events_emitted:
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
from code_loader.mixpanel_tracker import track_integration_test_event
|
|
101
|
+
track_integration_test_event(event_name, props)
|
|
102
|
+
_integration_events_emitted.add(event_name)
|
|
103
|
+
except Exception:
|
|
104
|
+
pass
|
|
105
|
+
|
|
213
106
|
def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]] = []):
|
|
214
|
-
assert isinstance(prediction_types, list),(
|
|
215
|
-
f"tensorleap_load_model validation failed: "
|
|
216
|
-
f" prediction_types is an optional argument of type List[PredictionTypeHandler]] but got {type(prediction_types).__name__}."
|
|
217
|
-
)
|
|
218
107
|
for i, prediction_type in enumerate(prediction_types):
|
|
219
|
-
assert isinstance(prediction_type, PredictionTypeHandler),(f"tensorleap_load_model validation failed: "
|
|
220
|
-
f" prediction_types at position {i} must be of type PredictionTypeHandler but got {type(prediction_types[i]).__name__}.")
|
|
221
108
|
leap_binder.add_prediction(prediction_type.name, prediction_type.labels, prediction_type.channel_dim, i)
|
|
222
109
|
|
|
223
|
-
def _validate_result(result) -> None:
|
|
224
|
-
valid_types=["onnxruntime","keras"]
|
|
225
|
-
err_message=f"tensorleap_load_model validation failed:\nSupported models are Keras and onnxruntime only and non of them was returned."
|
|
226
|
-
validate_output_structure(result, func_name="tensorleap_load_model", expected_type_name= [" | ".join(t for t in valid_types)][0])
|
|
227
|
-
try:
|
|
228
|
-
import keras
|
|
229
|
-
except ImportError:
|
|
230
|
-
keras = None
|
|
231
|
-
try:
|
|
232
|
-
import onnxruntime
|
|
233
|
-
except ImportError:
|
|
234
|
-
onnxruntime = None
|
|
235
|
-
|
|
236
|
-
if not keras and not onnxruntime:
|
|
237
|
-
raise AssertionError(err_message)
|
|
238
|
-
|
|
239
|
-
is_keras_model = bool(keras and isinstance(result, getattr(keras, "Model", tuple())))
|
|
240
|
-
is_onnx_model = bool(onnxruntime and isinstance(result, onnxruntime.InferenceSession))
|
|
241
|
-
|
|
242
|
-
if not any([is_keras_model, is_onnx_model]):
|
|
243
|
-
raise AssertionError( err_message)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
110
|
def decorating_function(load_model_func):
|
|
248
111
|
class TempMapping:
|
|
249
112
|
pass
|
|
250
113
|
|
|
251
114
|
@lru_cache()
|
|
252
|
-
def inner(
|
|
253
|
-
validate_args_structure(*args, types_order=[],
|
|
254
|
-
func_name='tensorleap_load_model',expected_names=[],**kwargs)
|
|
115
|
+
def inner():
|
|
255
116
|
class ModelPlaceholder:
|
|
256
117
|
def __init__(self):
|
|
257
|
-
self.model = load_model_func()
|
|
258
|
-
_validate_result(self.model)
|
|
118
|
+
self.model = load_model_func()
|
|
259
119
|
|
|
260
120
|
# keras interface
|
|
261
121
|
def __call__(self, arg):
|
|
@@ -319,9 +179,8 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
|
|
|
319
179
|
|
|
320
180
|
def get_inputs(self):
|
|
321
181
|
return self.model.get_inputs()
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return model_placeholder
|
|
182
|
+
|
|
183
|
+
return ModelPlaceholder()
|
|
325
184
|
|
|
326
185
|
def mapping_inner():
|
|
327
186
|
class ModelOutputPlaceholder:
|
|
@@ -384,11 +243,12 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
|
|
|
384
243
|
|
|
385
244
|
return ModelPlaceholder()
|
|
386
245
|
|
|
387
|
-
def final_inner(
|
|
246
|
+
def final_inner():
|
|
388
247
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
389
248
|
return mapping_inner()
|
|
390
249
|
else:
|
|
391
|
-
return inner(
|
|
250
|
+
return inner()
|
|
251
|
+
|
|
392
252
|
return final_inner
|
|
393
253
|
|
|
394
254
|
return decorating_function
|
|
@@ -399,168 +259,81 @@ def tensorleap_custom_metric(name: str,
|
|
|
399
259
|
compute_insights: Optional[Union[bool, Dict[str, bool]]] = None,
|
|
400
260
|
connects_to=None):
|
|
401
261
|
name_to_unique_name = defaultdict(set)
|
|
262
|
+
|
|
402
263
|
def decorating_function(
|
|
403
264
|
user_function: Union[CustomCallableInterfaceMultiArgs, CustomMultipleReturnCallableInterfaceMultiArgs,
|
|
404
265
|
ConfusionMatrixCallableInterfaceMultiArgs]):
|
|
405
|
-
|
|
406
|
-
def _validate_decorators_signature():
|
|
407
|
-
err_message = f"{user_function.__name__} validation failed.\n"
|
|
408
|
-
if not isinstance(name, str):
|
|
409
|
-
raise TypeError(err_message + f"`name` must be a string, got type {type(name).__name__}.")
|
|
410
|
-
valid_directions = {MetricDirection.Upward, MetricDirection.Downward}
|
|
411
|
-
if isinstance(direction, MetricDirection):
|
|
412
|
-
if direction not in valid_directions:
|
|
413
|
-
raise ValueError(
|
|
414
|
-
err_message +
|
|
415
|
-
f"Invalid MetricDirection: {direction}. Must be one of {valid_directions}, "
|
|
416
|
-
f"got type {type(direction).__name__}."
|
|
417
|
-
)
|
|
418
|
-
elif isinstance(direction, dict):
|
|
419
|
-
if not all(isinstance(k, str) for k in direction.keys()):
|
|
420
|
-
invalid_keys = {k: type(k).__name__ for k in direction.keys() if not isinstance(k, str)}
|
|
421
|
-
raise TypeError(
|
|
422
|
-
err_message +
|
|
423
|
-
f"All keys in `direction` must be strings, got invalid key types: {invalid_keys}."
|
|
424
|
-
)
|
|
425
|
-
for k, v in direction.items():
|
|
426
|
-
if v not in valid_directions:
|
|
427
|
-
raise ValueError(
|
|
428
|
-
err_message +
|
|
429
|
-
f"Invalid direction for key '{k}': {v}. Must be one of {valid_directions}, "
|
|
430
|
-
f"got type {type(v).__name__}."
|
|
431
|
-
)
|
|
432
|
-
else:
|
|
433
|
-
raise TypeError(
|
|
434
|
-
err_message +
|
|
435
|
-
f"`direction` must be a MetricDirection or a Dict[str, MetricDirection], "
|
|
436
|
-
f"got type {type(direction).__name__}."
|
|
437
|
-
)
|
|
438
|
-
if compute_insights is not None:
|
|
439
|
-
if not isinstance(compute_insights, (bool, dict)):
|
|
440
|
-
raise TypeError(
|
|
441
|
-
err_message +
|
|
442
|
-
f"`compute_insights` must be a bool or a Dict[str, bool], "
|
|
443
|
-
f"got type {type(compute_insights).__name__}."
|
|
444
|
-
)
|
|
445
|
-
if isinstance(compute_insights, dict):
|
|
446
|
-
if not all(isinstance(k, str) for k in compute_insights.keys()):
|
|
447
|
-
invalid_keys = {k: type(k).__name__ for k in compute_insights.keys() if not isinstance(k, str)}
|
|
448
|
-
raise TypeError(
|
|
449
|
-
err_message +
|
|
450
|
-
f"All keys in `compute_insights` must be strings, got invalid key types: {invalid_keys}."
|
|
451
|
-
)
|
|
452
|
-
for k, v in compute_insights.items():
|
|
453
|
-
if not isinstance(v, bool):
|
|
454
|
-
raise TypeError(
|
|
455
|
-
err_message +
|
|
456
|
-
f"Invalid type for compute_insights['{k}']: expected bool, got type {type(v).__name__}."
|
|
457
|
-
)
|
|
458
|
-
if connects_to is not None:
|
|
459
|
-
valid_types = (str, list, tuple, set)
|
|
460
|
-
if not isinstance(connects_to, valid_types):
|
|
461
|
-
raise TypeError(
|
|
462
|
-
err_message +
|
|
463
|
-
f"`connects_to` must be one of {valid_types}, got type {type(connects_to).__name__}."
|
|
464
|
-
)
|
|
465
|
-
if isinstance(connects_to, (list, tuple, set)):
|
|
466
|
-
invalid_elems = [f"{type(e).__name__}" for e in connects_to if not isinstance(e, str)]
|
|
467
|
-
if invalid_elems:
|
|
468
|
-
raise TypeError(
|
|
469
|
-
err_message +
|
|
470
|
-
f"All elements in `connects_to` must be strings, "
|
|
471
|
-
f"but found element types: {invalid_elems}."
|
|
472
|
-
)
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
_validate_decorators_signature()
|
|
476
|
-
|
|
477
266
|
for metric_handler in leap_binder.setup_container.metrics:
|
|
478
267
|
if metric_handler.metric_handler_data.name == name:
|
|
479
268
|
raise Exception(f'Metric with name {name} already exists. '
|
|
480
269
|
f'Please choose another')
|
|
481
270
|
|
|
482
271
|
def _validate_input_args(*args, **kwargs) -> None:
|
|
483
|
-
assert len(args) > 0, (
|
|
484
|
-
f"{user_function.__name__}() validation failed: "
|
|
485
|
-
f"Expected at least one positional|key-word argument of type np.ndarray, "
|
|
486
|
-
f"but received none. "
|
|
487
|
-
f"Correct usage example: tensorleap_custom_metric(input_array: np.ndarray, ...)"
|
|
488
|
-
)
|
|
489
272
|
for i, arg in enumerate(args):
|
|
490
273
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
491
|
-
f'
|
|
274
|
+
f'tensorleap_custom_metric validation failed: '
|
|
492
275
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
493
276
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
494
277
|
assert arg.shape[0] == leap_binder.batch_size_to_validate, \
|
|
495
|
-
(f'
|
|
278
|
+
(f'tensorleap_custom_metric validation failed: Argument #{i} '
|
|
496
279
|
f'first dim should be as the batch size. Got {arg.shape[0]} '
|
|
497
280
|
f'instead of {leap_binder.batch_size_to_validate}')
|
|
498
281
|
|
|
499
282
|
for _arg_name, arg in kwargs.items():
|
|
500
283
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
501
|
-
f'
|
|
284
|
+
f'tensorleap_custom_metric validation failed: '
|
|
502
285
|
f'Argument {_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
503
286
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
504
287
|
assert arg.shape[0] == leap_binder.batch_size_to_validate, \
|
|
505
|
-
(f'
|
|
288
|
+
(f'tensorleap_custom_metric validation failed: Argument {_arg_name} '
|
|
506
289
|
f'first dim should be as the batch size. Got {arg.shape[0]} '
|
|
507
290
|
f'instead of {leap_binder.batch_size_to_validate}')
|
|
508
291
|
|
|
509
292
|
def _validate_result(result) -> None:
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
f'{user_function.__name__}() has returned unsupported type.\nSupported types are List[float|int|None], '
|
|
514
|
-
f'List[List[ConfusionMatrixElement]], NDArray[np.float32] or dictonary with one of these types as its values types. ')
|
|
293
|
+
supported_types_message = (f'tensorleap_custom_metric validation failed: '
|
|
294
|
+
f'Metric has returned unsupported type. Supported types are List[float], '
|
|
295
|
+
f'List[List[ConfusionMatrixElement]], NDArray[np.float32]. ')
|
|
515
296
|
|
|
516
|
-
def _validate_single_metric(single_metric_result
|
|
297
|
+
def _validate_single_metric(single_metric_result):
|
|
517
298
|
if isinstance(single_metric_result, list):
|
|
518
299
|
if isinstance(single_metric_result[0], list):
|
|
519
|
-
assert
|
|
520
|
-
f
|
|
521
|
-
f"Got {'a dict where the value of ' + str(key) + ' is of type ' if key is not None else ''}"
|
|
522
|
-
f"List[List[{', '.join(type(cm).__name__ for cm in single_metric_result[0])}]]."
|
|
523
|
-
)
|
|
524
|
-
|
|
300
|
+
assert isinstance(single_metric_result[0][0], ConfusionMatrixElement), \
|
|
301
|
+
f'{supported_types_message}Got List[List[{type(single_metric_result[0][0])}]].'
|
|
525
302
|
else:
|
|
526
|
-
assert
|
|
527
|
-
|
|
528
|
-
f
|
|
529
|
-
f"List[{', '.join(type(v).__name__ for v in single_metric_result)}]."
|
|
530
|
-
)
|
|
303
|
+
assert isinstance(single_metric_result[0], (
|
|
304
|
+
float, int,
|
|
305
|
+
type(None))), f'{supported_types_message}Got List[{type(single_metric_result[0])}].'
|
|
531
306
|
else:
|
|
532
307
|
assert isinstance(single_metric_result,
|
|
533
|
-
np.ndarray), f'{supported_types_message}
|
|
534
|
-
assert len(single_metric_result.shape) == 1, (f'
|
|
308
|
+
np.ndarray), f'{supported_types_message}Got {type(single_metric_result)}.'
|
|
309
|
+
assert len(single_metric_result.shape) == 1, (f'tensorleap_custom_metric validation failed: '
|
|
535
310
|
f'The return shape should be 1D. Got {len(single_metric_result.shape)}D.')
|
|
536
311
|
|
|
537
312
|
if leap_binder.batch_size_to_validate:
|
|
538
313
|
assert len(single_metric_result) == leap_binder.batch_size_to_validate, \
|
|
539
|
-
f'
|
|
314
|
+
f'tensorleap_custom_metrix validation failed: The return len should be as the batch size.'
|
|
540
315
|
|
|
541
316
|
if isinstance(result, dict):
|
|
542
317
|
for key, value in result.items():
|
|
543
|
-
_validate_single_metric(value,key)
|
|
544
|
-
|
|
545
318
|
assert isinstance(key, str), \
|
|
546
|
-
(f'
|
|
319
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
547
320
|
f'Keys in the return dict should be of type str. Got {type(key)}.')
|
|
548
321
|
_validate_single_metric(value)
|
|
549
322
|
|
|
550
323
|
if isinstance(direction, dict):
|
|
551
324
|
for direction_key in direction:
|
|
552
325
|
assert direction_key in result, \
|
|
553
|
-
(f'
|
|
326
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
554
327
|
f'Keys in the direction mapping should be part of result keys. Got key {direction_key}.')
|
|
555
328
|
|
|
556
329
|
if compute_insights is not None:
|
|
557
330
|
assert isinstance(compute_insights, dict), \
|
|
558
|
-
(f'
|
|
331
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
559
332
|
f'compute_insights should be dict if using the dict results. Got {type(compute_insights)}.')
|
|
560
333
|
|
|
561
334
|
for ci_key in compute_insights:
|
|
562
335
|
assert ci_key in result, \
|
|
563
|
-
(f'
|
|
336
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
564
337
|
f'Keys in the compute_insights mapping should be part of result keys. Got key {ci_key}.')
|
|
565
338
|
|
|
566
339
|
else:
|
|
@@ -568,7 +341,7 @@ def tensorleap_custom_metric(name: str,
|
|
|
568
341
|
|
|
569
342
|
if compute_insights is not None:
|
|
570
343
|
assert isinstance(compute_insights, bool), \
|
|
571
|
-
(f'
|
|
344
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
572
345
|
f'compute_insights should be boolean. Got {type(compute_insights)}.')
|
|
573
346
|
|
|
574
347
|
@functools.wraps(user_function)
|
|
@@ -600,7 +373,6 @@ def tensorleap_custom_metric(name: str,
|
|
|
600
373
|
result = inner_without_validate(*args, **kwargs)
|
|
601
374
|
|
|
602
375
|
_validate_result(result)
|
|
603
|
-
_update_env_status("tensorleap_custom_metric","v")
|
|
604
376
|
return result
|
|
605
377
|
|
|
606
378
|
def mapping_inner(*args, **kwargs):
|
|
@@ -640,38 +412,28 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
640
412
|
name_to_unique_name = defaultdict(set)
|
|
641
413
|
|
|
642
414
|
def decorating_function(user_function: VisualizerCallableInterface):
|
|
643
|
-
assert isinstance(visualizer_type,LeapDataType),(f"{user_function.__name__} validation failed: "
|
|
644
|
-
f"visualizer_type should be of type {LeapDataType.__name__} but got {type(visualizer_type)}"
|
|
645
|
-
)
|
|
646
|
-
|
|
647
415
|
for viz_handler in leap_binder.setup_container.visualizers:
|
|
648
416
|
if viz_handler.visualizer_handler_data.name == name:
|
|
649
417
|
raise Exception(f'Visualizer with name {name} already exists. '
|
|
650
418
|
f'Please choose another')
|
|
651
419
|
|
|
652
420
|
def _validate_input_args(*args, **kwargs):
|
|
653
|
-
assert len(args) > 0, (
|
|
654
|
-
f"{user_function.__name__}() validation failed: "
|
|
655
|
-
f"Expected at least one positional|key-word argument of type np.ndarray, "
|
|
656
|
-
f"but received none. "
|
|
657
|
-
f"Correct usage example: {user_function.__name__}(input_array: np.ndarray, ...)"
|
|
658
|
-
)
|
|
659
421
|
for i, arg in enumerate(args):
|
|
660
422
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
661
|
-
f'
|
|
423
|
+
f'tensorleap_custom_visualizer validation failed: '
|
|
662
424
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
663
425
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
664
426
|
assert arg.shape[0] != leap_binder.batch_size_to_validate, \
|
|
665
|
-
(f'
|
|
427
|
+
(f'tensorleap_custom_visualizer validation failed: '
|
|
666
428
|
f'Argument #{i} should be without batch dimension. ')
|
|
667
429
|
|
|
668
430
|
for _arg_name, arg in kwargs.items():
|
|
669
431
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
670
|
-
f'
|
|
432
|
+
f'tensorleap_custom_visualizer validation failed: '
|
|
671
433
|
f'Argument {_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
672
434
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
673
435
|
assert arg.shape[0] != leap_binder.batch_size_to_validate, \
|
|
674
|
-
(f'
|
|
436
|
+
(f'tensorleap_custom_visualizer validation failed: Argument {_arg_name} '
|
|
675
437
|
f'should be without batch dimension. ')
|
|
676
438
|
|
|
677
439
|
def _validate_result(result):
|
|
@@ -685,11 +447,8 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
685
447
|
LeapDataType.ImageWithBBox: LeapImageWithBBox,
|
|
686
448
|
LeapDataType.ImageWithHeatmap: LeapImageWithHeatmap
|
|
687
449
|
}
|
|
688
|
-
validate_output_structure(result, func_name=user_function.__name__,
|
|
689
|
-
expected_type_name=result_type_map[visualizer_type])
|
|
690
|
-
|
|
691
450
|
assert isinstance(result, result_type_map[visualizer_type]), \
|
|
692
|
-
(f'
|
|
451
|
+
(f'tensorleap_custom_visualizer validation failed: '
|
|
693
452
|
f'The return type should be {result_type_map[visualizer_type]}. Got {type(result)}.')
|
|
694
453
|
|
|
695
454
|
@functools.wraps(user_function)
|
|
@@ -721,7 +480,6 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
721
480
|
result = inner_without_validate(*args, **kwargs)
|
|
722
481
|
|
|
723
482
|
_validate_result(result)
|
|
724
|
-
_update_env_status("tensorleap_custom_visualizer","v")
|
|
725
483
|
return result
|
|
726
484
|
|
|
727
485
|
def mapping_inner(*args, **kwargs):
|
|
@@ -763,26 +521,30 @@ def tensorleap_metadata(
|
|
|
763
521
|
f'Please choose another')
|
|
764
522
|
|
|
765
523
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
524
|
+
assert isinstance(sample_id, (int, str)), \
|
|
525
|
+
(f'tensorleap_metadata validation failed: '
|
|
526
|
+
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
527
|
+
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
528
|
+
(f'tensorleap_metadata validation failed: '
|
|
529
|
+
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
766
530
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
767
|
-
(f'
|
|
531
|
+
(f'tensorleap_metadata validation failed: '
|
|
768
532
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
769
533
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
770
534
|
|
|
771
535
|
def _validate_result(result):
|
|
772
536
|
supported_result_types = (type(None), int, str, bool, float, dict, np.floating,
|
|
773
537
|
np.bool_, np.unsignedinteger, np.signedinteger, np.integer)
|
|
774
|
-
validate_output_structure(result, func_name=user_function.__name__,
|
|
775
|
-
expected_type_name=supported_result_types)
|
|
776
538
|
assert isinstance(result, supported_result_types), \
|
|
777
|
-
(f'
|
|
539
|
+
(f'tensorleap_metadata validation failed: '
|
|
778
540
|
f'Unsupported return type. Got {type(result)}. should be any of {str(supported_result_types)}')
|
|
779
541
|
if isinstance(result, dict):
|
|
780
542
|
for key, value in result.items():
|
|
781
543
|
assert isinstance(key, str), \
|
|
782
|
-
(f'
|
|
544
|
+
(f'tensorleap_metadata validation failed: '
|
|
783
545
|
f'Keys in the return dict should be of type str. Got {type(key)}.')
|
|
784
546
|
assert isinstance(value, supported_result_types), \
|
|
785
|
-
(f'
|
|
547
|
+
(f'tensorleap_metadata validation failed: '
|
|
786
548
|
f'Values in the return dict should be of type {str(supported_result_types)}. Got {type(value)}.')
|
|
787
549
|
|
|
788
550
|
def inner_without_validate(sample_id, preprocess_response):
|
|
@@ -799,18 +561,15 @@ def tensorleap_metadata(
|
|
|
799
561
|
|
|
800
562
|
leap_binder.set_metadata(inner_without_validate, name, metadata_type)
|
|
801
563
|
|
|
802
|
-
def inner(
|
|
564
|
+
def inner(sample_id, preprocess_response):
|
|
803
565
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
804
566
|
return None
|
|
805
|
-
|
|
806
|
-
func_name=user_function.__name__, expected_names=["idx", "preprocess"],**kwargs)
|
|
807
|
-
sample_id, preprocess_response = args if len(args)!=0 else kwargs.values()
|
|
567
|
+
|
|
808
568
|
_validate_input_args(sample_id, preprocess_response)
|
|
809
569
|
|
|
810
570
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
811
571
|
|
|
812
572
|
_validate_result(result)
|
|
813
|
-
_update_env_status("tensorleap_metadata","v")
|
|
814
573
|
return result
|
|
815
574
|
|
|
816
575
|
return inner
|
|
@@ -873,23 +632,19 @@ def tensorleap_preprocess():
|
|
|
873
632
|
|
|
874
633
|
def _validate_input_args(*args, **kwargs):
|
|
875
634
|
assert len(args) == 0 and len(kwargs) == 0, \
|
|
876
|
-
(f'
|
|
635
|
+
(f'tensorleap_preprocess validation failed: '
|
|
877
636
|
f'The function should not take any arguments. Got {args} and {kwargs}.')
|
|
878
637
|
|
|
879
638
|
def _validate_result(result):
|
|
880
|
-
assert isinstance(result, list),
|
|
881
|
-
f
|
|
882
|
-
|
|
883
|
-
if not isinstance(result, tuple)
|
|
884
|
-
else f"{user_function.__name__}() validation failed: expected to return a single list[{PreprocessResponse.__name__}] object, "
|
|
885
|
-
f"but returned {len(result)} objects instead."
|
|
886
|
-
)
|
|
639
|
+
assert isinstance(result, list), \
|
|
640
|
+
(f'tensorleap_preprocess validation failed: '
|
|
641
|
+
f'The return type should be a list. Got {type(result)}.')
|
|
887
642
|
for i, response in enumerate(result):
|
|
888
643
|
assert isinstance(response, PreprocessResponse), \
|
|
889
|
-
(f'
|
|
644
|
+
(f'tensorleap_preprocess validation failed: '
|
|
890
645
|
f'Element #{i} in the return list should be a PreprocessResponse. Got {type(response)}.')
|
|
891
646
|
assert len(set(result)) == len(result), \
|
|
892
|
-
(f'
|
|
647
|
+
(f'tensorleap_preprocess validation failed: '
|
|
893
648
|
f'The return list should not contain duplicate PreprocessResponse objects.')
|
|
894
649
|
|
|
895
650
|
def inner(*args, **kwargs):
|
|
@@ -897,9 +652,9 @@ def tensorleap_preprocess():
|
|
|
897
652
|
return [None, None, None, None]
|
|
898
653
|
|
|
899
654
|
_validate_input_args(*args, **kwargs)
|
|
655
|
+
|
|
900
656
|
result = user_function()
|
|
901
657
|
_validate_result(result)
|
|
902
|
-
_update_env_status("tensorleap_preprocess", "v")
|
|
903
658
|
return result
|
|
904
659
|
|
|
905
660
|
return inner
|
|
@@ -1098,23 +853,29 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1098
853
|
raise Exception(f"Channel dim for input {name} is expected to be either -1 or positive")
|
|
1099
854
|
|
|
1100
855
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
856
|
+
assert isinstance(sample_id, (int, str)), \
|
|
857
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
858
|
+
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
859
|
+
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
860
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
861
|
+
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
1101
862
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
1102
|
-
(f'
|
|
863
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
1103
864
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
1104
865
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
1105
866
|
|
|
1106
867
|
def _validate_result(result):
|
|
1107
|
-
validate_output_structure(result, func_name=user_function.__name__, expected_type_name = "np.ndarray")
|
|
1108
868
|
assert isinstance(result, np.ndarray), \
|
|
1109
|
-
(f'
|
|
869
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
1110
870
|
f'Unsupported return type. Should be a numpy array. Got {type(result)}.')
|
|
1111
871
|
assert result.dtype == np.float32, \
|
|
1112
|
-
(f'
|
|
872
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
1113
873
|
f'The return type should be a numpy array of type float32. Got {result.dtype}.')
|
|
1114
|
-
assert channel_dim - 1 <= len(result.shape), (f'
|
|
874
|
+
assert channel_dim - 1 <= len(result.shape), (f'tensorleap_input_encoder validation failed: '
|
|
1115
875
|
f'The channel_dim ({channel_dim}) should be <= to the rank of the resulting input rank ({len(result.shape)}).')
|
|
1116
876
|
|
|
1117
877
|
def inner_without_validate(sample_id, preprocess_response):
|
|
878
|
+
|
|
1118
879
|
global _called_from_inside_tl_decorator
|
|
1119
880
|
_called_from_inside_tl_decorator += 1
|
|
1120
881
|
|
|
@@ -1128,10 +889,7 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1128
889
|
leap_binder.set_input(inner_without_validate, name, channel_dim=channel_dim)
|
|
1129
890
|
|
|
1130
891
|
|
|
1131
|
-
def inner(
|
|
1132
|
-
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
1133
|
-
func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
|
|
1134
|
-
sample_id, preprocess_response = args if len(args)!=0 else kwargs.values()
|
|
892
|
+
def inner(sample_id, preprocess_response):
|
|
1135
893
|
_validate_input_args(sample_id, preprocess_response)
|
|
1136
894
|
|
|
1137
895
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
@@ -1139,19 +897,24 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1139
897
|
_validate_result(result)
|
|
1140
898
|
|
|
1141
899
|
if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
|
|
1142
|
-
batch_warning(result,user_function.__name__)
|
|
1143
900
|
result = np.expand_dims(result, axis=0)
|
|
1144
|
-
|
|
901
|
+
# Emit integration test event once per test
|
|
902
|
+
_emit_integration_event_once('input_encoder_integration_test', {
|
|
903
|
+
'encoder_name': name,
|
|
904
|
+
'channel_dim': channel_dim,
|
|
905
|
+
'model_input_index': model_input_index
|
|
906
|
+
})
|
|
1145
907
|
|
|
1146
908
|
return result
|
|
1147
909
|
|
|
1148
910
|
|
|
911
|
+
|
|
1149
912
|
node_mapping_type = NodeMappingType.Input
|
|
1150
913
|
if model_input_index is not None:
|
|
1151
914
|
node_mapping_type = NodeMappingType(f'Input{str(model_input_index)}')
|
|
1152
915
|
inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
1153
916
|
|
|
1154
|
-
def mapping_inner(
|
|
917
|
+
def mapping_inner(sample_id, preprocess_response):
|
|
1155
918
|
class TempMapping:
|
|
1156
919
|
pass
|
|
1157
920
|
|
|
@@ -1163,11 +926,11 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1163
926
|
|
|
1164
927
|
mapping_inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
1165
928
|
|
|
1166
|
-
def final_inner(
|
|
929
|
+
def final_inner(sample_id, preprocess_response):
|
|
1167
930
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
1168
|
-
return mapping_inner(
|
|
931
|
+
return mapping_inner(sample_id, preprocess_response)
|
|
1169
932
|
else:
|
|
1170
|
-
return inner(
|
|
933
|
+
return inner(sample_id, preprocess_response)
|
|
1171
934
|
|
|
1172
935
|
final_inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
1173
936
|
|
|
@@ -1184,18 +947,23 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1184
947
|
f'Please choose another')
|
|
1185
948
|
|
|
1186
949
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
950
|
+
assert isinstance(sample_id, (int, str)), \
|
|
951
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
952
|
+
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
953
|
+
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
954
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
955
|
+
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
1187
956
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
1188
|
-
(f'
|
|
957
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
1189
958
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
1190
959
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
1191
960
|
|
|
1192
961
|
def _validate_result(result):
|
|
1193
|
-
validate_output_structure(result, func_name=user_function.__name__, expected_type_name = "np.ndarray",gt_flag=True)
|
|
1194
962
|
assert isinstance(result, np.ndarray), \
|
|
1195
|
-
(f'
|
|
963
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
1196
964
|
f'Unsupported return type. Should be a numpy array. Got {type(result)}.')
|
|
1197
965
|
assert result.dtype == np.float32, \
|
|
1198
|
-
(f'
|
|
966
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
1199
967
|
f'The return type should be a numpy array of type float32. Got {result.dtype}.')
|
|
1200
968
|
|
|
1201
969
|
def inner_without_validate(sample_id, preprocess_response):
|
|
@@ -1212,10 +980,7 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1212
980
|
leap_binder.set_ground_truth(inner_without_validate, name)
|
|
1213
981
|
|
|
1214
982
|
|
|
1215
|
-
def inner(
|
|
1216
|
-
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
1217
|
-
func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
|
|
1218
|
-
sample_id, preprocess_response = args
|
|
983
|
+
def inner(sample_id, preprocess_response):
|
|
1219
984
|
_validate_input_args(sample_id, preprocess_response)
|
|
1220
985
|
|
|
1221
986
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
@@ -1223,15 +988,13 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1223
988
|
_validate_result(result)
|
|
1224
989
|
|
|
1225
990
|
if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
|
|
1226
|
-
batch_warning(result, user_function.__name__)
|
|
1227
991
|
result = np.expand_dims(result, axis=0)
|
|
1228
|
-
_update_env_status("tensorleap_gt_encoder", "v")
|
|
1229
992
|
|
|
1230
993
|
return result
|
|
1231
994
|
|
|
1232
995
|
inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
1233
996
|
|
|
1234
|
-
def mapping_inner(
|
|
997
|
+
def mapping_inner(sample_id, preprocess_response):
|
|
1235
998
|
class TempMapping:
|
|
1236
999
|
pass
|
|
1237
1000
|
|
|
@@ -1242,11 +1005,11 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1242
1005
|
|
|
1243
1006
|
mapping_inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
1244
1007
|
|
|
1245
|
-
def final_inner(
|
|
1008
|
+
def final_inner(sample_id, preprocess_response):
|
|
1246
1009
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
1247
|
-
return mapping_inner(
|
|
1010
|
+
return mapping_inner(sample_id, preprocess_response)
|
|
1248
1011
|
else:
|
|
1249
|
-
return inner(
|
|
1012
|
+
return inner(sample_id, preprocess_response)
|
|
1250
1013
|
|
|
1251
1014
|
final_inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
1252
1015
|
|
|
@@ -1267,37 +1030,28 @@ def tensorleap_custom_loss(name: str, connects_to=None):
|
|
|
1267
1030
|
valid_types = (np.ndarray, SamplePreprocessResponse)
|
|
1268
1031
|
|
|
1269
1032
|
def _validate_input_args(*args, **kwargs):
|
|
1270
|
-
assert len(args) > 0 and len(kwargs)==0, (
|
|
1271
|
-
f"{user_function.__name__}() validation failed: "
|
|
1272
|
-
f"Expected at least one positional|key-word argument of the allowed types (np.ndarray|SamplePreprocessResponse|list(np.ndarray|SamplePreprocessResponse)). "
|
|
1273
|
-
f"but received none. "
|
|
1274
|
-
f"Correct usage example: {user_function.__name__}(input_array: np.ndarray, ...)"
|
|
1275
|
-
)
|
|
1276
1033
|
for i, arg in enumerate(args):
|
|
1277
1034
|
if isinstance(arg, list):
|
|
1278
1035
|
for y, elem in enumerate(arg):
|
|
1279
|
-
assert isinstance(elem, valid_types), (f'
|
|
1036
|
+
assert isinstance(elem, valid_types), (f'tensorleap_custom_loss validation failed: '
|
|
1280
1037
|
f'Element #{y} of list should be a numpy array. Got {type(elem)}.')
|
|
1281
1038
|
else:
|
|
1282
|
-
assert isinstance(arg, valid_types), (f'
|
|
1039
|
+
assert isinstance(arg, valid_types), (f'tensorleap_custom_loss validation failed: '
|
|
1283
1040
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
1284
1041
|
for _arg_name, arg in kwargs.items():
|
|
1285
1042
|
if isinstance(arg, list):
|
|
1286
1043
|
for y, elem in enumerate(arg):
|
|
1287
|
-
assert isinstance(elem, valid_types), (f'
|
|
1044
|
+
assert isinstance(elem, valid_types), (f'tensorleap_custom_loss validation failed: '
|
|
1288
1045
|
f'Element #{y} of list should be a numpy array. Got {type(elem)}.')
|
|
1289
1046
|
else:
|
|
1290
|
-
assert isinstance(arg, valid_types), (f'
|
|
1047
|
+
assert isinstance(arg, valid_types), (f'tensorleap_custom_loss validation failed: '
|
|
1291
1048
|
f'Argument #{_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
1292
1049
|
|
|
1293
1050
|
def _validate_result(result):
|
|
1294
|
-
validate_output_structure(result, func_name=user_function.__name__,
|
|
1295
|
-
expected_type_name="np.ndarray")
|
|
1296
1051
|
assert isinstance(result, np.ndarray), \
|
|
1297
|
-
(f'
|
|
1052
|
+
(f'tensorleap_custom_loss validation failed: '
|
|
1298
1053
|
f'The return type should be a numpy array. Got {type(result)}.')
|
|
1299
|
-
|
|
1300
|
-
f'The return type should be a 1Dim numpy array but got {result.ndim}Dim.')
|
|
1054
|
+
|
|
1301
1055
|
|
|
1302
1056
|
@functools.wraps(user_function)
|
|
1303
1057
|
def inner_without_validate(*args, **kwargs):
|
|
@@ -1328,8 +1082,6 @@ def tensorleap_custom_loss(name: str, connects_to=None):
|
|
|
1328
1082
|
result = inner_without_validate(*args, **kwargs)
|
|
1329
1083
|
|
|
1330
1084
|
_validate_result(result)
|
|
1331
|
-
_update_env_status("tensorleap_custom_loss", "v")
|
|
1332
|
-
|
|
1333
1085
|
return result
|
|
1334
1086
|
|
|
1335
1087
|
def mapping_inner(*args, **kwargs):
|
|
@@ -1386,87 +1138,3 @@ def tensorleap_custom_layer(name: str):
|
|
|
1386
1138
|
return custom_layer
|
|
1387
1139
|
|
|
1388
1140
|
return decorating_function
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
def tensorleap_status_table():
|
|
1392
|
-
'''
|
|
1393
|
-
Usage example:
|
|
1394
|
-
###################
|
|
1395
|
-
leap_integration.py
|
|
1396
|
-
###################
|
|
1397
|
-
from code_loader.inner_leap_binder.leapbinder_decorators import tensorleap_status_table
|
|
1398
|
-
...
|
|
1399
|
-
...
|
|
1400
|
-
...
|
|
1401
|
-
if __name__ == '__main__':
|
|
1402
|
-
tensorleap_status_table()
|
|
1403
|
-
...
|
|
1404
|
-
'''
|
|
1405
|
-
import atexit
|
|
1406
|
-
import sys
|
|
1407
|
-
import traceback
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
table = [
|
|
1411
|
-
{"name": "tensorleap_preprocess", "status": "x"},
|
|
1412
|
-
{"name": "tensorleap_integration_test", "status": "x"},
|
|
1413
|
-
{"name": "tensorleap_input_encoder", "status": "x"},
|
|
1414
|
-
{"name": "tensorleap_gt_encoder", "status": "x"},
|
|
1415
|
-
{"name": "tensorleap_load_model", "status": "x"},
|
|
1416
|
-
{"name": "tensorleap_custom_loss", "status": "x"},
|
|
1417
|
-
{"name": "tensorleap_custom_metric (optional)", "status": "x"},
|
|
1418
|
-
{"name": "tensorleap_metadata (optional)", "status": "x"},
|
|
1419
|
-
{"name": "tensorleap_custom_visualizer (optional)", "status": "x"},
|
|
1420
|
-
|
|
1421
|
-
]
|
|
1422
|
-
|
|
1423
|
-
_finalizer_called = {"done": False}
|
|
1424
|
-
|
|
1425
|
-
def _print_table():
|
|
1426
|
-
ready_mess = "\nAll parts have been successfully set. If no errors accured, you can now push the project to the Tensorleap system."
|
|
1427
|
-
not_ready_mess = "\nSome mandatory components have not been set yet. Recommended next implementation step: "
|
|
1428
|
-
mandatory_ready_mess = "\nAll mandatory parts have been successfully set. If no errors accured, you can now push the project to the Tensorleap system or continue to the next optional implementation step: "
|
|
1429
|
-
|
|
1430
|
-
name_width = max(len(row["name"]) for row in table)
|
|
1431
|
-
status_width = max(len(row["status"]) for row in table)
|
|
1432
|
-
header = f"{'Function Name'.ljust(name_width)} | {'Status'.ljust(status_width)}"
|
|
1433
|
-
sep = "-" * len(header)
|
|
1434
|
-
print("\n" + header)
|
|
1435
|
-
print(sep)
|
|
1436
|
-
ready=True
|
|
1437
|
-
for row in table:
|
|
1438
|
-
print(f"{row['name'].ljust(name_width)} | {row['status'].ljust(status_width)}")
|
|
1439
|
-
if row['status']=='x' and ready:
|
|
1440
|
-
ready=False
|
|
1441
|
-
next_step=row['name']
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
print(ready_mess) if ready else print(mandatory_ready_mess+next_step) if "optional" in next_step else print(not_ready_mess+next_step)
|
|
1445
|
-
def update_env_params(name: str, status: str = "✓"):
|
|
1446
|
-
for row in table:
|
|
1447
|
-
if row["name"].removesuffix(" (optional)") == name:
|
|
1448
|
-
row["status"] = status
|
|
1449
|
-
break
|
|
1450
|
-
def run_on_exit():
|
|
1451
|
-
if _finalizer_called["done"]:
|
|
1452
|
-
return
|
|
1453
|
-
_finalizer_called["done"] = True
|
|
1454
|
-
_print_table()
|
|
1455
|
-
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
1456
|
-
traceback.print_exception(exc_type, exc_value, exc_traceback)
|
|
1457
|
-
run_on_exit()
|
|
1458
|
-
atexit.register(run_on_exit)
|
|
1459
|
-
sys.excepthook = handle_exception
|
|
1460
|
-
global _update_env_status
|
|
1461
|
-
_update_env_status = update_env_params
|
|
1462
|
-
return update_env_params
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
@@ -126,6 +126,43 @@ class MixpanelTracker:
|
|
|
126
126
|
except Exception as e:
|
|
127
127
|
pass
|
|
128
128
|
|
|
129
|
+
def track_integration_test_event(self, event_name: str, event_properties: Optional[Dict[str, Any]] = None) -> None:
|
|
130
|
+
"""Track an integration test event with device identification.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
event_name: The name of the event to track
|
|
134
|
+
event_properties: Optional additional properties to include in the event
|
|
135
|
+
"""
|
|
136
|
+
# Skip tracking if IS_TENSORLEAP_PLATFORM environment variable is set to 'true'
|
|
137
|
+
if os.environ.get('IS_TENSORLEAP_PLATFORM') == 'true':
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
distinct_id = self._get_distinct_id()
|
|
142
|
+
|
|
143
|
+
tensorleap_user_id = self._get_tensorleap_user_id()
|
|
144
|
+
whoami = self._get_whoami()
|
|
145
|
+
device_id = self._get_or_create_device_id()
|
|
146
|
+
|
|
147
|
+
properties = {
|
|
148
|
+
'tracking_version': TRACKING_VERSION,
|
|
149
|
+
'service': 'code-loader',
|
|
150
|
+
'whoami': whoami,
|
|
151
|
+
'$device_id': device_id, # Always use device_id for $device_id
|
|
152
|
+
'python_version': f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
|
153
|
+
'platform': os.name,
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if tensorleap_user_id:
|
|
157
|
+
properties['user_id'] = tensorleap_user_id
|
|
158
|
+
|
|
159
|
+
if event_properties:
|
|
160
|
+
properties.update(event_properties)
|
|
161
|
+
|
|
162
|
+
self.mp.track(distinct_id, event_name, properties)
|
|
163
|
+
except Exception as e:
|
|
164
|
+
pass
|
|
165
|
+
|
|
129
166
|
|
|
130
167
|
# Global tracker instance
|
|
131
168
|
_tracker = None
|
|
@@ -140,3 +177,7 @@ def get_tracker() -> MixpanelTracker:
|
|
|
140
177
|
|
|
141
178
|
def track_code_loader_loaded(event_properties: Optional[Dict[str, Any]] = None) -> None:
|
|
142
179
|
get_tracker().track_code_loader_loaded(event_properties)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def track_integration_test_event(event_name: str, event_properties: Optional[Dict[str, Any]] = None) -> None:
|
|
183
|
+
get_tracker().track_integration_test_event(event_name, event_properties)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/responsedataclasses.py
RENAMED
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/contract/visualizer_classes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/cli_config_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/experiment_api/experiment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/inner_leap_binder/__init__.py
RENAMED
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/inner_leap_binder/leapbinder.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/plot_functions/__init__.py
RENAMED
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/plot_functions/plot_functions.py
RENAMED
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/plot_functions/visualize.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.139.dev2 → code_loader-1.0.139.dev4}/code_loader/visualizers/default_visualizers.py
RENAMED
|
File without changes
|