code-loader 1.0.146__tar.gz → 1.0.147__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.
- {code_loader-1.0.146 → code_loader-1.0.147}/PKG-INFO +1 -1
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/contract/datasetclasses.py +1 -9
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/inner_leap_binder/leapbinder_decorators.py +110 -482
- {code_loader-1.0.146 → code_loader-1.0.147}/pyproject.toml +1 -1
- {code_loader-1.0.146 → code_loader-1.0.147}/LICENSE +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/README.md +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/__init__.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/contract/__init__.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/contract/enums.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/contract/exceptions.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/contract/mapping.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/contract/responsedataclasses.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/contract/visualizer_classes.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/default_losses.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/default_metrics.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/__init__.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/api.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/cli_config_utils.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/client.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/epoch.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/experiment.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/experiment_context.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/types.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/utils.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/inner_leap_binder/__init__.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/inner_leap_binder/leapbinder.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/leaploader.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/leaploaderbase.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/mixpanel_tracker.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/plot_functions/__init__.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/plot_functions/plot_functions.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/plot_functions/visualize.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/utils.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/visualizers/__init__.py +0 -0
- {code_loader-1.0.146 → code_loader-1.0.147}/code_loader/visualizers/default_visualizers.py +0 -0
|
@@ -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)
|
{code_loader-1.0.146 → code_loader-1.0.147}/code_loader/inner_leap_binder/leapbinder_decorators.py
RENAMED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# mypy: ignore-errors
|
|
2
2
|
import os
|
|
3
|
-
import warnings
|
|
4
3
|
import logging
|
|
5
4
|
from collections import defaultdict
|
|
6
5
|
from functools import lru_cache
|
|
7
6
|
from pathlib import Path
|
|
8
7
|
from typing import Optional, Union, Callable, List, Dict, Set, Any
|
|
9
|
-
from typing import Optional, Union, Callable, List, Dict, get_args, get_origin
|
|
10
8
|
|
|
11
9
|
import numpy as np
|
|
12
10
|
import numpy.typing as npt
|
|
@@ -31,116 +29,8 @@ import functools
|
|
|
31
29
|
|
|
32
30
|
_called_from_inside_tl_decorator = 0
|
|
33
31
|
_called_from_inside_tl_integration_test_decorator = False
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def validate_args_structure(*args, types_order, func_name, expected_names, **kwargs):
|
|
40
|
-
def _type_to_str(t):
|
|
41
|
-
origin = get_origin(t)
|
|
42
|
-
if origin is Union:
|
|
43
|
-
return " | ".join(tt.__name__ for tt in get_args(t))
|
|
44
|
-
elif hasattr(t, "__name__"):
|
|
45
|
-
return t.__name__
|
|
46
|
-
else:
|
|
47
|
-
return str(t)
|
|
48
|
-
|
|
49
|
-
def _format_types(types, names=None):
|
|
50
|
-
return ", ".join(
|
|
51
|
-
f"{(names[i] + ': ') if names else f'arg{i}: '}{_type_to_str(ty)}"
|
|
52
|
-
for i, ty in enumerate(types)
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
if expected_names:
|
|
56
|
-
normalized_args = []
|
|
57
|
-
for i, name in enumerate(expected_names):
|
|
58
|
-
if i < len(args):
|
|
59
|
-
normalized_args.append(args[i])
|
|
60
|
-
elif name in kwargs:
|
|
61
|
-
normalized_args.append(kwargs[name])
|
|
62
|
-
else:
|
|
63
|
-
raise AssertionError(
|
|
64
|
-
f"{func_name} validation failed: "
|
|
65
|
-
f"Missing required argument '{name}'. "
|
|
66
|
-
f"Expected arguments: {expected_names}."
|
|
67
|
-
)
|
|
68
|
-
else:
|
|
69
|
-
normalized_args = list(args)
|
|
70
|
-
if len(normalized_args) != len(types_order):
|
|
71
|
-
expected = _format_types(types_order, expected_names)
|
|
72
|
-
got_types = ", ".join(type(arg).__name__ for arg in normalized_args)
|
|
73
|
-
raise AssertionError(
|
|
74
|
-
f"{func_name} validation failed: "
|
|
75
|
-
f"Expected exactly {len(types_order)} arguments ({expected}), "
|
|
76
|
-
f"but got {len(normalized_args)} argument(s) of type(s): ({got_types}). "
|
|
77
|
-
f"Correct usage example: {func_name}({expected})"
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
for i, (arg, expected_type) in enumerate(zip(normalized_args, types_order)):
|
|
81
|
-
origin = get_origin(expected_type)
|
|
82
|
-
if origin is Union:
|
|
83
|
-
allowed_types = get_args(expected_type)
|
|
84
|
-
else:
|
|
85
|
-
allowed_types = (expected_type,)
|
|
86
|
-
|
|
87
|
-
if not isinstance(arg, allowed_types):
|
|
88
|
-
allowed_str = " | ".join(t.__name__ for t in allowed_types)
|
|
89
|
-
raise AssertionError(
|
|
90
|
-
f"{func_name} validation failed: "
|
|
91
|
-
f"Argument '{expected_names[i] if expected_names else f'arg{i}'}' "
|
|
92
|
-
f"expected type {allowed_str}, but got {type(arg).__name__}. "
|
|
93
|
-
f"Correct usage example: {func_name}({_format_types(types_order, expected_names)})"
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def validate_output_structure(result, func_name: str, expected_type_name="np.ndarray",gt_flag=False):
|
|
98
|
-
if result is None or (isinstance(result, float) and np.isnan(result)):
|
|
99
|
-
if gt_flag:
|
|
100
|
-
raise AssertionError(
|
|
101
|
-
f"{func_name} validation failed: "
|
|
102
|
-
f"The function returned {result!r}. "
|
|
103
|
-
f"If you are working with an unlabeled dataset and no ground truth is available, "
|
|
104
|
-
f"use 'return np.array([], dtype=np.float32)' instead. "
|
|
105
|
-
f"Otherwise, {func_name} expected a single {expected_type_name} object. "
|
|
106
|
-
f"Make sure the function ends with 'return <{expected_type_name}>'."
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
raise AssertionError(
|
|
110
|
-
f"{func_name} validation failed: "
|
|
111
|
-
f"The function returned None. "
|
|
112
|
-
f"Expected a single {expected_type_name} object. "
|
|
113
|
-
f"Make sure the function ends with 'return <{expected_type_name}>'."
|
|
114
|
-
)
|
|
115
|
-
if isinstance(result, tuple):
|
|
116
|
-
element_descriptions = [
|
|
117
|
-
f"[{i}] type: {type(r).__name__}"
|
|
118
|
-
for i, r in enumerate(result)
|
|
119
|
-
]
|
|
120
|
-
element_summary = "\n ".join(element_descriptions)
|
|
121
|
-
|
|
122
|
-
raise AssertionError(
|
|
123
|
-
f"{func_name} validation failed: "
|
|
124
|
-
f"The function returned multiple outputs ({len(result)} values), "
|
|
125
|
-
f"but only a single {expected_type_name} is allowed.\n\n"
|
|
126
|
-
f"Returned elements:\n"
|
|
127
|
-
f" {element_summary}\n\n"
|
|
128
|
-
f"Correct usage example:\n"
|
|
129
|
-
f" def {func_name}(...):\n"
|
|
130
|
-
f" return <{expected_type_name}>\n\n"
|
|
131
|
-
f"If you intended to return multiple values, combine them into a single "
|
|
132
|
-
f"{expected_type_name} (e.g., by concatenation or stacking)."
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
def batch_warning(result, func_name):
|
|
136
|
-
if result.shape[0] == 1:
|
|
137
|
-
warnings.warn(
|
|
138
|
-
f"{func_name} warning: Tensorleap will add a batch dimension at axis 0 to the output of {func_name}, "
|
|
139
|
-
f"although the detected size of axis 0 is already 1. "
|
|
140
|
-
f"This may lead to an extra batch dimension (e.g., shape (1, 1, ...)). "
|
|
141
|
-
f"Please ensure that the output of '{func_name}' is not already batched "
|
|
142
|
-
f"to avoid computation errors."
|
|
143
|
-
)
|
|
32
|
+
|
|
33
|
+
|
|
144
34
|
def _add_mapping_connection(user_unique_name, connection_destinations, arg_names, name, node_mapping_type):
|
|
145
35
|
connection_destinations = [connection_destination for connection_destination in connection_destinations
|
|
146
36
|
if not isinstance(connection_destination, SamplePreprocessResponse)]
|
|
@@ -163,19 +53,7 @@ def tensorleap_integration_test():
|
|
|
163
53
|
def decorating_function(integration_test_function: Callable):
|
|
164
54
|
leap_binder.integration_test_func = integration_test_function
|
|
165
55
|
|
|
166
|
-
def _validate_input_args(*args, **kwargs):
|
|
167
|
-
sample_id,preprocess_response=args
|
|
168
|
-
assert type(sample_id) == preprocess_response.sample_id_type, (
|
|
169
|
-
f"tensorleap_integration_test validation failed: "
|
|
170
|
-
f"sample_id type ({type(sample_id).__name__}) does not match the expected "
|
|
171
|
-
f"type ({preprocess_response.sample_id_type}) from the PreprocessResponse."
|
|
172
|
-
)
|
|
173
|
-
|
|
174
56
|
def inner(*args, **kwargs):
|
|
175
|
-
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
176
|
-
func_name='integration_test',expected_names=["idx", "preprocess"],**kwargs)
|
|
177
|
-
_validate_input_args(*args, **kwargs)
|
|
178
|
-
|
|
179
57
|
global _called_from_inside_tl_integration_test_decorator
|
|
180
58
|
# Clear integration test events for new test
|
|
181
59
|
try:
|
|
@@ -184,8 +62,6 @@ def tensorleap_integration_test():
|
|
|
184
62
|
logger.debug(f"Failed to clear integration events: {e}")
|
|
185
63
|
try:
|
|
186
64
|
_called_from_inside_tl_integration_test_decorator = True
|
|
187
|
-
if not _call_from_tl_platform:
|
|
188
|
-
update_env_params_func("tensorleap_integration_test", "v")#put here because otherwise it will become v only if it finishes all the script
|
|
189
65
|
ret = integration_test_function(*args, **kwargs)
|
|
190
66
|
|
|
191
67
|
try:
|
|
@@ -197,14 +73,10 @@ def tensorleap_integration_test():
|
|
|
197
73
|
file_name = Path(first_tb.filename).name
|
|
198
74
|
line_number = first_tb.lineno
|
|
199
75
|
if isinstance(e, TypeError) and 'is not subscriptable' in str(e):
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
raise(f'Invalid integration code. File {file_name}, line {line_number}: '
|
|
203
|
-
f"indexing is supported only on the model's predictions inside the integration test. Please remove this indexing operation usage from the integration test code.")
|
|
76
|
+
print(f'Invalid integration code. File {file_name}, line {line_number}: '
|
|
77
|
+
f'Please remove this indexing operation usage from the integration test code.')
|
|
204
78
|
else:
|
|
205
|
-
|
|
206
|
-
update_env_params_func("code_mapping", "v")
|
|
207
|
-
raise(f'Invalid integration code. File {file_name}, line {line_number}: '
|
|
79
|
+
print(f'Invalid integration code. File {file_name}, line {line_number}: '
|
|
208
80
|
f'Integration test is only allowed to call Tensorleap decorators. '
|
|
209
81
|
f'Ensure any arithmetics, external library use, Python logic is placed within Tensorleap decoders')
|
|
210
82
|
finally:
|
|
@@ -214,8 +86,8 @@ def tensorleap_integration_test():
|
|
|
214
86
|
_called_from_inside_tl_integration_test_decorator = False
|
|
215
87
|
|
|
216
88
|
leap_binder.check()
|
|
217
|
-
return inner
|
|
218
89
|
|
|
90
|
+
return inner
|
|
219
91
|
|
|
220
92
|
return decorating_function
|
|
221
93
|
|
|
@@ -225,63 +97,34 @@ def _safe_get_item(key):
|
|
|
225
97
|
except ValueError:
|
|
226
98
|
raise Exception(f'Tensorleap currently supports models with no more then 10 inputs')
|
|
227
99
|
|
|
100
|
+
|
|
228
101
|
def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]] = []):
|
|
229
|
-
assert isinstance(prediction_types, list),(
|
|
230
|
-
f"tensorleap_load_model validation failed: "
|
|
231
|
-
f" prediction_types is an optional argument of type List[PredictionTypeHandler]] but got {type(prediction_types).__name__}."
|
|
232
|
-
)
|
|
233
102
|
for i, prediction_type in enumerate(prediction_types):
|
|
234
|
-
assert isinstance(prediction_type, PredictionTypeHandler),(f"tensorleap_load_model validation failed: "
|
|
235
|
-
f" prediction_types at position {i} must be of type PredictionTypeHandler but got {type(prediction_types[i]).__name__}.")
|
|
236
103
|
leap_binder.add_prediction(prediction_type.name, prediction_type.labels, prediction_type.channel_dim, i)
|
|
237
104
|
|
|
238
|
-
def _validate_result(result) -> None:
|
|
239
|
-
valid_types=["onnxruntime","keras"]
|
|
240
|
-
err_message=f"tensorleap_load_model validation failed:\nSupported models are Keras and onnxruntime only and non of them was returned."
|
|
241
|
-
validate_output_structure(result, func_name="tensorleap_load_model", expected_type_name= [" | ".join(t for t in valid_types)][0])
|
|
242
|
-
try:
|
|
243
|
-
import keras
|
|
244
|
-
except ImportError:
|
|
245
|
-
keras = None
|
|
246
|
-
try:
|
|
247
|
-
import tensorflow as tf
|
|
248
|
-
except ImportError:
|
|
249
|
-
tf = None
|
|
250
|
-
try:
|
|
251
|
-
import onnxruntime
|
|
252
|
-
except ImportError:
|
|
253
|
-
onnxruntime = None
|
|
254
|
-
|
|
255
|
-
if not keras and not onnxruntime:
|
|
256
|
-
raise AssertionError(err_message)
|
|
257
|
-
|
|
258
|
-
is_keras_model = (
|
|
259
|
-
bool(keras and isinstance(result, getattr(keras, "Model", tuple())))
|
|
260
|
-
or bool(tf and isinstance(result, getattr(tf.keras, "Model", tuple())))
|
|
261
|
-
)
|
|
262
|
-
is_onnx_model = bool(onnxruntime and isinstance(result, onnxruntime.InferenceSession))
|
|
263
|
-
|
|
264
|
-
if not any([is_keras_model, is_onnx_model]):
|
|
265
|
-
raise AssertionError( err_message)
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
105
|
def decorating_function(load_model_func):
|
|
270
106
|
class TempMapping:
|
|
271
107
|
pass
|
|
272
108
|
|
|
273
109
|
@lru_cache()
|
|
274
|
-
def inner(
|
|
275
|
-
validate_args_structure(*args, types_order=[],
|
|
276
|
-
func_name='tensorleap_load_model',expected_names=[],**kwargs)
|
|
110
|
+
def inner():
|
|
277
111
|
class ModelPlaceholder:
|
|
278
112
|
def __init__(self):
|
|
279
|
-
self.model = load_model_func()
|
|
280
|
-
|
|
113
|
+
self.model = load_model_func()
|
|
114
|
+
# Emit integration test event once per test
|
|
115
|
+
try:
|
|
116
|
+
emit_integration_event_once(AnalyticsEvent.LOAD_MODEL_INTEGRATION_TEST, {
|
|
117
|
+
'prediction_types_count': len(prediction_types)
|
|
118
|
+
})
|
|
119
|
+
except Exception as e:
|
|
120
|
+
logger.debug(f"Failed to emit load_model integration test event: {e}")
|
|
281
121
|
|
|
282
122
|
# keras interface
|
|
283
123
|
def __call__(self, arg):
|
|
284
124
|
ret = self.model(arg)
|
|
125
|
+
if isinstance(ret, list):
|
|
126
|
+
return [r.numpy() for r in ret]
|
|
127
|
+
|
|
285
128
|
return ret.numpy()
|
|
286
129
|
|
|
287
130
|
def _convert_onnx_inputs_to_correct_type(
|
|
@@ -341,10 +184,8 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
|
|
|
341
184
|
|
|
342
185
|
def get_inputs(self):
|
|
343
186
|
return self.model.get_inputs()
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
update_env_params_func("tensorleap_load_model", "v")
|
|
347
|
-
return model_placeholder
|
|
187
|
+
|
|
188
|
+
return ModelPlaceholder()
|
|
348
189
|
|
|
349
190
|
def mapping_inner():
|
|
350
191
|
class ModelOutputPlaceholder:
|
|
@@ -407,11 +248,12 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
|
|
|
407
248
|
|
|
408
249
|
return ModelPlaceholder()
|
|
409
250
|
|
|
410
|
-
def final_inner(
|
|
251
|
+
def final_inner():
|
|
411
252
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
412
253
|
return mapping_inner()
|
|
413
254
|
else:
|
|
414
|
-
return inner(
|
|
255
|
+
return inner()
|
|
256
|
+
|
|
415
257
|
return final_inner
|
|
416
258
|
|
|
417
259
|
return decorating_function
|
|
@@ -422,168 +264,81 @@ def tensorleap_custom_metric(name: str,
|
|
|
422
264
|
compute_insights: Optional[Union[bool, Dict[str, bool]]] = None,
|
|
423
265
|
connects_to=None):
|
|
424
266
|
name_to_unique_name = defaultdict(set)
|
|
267
|
+
|
|
425
268
|
def decorating_function(
|
|
426
269
|
user_function: Union[CustomCallableInterfaceMultiArgs, CustomMultipleReturnCallableInterfaceMultiArgs,
|
|
427
270
|
ConfusionMatrixCallableInterfaceMultiArgs]):
|
|
428
|
-
|
|
429
|
-
def _validate_decorators_signature():
|
|
430
|
-
err_message = f"{user_function.__name__} validation failed.\n"
|
|
431
|
-
if not isinstance(name, str):
|
|
432
|
-
raise TypeError(err_message + f"`name` must be a string, got type {type(name).__name__}.")
|
|
433
|
-
valid_directions = {MetricDirection.Upward, MetricDirection.Downward}
|
|
434
|
-
if isinstance(direction, MetricDirection):
|
|
435
|
-
if direction not in valid_directions:
|
|
436
|
-
raise ValueError(
|
|
437
|
-
err_message +
|
|
438
|
-
f"Invalid MetricDirection: {direction}. Must be one of {valid_directions}, "
|
|
439
|
-
f"got type {type(direction).__name__}."
|
|
440
|
-
)
|
|
441
|
-
elif isinstance(direction, dict):
|
|
442
|
-
if not all(isinstance(k, str) for k in direction.keys()):
|
|
443
|
-
invalid_keys = {k: type(k).__name__ for k in direction.keys() if not isinstance(k, str)}
|
|
444
|
-
raise TypeError(
|
|
445
|
-
err_message +
|
|
446
|
-
f"All keys in `direction` must be strings, got invalid key types: {invalid_keys}."
|
|
447
|
-
)
|
|
448
|
-
for k, v in direction.items():
|
|
449
|
-
if v not in valid_directions:
|
|
450
|
-
raise ValueError(
|
|
451
|
-
err_message +
|
|
452
|
-
f"Invalid direction for key '{k}': {v}. Must be one of {valid_directions}, "
|
|
453
|
-
f"got type {type(v).__name__}."
|
|
454
|
-
)
|
|
455
|
-
else:
|
|
456
|
-
raise TypeError(
|
|
457
|
-
err_message +
|
|
458
|
-
f"`direction` must be a MetricDirection or a Dict[str, MetricDirection], "
|
|
459
|
-
f"got type {type(direction).__name__}."
|
|
460
|
-
)
|
|
461
|
-
if compute_insights is not None:
|
|
462
|
-
if not isinstance(compute_insights, (bool, dict)):
|
|
463
|
-
raise TypeError(
|
|
464
|
-
err_message +
|
|
465
|
-
f"`compute_insights` must be a bool or a Dict[str, bool], "
|
|
466
|
-
f"got type {type(compute_insights).__name__}."
|
|
467
|
-
)
|
|
468
|
-
if isinstance(compute_insights, dict):
|
|
469
|
-
if not all(isinstance(k, str) for k in compute_insights.keys()):
|
|
470
|
-
invalid_keys = {k: type(k).__name__ for k in compute_insights.keys() if not isinstance(k, str)}
|
|
471
|
-
raise TypeError(
|
|
472
|
-
err_message +
|
|
473
|
-
f"All keys in `compute_insights` must be strings, got invalid key types: {invalid_keys}."
|
|
474
|
-
)
|
|
475
|
-
for k, v in compute_insights.items():
|
|
476
|
-
if not isinstance(v, bool):
|
|
477
|
-
raise TypeError(
|
|
478
|
-
err_message +
|
|
479
|
-
f"Invalid type for compute_insights['{k}']: expected bool, got type {type(v).__name__}."
|
|
480
|
-
)
|
|
481
|
-
if connects_to is not None:
|
|
482
|
-
valid_types = (str, list, tuple, set)
|
|
483
|
-
if not isinstance(connects_to, valid_types):
|
|
484
|
-
raise TypeError(
|
|
485
|
-
err_message +
|
|
486
|
-
f"`connects_to` must be one of {valid_types}, got type {type(connects_to).__name__}."
|
|
487
|
-
)
|
|
488
|
-
if isinstance(connects_to, (list, tuple, set)):
|
|
489
|
-
invalid_elems = [f"{type(e).__name__}" for e in connects_to if not isinstance(e, str)]
|
|
490
|
-
if invalid_elems:
|
|
491
|
-
raise TypeError(
|
|
492
|
-
err_message +
|
|
493
|
-
f"All elements in `connects_to` must be strings, "
|
|
494
|
-
f"but found element types: {invalid_elems}."
|
|
495
|
-
)
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
_validate_decorators_signature()
|
|
499
|
-
|
|
500
271
|
for metric_handler in leap_binder.setup_container.metrics:
|
|
501
272
|
if metric_handler.metric_handler_data.name == name:
|
|
502
273
|
raise Exception(f'Metric with name {name} already exists. '
|
|
503
274
|
f'Please choose another')
|
|
504
275
|
|
|
505
276
|
def _validate_input_args(*args, **kwargs) -> None:
|
|
506
|
-
assert len(args)+len(kwargs) > 0, (
|
|
507
|
-
f"{user_function.__name__}() validation failed: "
|
|
508
|
-
f"Expected at least one positional|key-word argument of type np.ndarray, "
|
|
509
|
-
f"but received none. "
|
|
510
|
-
f"Correct usage example: tensorleap_custom_metric(input_array: np.ndarray, ...)"
|
|
511
|
-
)
|
|
512
277
|
for i, arg in enumerate(args):
|
|
513
278
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
514
|
-
f'
|
|
279
|
+
f'tensorleap_custom_metric validation failed: '
|
|
515
280
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
516
281
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
517
282
|
assert arg.shape[0] == leap_binder.batch_size_to_validate, \
|
|
518
|
-
(f'
|
|
283
|
+
(f'tensorleap_custom_metric validation failed: Argument #{i} '
|
|
519
284
|
f'first dim should be as the batch size. Got {arg.shape[0]} '
|
|
520
285
|
f'instead of {leap_binder.batch_size_to_validate}')
|
|
521
286
|
|
|
522
287
|
for _arg_name, arg in kwargs.items():
|
|
523
288
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
524
|
-
f'
|
|
289
|
+
f'tensorleap_custom_metric validation failed: '
|
|
525
290
|
f'Argument {_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
526
291
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
527
292
|
assert arg.shape[0] == leap_binder.batch_size_to_validate, \
|
|
528
|
-
(f'
|
|
293
|
+
(f'tensorleap_custom_metric validation failed: Argument {_arg_name} '
|
|
529
294
|
f'first dim should be as the batch size. Got {arg.shape[0]} '
|
|
530
295
|
f'instead of {leap_binder.batch_size_to_validate}')
|
|
531
296
|
|
|
532
297
|
def _validate_result(result) -> None:
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
f'{user_function.__name__}() has returned unsupported type.\nSupported types are List[float|int|None], '
|
|
537
|
-
f'List[List[ConfusionMatrixElement]], NDArray[np.float32] or dictonary with one of these types as its values types. ')
|
|
298
|
+
supported_types_message = (f'tensorleap_custom_metric validation failed: '
|
|
299
|
+
f'Metric has returned unsupported type. Supported types are List[float], '
|
|
300
|
+
f'List[List[ConfusionMatrixElement]], NDArray[np.float32]. ')
|
|
538
301
|
|
|
539
|
-
def _validate_single_metric(single_metric_result
|
|
302
|
+
def _validate_single_metric(single_metric_result):
|
|
540
303
|
if isinstance(single_metric_result, list):
|
|
541
304
|
if isinstance(single_metric_result[0], list):
|
|
542
|
-
assert
|
|
543
|
-
f
|
|
544
|
-
f"Got {'a dict where the value of ' + str(key) + ' is of type ' if key is not None else ''}"
|
|
545
|
-
f"List[List[{', '.join(type(cm).__name__ for cm in single_metric_result[0])}]]."
|
|
546
|
-
)
|
|
547
|
-
|
|
305
|
+
assert isinstance(single_metric_result[0][0], ConfusionMatrixElement), \
|
|
306
|
+
f'{supported_types_message}Got List[List[{type(single_metric_result[0][0])}]].'
|
|
548
307
|
else:
|
|
549
|
-
assert
|
|
550
|
-
|
|
551
|
-
f
|
|
552
|
-
f"List[{', '.join(type(v).__name__ for v in single_metric_result)}]."
|
|
553
|
-
)
|
|
308
|
+
assert isinstance(single_metric_result[0], (
|
|
309
|
+
float, int,
|
|
310
|
+
type(None))), f'{supported_types_message}Got List[{type(single_metric_result[0])}].'
|
|
554
311
|
else:
|
|
555
312
|
assert isinstance(single_metric_result,
|
|
556
|
-
np.ndarray), f'{supported_types_message}
|
|
557
|
-
assert len(single_metric_result.shape) == 1, (f'
|
|
313
|
+
np.ndarray), f'{supported_types_message}Got {type(single_metric_result)}.'
|
|
314
|
+
assert len(single_metric_result.shape) == 1, (f'tensorleap_custom_metric validation failed: '
|
|
558
315
|
f'The return shape should be 1D. Got {len(single_metric_result.shape)}D.')
|
|
559
316
|
|
|
560
317
|
if leap_binder.batch_size_to_validate:
|
|
561
318
|
assert len(single_metric_result) == leap_binder.batch_size_to_validate, \
|
|
562
|
-
f'
|
|
319
|
+
f'tensorleap_custom_metrix validation failed: The return len should be as the batch size.'
|
|
563
320
|
|
|
564
321
|
if isinstance(result, dict):
|
|
565
322
|
for key, value in result.items():
|
|
566
|
-
_validate_single_metric(value,key)
|
|
567
|
-
|
|
568
323
|
assert isinstance(key, str), \
|
|
569
|
-
(f'
|
|
324
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
570
325
|
f'Keys in the return dict should be of type str. Got {type(key)}.')
|
|
571
326
|
_validate_single_metric(value)
|
|
572
327
|
|
|
573
328
|
if isinstance(direction, dict):
|
|
574
329
|
for direction_key in direction:
|
|
575
330
|
assert direction_key in result, \
|
|
576
|
-
(f'
|
|
331
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
577
332
|
f'Keys in the direction mapping should be part of result keys. Got key {direction_key}.')
|
|
578
333
|
|
|
579
334
|
if compute_insights is not None:
|
|
580
335
|
assert isinstance(compute_insights, dict), \
|
|
581
|
-
(f'
|
|
336
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
582
337
|
f'compute_insights should be dict if using the dict results. Got {type(compute_insights)}.')
|
|
583
338
|
|
|
584
339
|
for ci_key in compute_insights:
|
|
585
340
|
assert ci_key in result, \
|
|
586
|
-
(f'
|
|
341
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
587
342
|
f'Keys in the compute_insights mapping should be part of result keys. Got key {ci_key}.')
|
|
588
343
|
|
|
589
344
|
else:
|
|
@@ -591,7 +346,7 @@ def tensorleap_custom_metric(name: str,
|
|
|
591
346
|
|
|
592
347
|
if compute_insights is not None:
|
|
593
348
|
assert isinstance(compute_insights, bool), \
|
|
594
|
-
(f'
|
|
349
|
+
(f'tensorleap_custom_metric validation failed: '
|
|
595
350
|
f'compute_insights should be boolean. Got {type(compute_insights)}.')
|
|
596
351
|
|
|
597
352
|
@functools.wraps(user_function)
|
|
@@ -623,8 +378,6 @@ def tensorleap_custom_metric(name: str,
|
|
|
623
378
|
result = inner_without_validate(*args, **kwargs)
|
|
624
379
|
|
|
625
380
|
_validate_result(result)
|
|
626
|
-
if not _call_from_tl_platform:
|
|
627
|
-
update_env_params_func("tensorleap_custom_metric","v")
|
|
628
381
|
return result
|
|
629
382
|
|
|
630
383
|
def mapping_inner(*args, **kwargs):
|
|
@@ -664,38 +417,28 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
664
417
|
name_to_unique_name = defaultdict(set)
|
|
665
418
|
|
|
666
419
|
def decorating_function(user_function: VisualizerCallableInterface):
|
|
667
|
-
assert isinstance(visualizer_type,LeapDataType),(f"{user_function.__name__} validation failed: "
|
|
668
|
-
f"visualizer_type should be of type {LeapDataType.__name__} but got {type(visualizer_type)}"
|
|
669
|
-
)
|
|
670
|
-
|
|
671
420
|
for viz_handler in leap_binder.setup_container.visualizers:
|
|
672
421
|
if viz_handler.visualizer_handler_data.name == name:
|
|
673
422
|
raise Exception(f'Visualizer with name {name} already exists. '
|
|
674
423
|
f'Please choose another')
|
|
675
424
|
|
|
676
425
|
def _validate_input_args(*args, **kwargs):
|
|
677
|
-
assert len(args) + len(kwargs) > 0, (
|
|
678
|
-
f"{user_function.__name__}() validation failed: "
|
|
679
|
-
f"Expected at least one positional|key-word argument of type np.ndarray, "
|
|
680
|
-
f"but received none. "
|
|
681
|
-
f"Correct usage example: {user_function.__name__}(input_array: np.ndarray, ...)"
|
|
682
|
-
)
|
|
683
426
|
for i, arg in enumerate(args):
|
|
684
427
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
685
|
-
f'
|
|
428
|
+
f'tensorleap_custom_visualizer validation failed: '
|
|
686
429
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
687
430
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
688
431
|
assert arg.shape[0] != leap_binder.batch_size_to_validate, \
|
|
689
|
-
(f'
|
|
432
|
+
(f'tensorleap_custom_visualizer validation failed: '
|
|
690
433
|
f'Argument #{i} should be without batch dimension. ')
|
|
691
434
|
|
|
692
435
|
for _arg_name, arg in kwargs.items():
|
|
693
436
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
694
|
-
f'
|
|
437
|
+
f'tensorleap_custom_visualizer validation failed: '
|
|
695
438
|
f'Argument {_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
696
439
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
697
440
|
assert arg.shape[0] != leap_binder.batch_size_to_validate, \
|
|
698
|
-
(f'
|
|
441
|
+
(f'tensorleap_custom_visualizer validation failed: Argument {_arg_name} '
|
|
699
442
|
f'should be without batch dimension. ')
|
|
700
443
|
|
|
701
444
|
def _validate_result(result):
|
|
@@ -709,11 +452,8 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
709
452
|
LeapDataType.ImageWithBBox: LeapImageWithBBox,
|
|
710
453
|
LeapDataType.ImageWithHeatmap: LeapImageWithHeatmap
|
|
711
454
|
}
|
|
712
|
-
validate_output_structure(result, func_name=user_function.__name__,
|
|
713
|
-
expected_type_name=result_type_map[visualizer_type])
|
|
714
|
-
|
|
715
455
|
assert isinstance(result, result_type_map[visualizer_type]), \
|
|
716
|
-
(f'
|
|
456
|
+
(f'tensorleap_custom_visualizer validation failed: '
|
|
717
457
|
f'The return type should be {result_type_map[visualizer_type]}. Got {type(result)}.')
|
|
718
458
|
|
|
719
459
|
@functools.wraps(user_function)
|
|
@@ -745,8 +485,6 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
745
485
|
result = inner_without_validate(*args, **kwargs)
|
|
746
486
|
|
|
747
487
|
_validate_result(result)
|
|
748
|
-
if not _call_from_tl_platform:
|
|
749
|
-
update_env_params_func("tensorleap_custom_visualizer","v")
|
|
750
488
|
return result
|
|
751
489
|
|
|
752
490
|
def mapping_inner(*args, **kwargs):
|
|
@@ -788,26 +526,30 @@ def tensorleap_metadata(
|
|
|
788
526
|
f'Please choose another')
|
|
789
527
|
|
|
790
528
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
529
|
+
assert isinstance(sample_id, (int, str)), \
|
|
530
|
+
(f'tensorleap_metadata validation failed: '
|
|
531
|
+
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
532
|
+
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
533
|
+
(f'tensorleap_metadata validation failed: '
|
|
534
|
+
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
791
535
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
792
|
-
(f'
|
|
536
|
+
(f'tensorleap_metadata validation failed: '
|
|
793
537
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
794
538
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
795
539
|
|
|
796
540
|
def _validate_result(result):
|
|
797
541
|
supported_result_types = (type(None), int, str, bool, float, dict, np.floating,
|
|
798
542
|
np.bool_, np.unsignedinteger, np.signedinteger, np.integer)
|
|
799
|
-
validate_output_structure(result, func_name=user_function.__name__,
|
|
800
|
-
expected_type_name=supported_result_types)
|
|
801
543
|
assert isinstance(result, supported_result_types), \
|
|
802
|
-
(f'
|
|
544
|
+
(f'tensorleap_metadata validation failed: '
|
|
803
545
|
f'Unsupported return type. Got {type(result)}. should be any of {str(supported_result_types)}')
|
|
804
546
|
if isinstance(result, dict):
|
|
805
547
|
for key, value in result.items():
|
|
806
548
|
assert isinstance(key, str), \
|
|
807
|
-
(f'
|
|
549
|
+
(f'tensorleap_metadata validation failed: '
|
|
808
550
|
f'Keys in the return dict should be of type str. Got {type(key)}.')
|
|
809
551
|
assert isinstance(value, supported_result_types), \
|
|
810
|
-
(f'
|
|
552
|
+
(f'tensorleap_metadata validation failed: '
|
|
811
553
|
f'Values in the return dict should be of type {str(supported_result_types)}. Got {type(value)}.')
|
|
812
554
|
|
|
813
555
|
def inner_without_validate(sample_id, preprocess_response):
|
|
@@ -824,19 +566,15 @@ def tensorleap_metadata(
|
|
|
824
566
|
|
|
825
567
|
leap_binder.set_metadata(inner_without_validate, name, metadata_type)
|
|
826
568
|
|
|
827
|
-
def inner(
|
|
569
|
+
def inner(sample_id, preprocess_response):
|
|
828
570
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
829
571
|
return None
|
|
830
|
-
|
|
831
|
-
func_name=user_function.__name__, expected_names=["idx", "preprocess"],**kwargs)
|
|
832
|
-
sample_id, preprocess_response = args if len(args)!=0 else kwargs.values()
|
|
572
|
+
|
|
833
573
|
_validate_input_args(sample_id, preprocess_response)
|
|
834
574
|
|
|
835
575
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
836
576
|
|
|
837
577
|
_validate_result(result)
|
|
838
|
-
if not _call_from_tl_platform:
|
|
839
|
-
update_env_params_func("tensorleap_metadata","v")
|
|
840
578
|
return result
|
|
841
579
|
|
|
842
580
|
return inner
|
|
@@ -898,24 +636,20 @@ def tensorleap_preprocess():
|
|
|
898
636
|
leap_binder.set_preprocess(user_function)
|
|
899
637
|
|
|
900
638
|
def _validate_input_args(*args, **kwargs):
|
|
901
|
-
assert len(args)
|
|
902
|
-
(f'
|
|
639
|
+
assert len(args) == 0 and len(kwargs) == 0, \
|
|
640
|
+
(f'tensorleap_preprocess validation failed: '
|
|
903
641
|
f'The function should not take any arguments. Got {args} and {kwargs}.')
|
|
904
642
|
|
|
905
643
|
def _validate_result(result):
|
|
906
|
-
assert isinstance(result, list),
|
|
907
|
-
f
|
|
908
|
-
|
|
909
|
-
if not isinstance(result, tuple)
|
|
910
|
-
else f"{user_function.__name__}() validation failed: expected to return a single list[{PreprocessResponse.__name__}] object, "
|
|
911
|
-
f"but returned {len(result)} objects instead."
|
|
912
|
-
)
|
|
644
|
+
assert isinstance(result, list), \
|
|
645
|
+
(f'tensorleap_preprocess validation failed: '
|
|
646
|
+
f'The return type should be a list. Got {type(result)}.')
|
|
913
647
|
for i, response in enumerate(result):
|
|
914
648
|
assert isinstance(response, PreprocessResponse), \
|
|
915
|
-
(f'
|
|
649
|
+
(f'tensorleap_preprocess validation failed: '
|
|
916
650
|
f'Element #{i} in the return list should be a PreprocessResponse. Got {type(response)}.')
|
|
917
651
|
assert len(set(result)) == len(result), \
|
|
918
|
-
(f'
|
|
652
|
+
(f'tensorleap_preprocess validation failed: '
|
|
919
653
|
f'The return list should not contain duplicate PreprocessResponse objects.')
|
|
920
654
|
|
|
921
655
|
def inner(*args, **kwargs):
|
|
@@ -923,6 +657,7 @@ def tensorleap_preprocess():
|
|
|
923
657
|
return [None, None, None, None]
|
|
924
658
|
|
|
925
659
|
_validate_input_args(*args, **kwargs)
|
|
660
|
+
|
|
926
661
|
result = user_function()
|
|
927
662
|
_validate_result(result)
|
|
928
663
|
|
|
@@ -933,8 +668,7 @@ def tensorleap_preprocess():
|
|
|
933
668
|
})
|
|
934
669
|
except Exception as e:
|
|
935
670
|
logger.debug(f"Failed to emit preprocess integration test event: {e}")
|
|
936
|
-
|
|
937
|
-
update_env_params_func("tensorleap_preprocess", "v")
|
|
671
|
+
|
|
938
672
|
return result
|
|
939
673
|
|
|
940
674
|
return inner
|
|
@@ -1133,23 +867,29 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1133
867
|
raise Exception(f"Channel dim for input {name} is expected to be either -1 or positive")
|
|
1134
868
|
|
|
1135
869
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
870
|
+
assert isinstance(sample_id, (int, str)), \
|
|
871
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
872
|
+
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
873
|
+
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
874
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
875
|
+
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
1136
876
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
1137
|
-
(f'
|
|
877
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
1138
878
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
1139
879
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
1140
880
|
|
|
1141
881
|
def _validate_result(result):
|
|
1142
|
-
validate_output_structure(result, func_name=user_function.__name__, expected_type_name = "np.ndarray")
|
|
1143
882
|
assert isinstance(result, np.ndarray), \
|
|
1144
|
-
(f'
|
|
883
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
1145
884
|
f'Unsupported return type. Should be a numpy array. Got {type(result)}.')
|
|
1146
885
|
assert result.dtype == np.float32, \
|
|
1147
|
-
(f'
|
|
886
|
+
(f'tensorleap_input_encoder validation failed: '
|
|
1148
887
|
f'The return type should be a numpy array of type float32. Got {result.dtype}.')
|
|
1149
|
-
assert channel_dim - 1 <= len(result.shape), (f'
|
|
888
|
+
assert channel_dim - 1 <= len(result.shape), (f'tensorleap_input_encoder validation failed: '
|
|
1150
889
|
f'The channel_dim ({channel_dim}) should be <= to the rank of the resulting input rank ({len(result.shape)}).')
|
|
1151
890
|
|
|
1152
891
|
def inner_without_validate(sample_id, preprocess_response):
|
|
892
|
+
|
|
1153
893
|
global _called_from_inside_tl_decorator
|
|
1154
894
|
_called_from_inside_tl_decorator += 1
|
|
1155
895
|
|
|
@@ -1163,10 +903,7 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1163
903
|
leap_binder.set_input(inner_without_validate, name, channel_dim=channel_dim)
|
|
1164
904
|
|
|
1165
905
|
|
|
1166
|
-
def inner(
|
|
1167
|
-
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
1168
|
-
func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
|
|
1169
|
-
sample_id, preprocess_response = args if len(args)!=0 else kwargs.values()
|
|
906
|
+
def inner(sample_id, preprocess_response):
|
|
1170
907
|
_validate_input_args(sample_id, preprocess_response)
|
|
1171
908
|
|
|
1172
909
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
@@ -1174,7 +911,6 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1174
911
|
_validate_result(result)
|
|
1175
912
|
|
|
1176
913
|
if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
|
|
1177
|
-
batch_warning(result,user_function.__name__)
|
|
1178
914
|
result = np.expand_dims(result, axis=0)
|
|
1179
915
|
# Emit integration test event once per test
|
|
1180
916
|
try:
|
|
@@ -1185,18 +921,17 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1185
921
|
})
|
|
1186
922
|
except Exception as e:
|
|
1187
923
|
logger.debug(f"Failed to emit input_encoder integration test event: {e}")
|
|
1188
|
-
if not _call_from_tl_platform:
|
|
1189
|
-
update_env_params_func("tensorleap_input_encoder", "v")
|
|
1190
924
|
|
|
1191
925
|
return result
|
|
1192
926
|
|
|
1193
927
|
|
|
928
|
+
|
|
1194
929
|
node_mapping_type = NodeMappingType.Input
|
|
1195
930
|
if model_input_index is not None:
|
|
1196
931
|
node_mapping_type = NodeMappingType(f'Input{str(model_input_index)}')
|
|
1197
932
|
inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
1198
933
|
|
|
1199
|
-
def mapping_inner(
|
|
934
|
+
def mapping_inner(sample_id, preprocess_response):
|
|
1200
935
|
class TempMapping:
|
|
1201
936
|
pass
|
|
1202
937
|
|
|
@@ -1208,11 +943,11 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
1208
943
|
|
|
1209
944
|
mapping_inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
1210
945
|
|
|
1211
|
-
def final_inner(
|
|
946
|
+
def final_inner(sample_id, preprocess_response):
|
|
1212
947
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
1213
|
-
return mapping_inner(
|
|
948
|
+
return mapping_inner(sample_id, preprocess_response)
|
|
1214
949
|
else:
|
|
1215
|
-
return inner(
|
|
950
|
+
return inner(sample_id, preprocess_response)
|
|
1216
951
|
|
|
1217
952
|
final_inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
1218
953
|
|
|
@@ -1229,18 +964,23 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1229
964
|
f'Please choose another')
|
|
1230
965
|
|
|
1231
966
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
967
|
+
assert isinstance(sample_id, (int, str)), \
|
|
968
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
969
|
+
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
970
|
+
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
971
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
972
|
+
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
1232
973
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
1233
|
-
(f'
|
|
974
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
1234
975
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
1235
976
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
1236
977
|
|
|
1237
978
|
def _validate_result(result):
|
|
1238
|
-
validate_output_structure(result, func_name=user_function.__name__, expected_type_name = "np.ndarray",gt_flag=True)
|
|
1239
979
|
assert isinstance(result, np.ndarray), \
|
|
1240
|
-
(f'
|
|
980
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
1241
981
|
f'Unsupported return type. Should be a numpy array. Got {type(result)}.')
|
|
1242
982
|
assert result.dtype == np.float32, \
|
|
1243
|
-
(f'
|
|
983
|
+
(f'tensorleap_gt_encoder validation failed: '
|
|
1244
984
|
f'The return type should be a numpy array of type float32. Got {result.dtype}.')
|
|
1245
985
|
|
|
1246
986
|
def inner_without_validate(sample_id, preprocess_response):
|
|
@@ -1257,10 +997,7 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1257
997
|
leap_binder.set_ground_truth(inner_without_validate, name)
|
|
1258
998
|
|
|
1259
999
|
|
|
1260
|
-
def inner(
|
|
1261
|
-
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
1262
|
-
func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
|
|
1263
|
-
sample_id, preprocess_response = args
|
|
1000
|
+
def inner(sample_id, preprocess_response):
|
|
1264
1001
|
_validate_input_args(sample_id, preprocess_response)
|
|
1265
1002
|
|
|
1266
1003
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
@@ -1268,7 +1005,6 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1268
1005
|
_validate_result(result)
|
|
1269
1006
|
|
|
1270
1007
|
if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
|
|
1271
|
-
batch_warning(result, user_function.__name__)
|
|
1272
1008
|
result = np.expand_dims(result, axis=0)
|
|
1273
1009
|
# Emit integration test event once per test
|
|
1274
1010
|
try:
|
|
@@ -1277,13 +1013,12 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1277
1013
|
})
|
|
1278
1014
|
except Exception as e:
|
|
1279
1015
|
logger.debug(f"Failed to emit gt_encoder integration test event: {e}")
|
|
1280
|
-
|
|
1281
|
-
update_env_params_func("tensorleap_gt_encoder", "v")
|
|
1016
|
+
|
|
1282
1017
|
return result
|
|
1283
1018
|
|
|
1284
1019
|
inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
1285
1020
|
|
|
1286
|
-
def mapping_inner(
|
|
1021
|
+
def mapping_inner(sample_id, preprocess_response):
|
|
1287
1022
|
class TempMapping:
|
|
1288
1023
|
pass
|
|
1289
1024
|
|
|
@@ -1294,11 +1029,11 @@ def tensorleap_gt_encoder(name: str):
|
|
|
1294
1029
|
|
|
1295
1030
|
mapping_inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
1296
1031
|
|
|
1297
|
-
def final_inner(
|
|
1032
|
+
def final_inner(sample_id, preprocess_response):
|
|
1298
1033
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
1299
|
-
return mapping_inner(
|
|
1034
|
+
return mapping_inner(sample_id, preprocess_response)
|
|
1300
1035
|
else:
|
|
1301
|
-
return inner(
|
|
1036
|
+
return inner(sample_id, preprocess_response)
|
|
1302
1037
|
|
|
1303
1038
|
final_inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
1304
1039
|
|
|
@@ -1319,37 +1054,28 @@ def tensorleap_custom_loss(name: str, connects_to=None):
|
|
|
1319
1054
|
valid_types = (np.ndarray, SamplePreprocessResponse)
|
|
1320
1055
|
|
|
1321
1056
|
def _validate_input_args(*args, **kwargs):
|
|
1322
|
-
assert len(args) + len(kwargs) > 0, (
|
|
1323
|
-
f"{user_function.__name__}() validation failed: "
|
|
1324
|
-
f"Expected at least one positional|key-word argument of the allowed types (np.ndarray|SamplePreprocessResponse|list(np.ndarray|SamplePreprocessResponse)). "
|
|
1325
|
-
f"but received none. "
|
|
1326
|
-
f"Correct usage example: {user_function.__name__}(input_array: np.ndarray, ...)"
|
|
1327
|
-
)
|
|
1328
1057
|
for i, arg in enumerate(args):
|
|
1329
1058
|
if isinstance(arg, list):
|
|
1330
1059
|
for y, elem in enumerate(arg):
|
|
1331
|
-
assert isinstance(elem, valid_types), (f'
|
|
1060
|
+
assert isinstance(elem, valid_types), (f'tensorleap_custom_loss validation failed: '
|
|
1332
1061
|
f'Element #{y} of list should be a numpy array. Got {type(elem)}.')
|
|
1333
1062
|
else:
|
|
1334
|
-
assert isinstance(arg, valid_types), (f'
|
|
1063
|
+
assert isinstance(arg, valid_types), (f'tensorleap_custom_loss validation failed: '
|
|
1335
1064
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
1336
1065
|
for _arg_name, arg in kwargs.items():
|
|
1337
1066
|
if isinstance(arg, list):
|
|
1338
1067
|
for y, elem in enumerate(arg):
|
|
1339
|
-
assert isinstance(elem, valid_types), (f'
|
|
1068
|
+
assert isinstance(elem, valid_types), (f'tensorleap_custom_loss validation failed: '
|
|
1340
1069
|
f'Element #{y} of list should be a numpy array. Got {type(elem)}.')
|
|
1341
1070
|
else:
|
|
1342
|
-
assert isinstance(arg, valid_types), (f'
|
|
1071
|
+
assert isinstance(arg, valid_types), (f'tensorleap_custom_loss validation failed: '
|
|
1343
1072
|
f'Argument #{_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
1344
1073
|
|
|
1345
1074
|
def _validate_result(result):
|
|
1346
|
-
validate_output_structure(result, func_name=user_function.__name__,
|
|
1347
|
-
expected_type_name="np.ndarray")
|
|
1348
1075
|
assert isinstance(result, np.ndarray), \
|
|
1349
|
-
(f'
|
|
1076
|
+
(f'tensorleap_custom_loss validation failed: '
|
|
1350
1077
|
f'The return type should be a numpy array. Got {type(result)}.')
|
|
1351
|
-
|
|
1352
|
-
f'The return type should be a 1Dim numpy array but got {result.ndim}Dim.')
|
|
1078
|
+
|
|
1353
1079
|
|
|
1354
1080
|
@functools.wraps(user_function)
|
|
1355
1081
|
def inner_without_validate(*args, **kwargs):
|
|
@@ -1380,9 +1106,6 @@ def tensorleap_custom_loss(name: str, connects_to=None):
|
|
|
1380
1106
|
result = inner_without_validate(*args, **kwargs)
|
|
1381
1107
|
|
|
1382
1108
|
_validate_result(result)
|
|
1383
|
-
if not _call_from_tl_platform:
|
|
1384
|
-
update_env_params_func("tensorleap_custom_loss", "v")
|
|
1385
|
-
|
|
1386
1109
|
return result
|
|
1387
1110
|
|
|
1388
1111
|
def mapping_inner(*args, **kwargs):
|
|
@@ -1439,98 +1162,3 @@ def tensorleap_custom_layer(name: str):
|
|
|
1439
1162
|
return custom_layer
|
|
1440
1163
|
|
|
1441
1164
|
return decorating_function
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
def tensorleap_status_table():
|
|
1445
|
-
'''
|
|
1446
|
-
Usage example:
|
|
1447
|
-
###################
|
|
1448
|
-
leap_integration.py
|
|
1449
|
-
###################
|
|
1450
|
-
from code_loader.inner_leap_binder.leapbinder_decorators import tensorleap_status_table
|
|
1451
|
-
...
|
|
1452
|
-
...
|
|
1453
|
-
...
|
|
1454
|
-
if __name__ == '__main__':
|
|
1455
|
-
tensorleap_status_table()
|
|
1456
|
-
...
|
|
1457
|
-
'''
|
|
1458
|
-
import atexit
|
|
1459
|
-
import sys
|
|
1460
|
-
import traceback
|
|
1461
|
-
CHECK = "✅"
|
|
1462
|
-
CROSS = "❌"
|
|
1463
|
-
code_mapping_failure=[0]
|
|
1464
|
-
table = [
|
|
1465
|
-
{"name": "tensorleap_preprocess", "Added to integration": CROSS},
|
|
1466
|
-
{"name": "tensorleap_integration_test", "Added to integration": CROSS},
|
|
1467
|
-
{"name": "tensorleap_input_encoder", "Added to integration": CROSS},
|
|
1468
|
-
{"name": "tensorleap_gt_encoder", "Added to integration": CROSS},
|
|
1469
|
-
{"name": "tensorleap_load_model", "Added to integration": CROSS},
|
|
1470
|
-
{"name": "tensorleap_custom_loss", "Added to integration": CROSS},
|
|
1471
|
-
{"name": "tensorleap_custom_metric (optional)", "Added to integration": CROSS},
|
|
1472
|
-
{"name": "tensorleap_metadata (optional)", "Added to integration": CROSS},
|
|
1473
|
-
{"name": "tensorleap_custom_visualizer (optional)", "Added to integration": CROSS},
|
|
1474
|
-
|
|
1475
|
-
]
|
|
1476
|
-
|
|
1477
|
-
_finalizer_called = {"done": False}
|
|
1478
|
-
|
|
1479
|
-
def _remove_suffix(s: str, suffix: str) -> str:
|
|
1480
|
-
#This is needed because str.remove_suffix was presented in python3.9+
|
|
1481
|
-
if suffix and s.endswith(suffix):
|
|
1482
|
-
return s[:-len(suffix)]
|
|
1483
|
-
return s
|
|
1484
|
-
|
|
1485
|
-
def _print_table():
|
|
1486
|
-
ready_mess = "\nAll parts have been successfully set. If no errors accured, you can now push the project to the Tensorleap system."
|
|
1487
|
-
not_ready_mess = "\nSome mandatory components have not yet been added to the Integration test. Recommended next interface to add is: "
|
|
1488
|
-
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 reccomeded interface,adding: "
|
|
1489
|
-
code_mapping_failure_mes= "Tensorleap_integration_test code flow failed, check raised exception."
|
|
1490
|
-
|
|
1491
|
-
name_width = max(len(row["name"]) for row in table)
|
|
1492
|
-
status_width = max(len(row["Added to integration"]) for row in table)
|
|
1493
|
-
header = f"{'Decorator Name'.ljust(name_width)} | {'Added to integration'.ljust(status_width)}"
|
|
1494
|
-
sep = "-" * len(header)
|
|
1495
|
-
print("\n" + header)
|
|
1496
|
-
print(sep)
|
|
1497
|
-
ready=True
|
|
1498
|
-
for row in table:
|
|
1499
|
-
print(f"{row['name'].ljust(name_width)} | {row['Added to integration'].ljust(status_width)}")
|
|
1500
|
-
if row['Added to integration']==CROSS and ready:
|
|
1501
|
-
ready=False
|
|
1502
|
-
next_step=row['name']
|
|
1503
|
-
|
|
1504
|
-
if code_mapping_failure:
|
|
1505
|
-
print(f"\n{ CROSS + code_mapping_failure_mes}.")
|
|
1506
|
-
else:
|
|
1507
|
-
print(ready_mess) if ready else print(mandatory_ready_mess+next_step) if "optional" in next_step else print(not_ready_mess+next_step)
|
|
1508
|
-
def update_env_params(name: str, status: str = "✓"):
|
|
1509
|
-
for row in table:
|
|
1510
|
-
if _remove_suffix(row["name"]," (optional)") == name:
|
|
1511
|
-
row["Added to integration"] = CHECK if status=="v" else CROSS
|
|
1512
|
-
break
|
|
1513
|
-
if name=="code_mapping":
|
|
1514
|
-
code_mapping_failure[0]=1
|
|
1515
|
-
def run_on_exit():
|
|
1516
|
-
if _finalizer_called["done"]:
|
|
1517
|
-
return
|
|
1518
|
-
_finalizer_called["done"] = True
|
|
1519
|
-
_print_table()
|
|
1520
|
-
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
1521
|
-
traceback.print_exception(exc_type, exc_value, exc_traceback)
|
|
1522
|
-
run_on_exit()
|
|
1523
|
-
atexit.register(run_on_exit)
|
|
1524
|
-
sys.excepthook = handle_exception
|
|
1525
|
-
return update_env_params
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
if not _call_from_tl_platform:
|
|
1529
|
-
update_env_params_func = tensorleap_status_table()
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.146 → code_loader-1.0.147}/code_loader/experiment_api/experiment_context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.146 → code_loader-1.0.147}/code_loader/experiment_api/workingspace_config_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|