code-loader 1.0.196.dev0__py3-none-any.whl → 1.0.196.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- code_loader/inner_leap_binder/leapbinder.py +47 -3
- code_loader/inner_leap_binder/leapbinder_decorators.py +16 -11
- code_loader/leaploader.py +0 -2
- code_loader/utils.py +29 -21
- {code_loader-1.0.196.dev0.dist-info → code_loader-1.0.196.dev1.dist-info}/METADATA +1 -1
- {code_loader-1.0.196.dev0.dist-info → code_loader-1.0.196.dev1.dist-info}/RECORD +8 -8
- {code_loader-1.0.196.dev0.dist-info → code_loader-1.0.196.dev1.dist-info}/LICENSE +0 -0
- {code_loader-1.0.196.dev0.dist-info → code_loader-1.0.196.dev1.dist-info}/WHEEL +0 -0
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
|
|
2
|
+
import builtins
|
|
2
3
|
import inspect
|
|
3
|
-
|
|
4
|
+
import os
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
from typing import Callable, List, Optional, Dict, Any, Type, Union, get_args, cast, Iterator, Set
|
|
4
7
|
|
|
5
8
|
import numpy as np
|
|
6
9
|
import numpy.typing as npt
|
|
@@ -16,7 +19,8 @@ from code_loader.contract.datasetclasses import SectionCallableInterface, InputH
|
|
|
16
19
|
SimulationHandler, _simulation_context, AutoregressiveStepHandler, AutoregressiveStepCallableInterface, \
|
|
17
20
|
AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS, AUTOREGRESSIVE_IMPLICIT_ARG_NAMES, \
|
|
18
21
|
AutoregressiveMetricHandler, AutoregressiveLossHandler, AutoregressiveVisualizerHandler
|
|
19
|
-
from code_loader.contract.enums import LeapDataType, DataStateEnum, DataStateType, MetricDirection, DatasetMetadataType
|
|
22
|
+
from code_loader.contract.enums import LeapDataType, DataStateEnum, DataStateType, MetricDirection, DatasetMetadataType, \
|
|
23
|
+
TestingSectionEnum
|
|
20
24
|
from code_loader.contract.mapping import NodeConnection, NodeMapping, NodeMappingType
|
|
21
25
|
from code_loader.contract.responsedataclasses import DatasetTestResultPayload, LeapAnalysisConfiguration
|
|
22
26
|
from code_loader.contract.visualizer_classes import map_leap_data_type_to_visualizer_class
|
|
@@ -33,6 +37,25 @@ from code_loader.visualizers.default_visualizers import DefaultVisualizer, \
|
|
|
33
37
|
mapping_runtime_mode_env_var_mame = '__MAPPING_RUNTIME_MODE__'
|
|
34
38
|
|
|
35
39
|
|
|
40
|
+
@contextmanager
|
|
41
|
+
def _track_opened_files() -> Iterator[Set[str]]:
|
|
42
|
+
opened: Set[str] = set()
|
|
43
|
+
original_open = builtins.open
|
|
44
|
+
|
|
45
|
+
def tracking_open(file: Any, *args: Any, **kwargs: Any) -> Any:
|
|
46
|
+
mode = args[0] if args else kwargs.get('mode', 'r')
|
|
47
|
+
is_read_mode = isinstance(mode, str) and not any(c in mode for c in ('a', 'w', 'x'))
|
|
48
|
+
if is_read_mode and isinstance(file, (str, os.PathLike)):
|
|
49
|
+
opened.add(os.fspath(file))
|
|
50
|
+
return original_open(file, *args, **kwargs)
|
|
51
|
+
|
|
52
|
+
builtins.open = tracking_open
|
|
53
|
+
try:
|
|
54
|
+
yield opened
|
|
55
|
+
finally:
|
|
56
|
+
builtins.open = original_open
|
|
57
|
+
|
|
58
|
+
|
|
36
59
|
def _stringized_annotation_type_name(annotation: Any) -> Optional[str]:
|
|
37
60
|
"""Bare type name if ``annotation`` is a stringized annotation (from ``from __future__
|
|
38
61
|
import annotations`` or a quoted hint), else ``None``. code_loader inspects raw
|
|
@@ -744,15 +767,34 @@ class LeapBinder:
|
|
|
744
767
|
preprocess_response: PreprocessResponse, test_result: List[DatasetTestResultPayload],
|
|
745
768
|
dataset_base_handler: Union[DatasetBaseHandler, MetadataHandler], state: DataStateEnum) -> List[DatasetTestResultPayload]:
|
|
746
769
|
assert preprocess_response.sample_ids is not None
|
|
770
|
+
opened_files: Optional[Set[str]] = None
|
|
747
771
|
if preprocess_response.is_grouped:
|
|
748
772
|
# Grouped: probe with the first group, then reduce to a single sample's result so the
|
|
749
773
|
# recorded shape/type is per-sample (matching the flat case), not the (B, *) batch.
|
|
750
774
|
# (casts: sample_ids[0] is a group list here, and the grouped result is a per-sample list.)
|
|
751
775
|
group = preprocess_response.sample_ids[0]
|
|
752
|
-
|
|
776
|
+
with _track_opened_files() as opened_files:
|
|
777
|
+
raw_result = cast(Any, dataset_base_handler.function(cast(Any, group), preprocess_response))[0]
|
|
753
778
|
else:
|
|
754
779
|
raw_result = dataset_base_handler.function(
|
|
755
780
|
cast(Union[int, str], preprocess_response.sample_ids[0]), preprocess_response)
|
|
781
|
+
|
|
782
|
+
def _warn_if_group_spans_multiple_files(payloads: List[DatasetTestResultPayload]) -> None:
|
|
783
|
+
if opened_files is None or len(opened_files) <= 1:
|
|
784
|
+
return
|
|
785
|
+
shown = sorted(opened_files)[:5]
|
|
786
|
+
suffix = f" (+{len(opened_files) - 5} more)" if len(opened_files) > 5 else ""
|
|
787
|
+
warning = (
|
|
788
|
+
f"Encoding declared group 0 (size {len(cast(List[Any], group))}) for '{dataset_base_handler.name}' opened "
|
|
789
|
+
f"{len(opened_files)} distinct files: {shown}{suffix}. If this group is meant to be one "
|
|
790
|
+
f"physical source (e.g. one Parquet file), it may be grouped incorrectly - check your "
|
|
791
|
+
f"preprocess grouping logic. (Only files opened via Python's open() are tracked, so this "
|
|
792
|
+
f"can miss other I/O paths or be a false positive if grouping isn't meant to reflect file "
|
|
793
|
+
f"locality.)")
|
|
794
|
+
for payload in payloads:
|
|
795
|
+
existing = payload.display.get(TestingSectionEnum.Errors.name, '')
|
|
796
|
+
payload.display[TestingSectionEnum.Errors.name] = (existing + '\n' if existing else '') + warning
|
|
797
|
+
|
|
756
798
|
handler_type = 'metadata' if isinstance(dataset_base_handler, MetadataHandler) else None
|
|
757
799
|
if isinstance(dataset_base_handler, MetadataHandler):
|
|
758
800
|
if isinstance(raw_result, dict):
|
|
@@ -792,6 +834,7 @@ class LeapBinder:
|
|
|
792
834
|
else:
|
|
793
835
|
if raw_result is None:
|
|
794
836
|
if state != DataStateEnum.training:
|
|
837
|
+
_warn_if_group_spans_multiple_files(test_result)
|
|
795
838
|
return test_result
|
|
796
839
|
|
|
797
840
|
if dataset_base_handler.metadata_type is None:
|
|
@@ -813,6 +856,7 @@ class LeapBinder:
|
|
|
813
856
|
# setting shape in setup for all encoders
|
|
814
857
|
if isinstance(dataset_base_handler, (InputHandler, GroundTruthHandler)):
|
|
815
858
|
dataset_base_handler.shape = result_shape
|
|
859
|
+
_warn_if_group_spans_multiple_files(test_result)
|
|
816
860
|
return test_result
|
|
817
861
|
|
|
818
862
|
def check_handlers(self, preprocess_result: Dict[DataStateEnum, PreprocessResponse]) -> None:
|
|
@@ -2010,9 +2010,10 @@ def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step'):
|
|
|
2010
2010
|
state returned by the previous call, and return the next step's full input dict together with
|
|
2011
2011
|
the updated state; returning (None, state) ends the chain — the terminating call still
|
|
2012
2012
|
returns state, so the final step participates in state aggregation. State is never fed to
|
|
2013
|
-
the model;
|
|
2014
|
-
|
|
2015
|
-
|
|
2013
|
+
the model; any picklable nest of builtin/numpy values works (dicts, lists, tuples, sets,
|
|
2014
|
+
numbers, strings, arrays — not user-defined classes, lambdas or open resources, since the
|
|
2015
|
+
platform deserializes state without the integration code), and it rides the platform queue
|
|
2016
|
+
on every step — accumulate reductions, not raw per-step tensors. The hook must be stateless and deterministically seeded (seed stochasticity from
|
|
2016
2017
|
sample_id) — the engine replays steps after crash recovery and relies on identical results.
|
|
2017
2018
|
|
|
2018
2019
|
latent_space_aggregation ('last_step' | 'mean') declares how the chain's latent-space
|
|
@@ -3114,10 +3115,12 @@ def tensorleap_input_encoder(name: str, channel_dim=_UNSET, model_input_index=No
|
|
|
3114
3115
|
if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
|
|
3115
3116
|
if grouped:
|
|
3116
3117
|
# A grouped result is a list of per-sample arrays (never stacked, so a
|
|
3117
|
-
# B=1-only model can be fed one sample at a time).
|
|
3118
|
-
#
|
|
3119
|
-
|
|
3120
|
-
|
|
3118
|
+
# B=1-only model can be fed one sample at a time). A user may also return a
|
|
3119
|
+
# supported (B, *) array; split it back into per-sample rows first (mirrors
|
|
3120
|
+
# LeapLoader._to_grouped_list) so both forms match the runtime path. Then add
|
|
3121
|
+
# a batch dim to each sample, mirroring the flat path's single-sample expand_dims.
|
|
3122
|
+
rows = result if isinstance(result, list) else [row for row in np.asarray(result)]
|
|
3123
|
+
result = [np.expand_dims(r, axis=0) for r in rows]
|
|
3121
3124
|
else:
|
|
3122
3125
|
batch_warning(result, user_function.__name__)
|
|
3123
3126
|
result = np.expand_dims(result, axis=0)
|
|
@@ -3228,10 +3231,12 @@ def tensorleap_gt_encoder(name: str):
|
|
|
3228
3231
|
if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
|
|
3229
3232
|
if grouped:
|
|
3230
3233
|
# A grouped result is a list of per-sample arrays (never stacked, so a
|
|
3231
|
-
# B=1-only model can be fed one sample at a time).
|
|
3232
|
-
#
|
|
3233
|
-
|
|
3234
|
-
|
|
3234
|
+
# B=1-only model can be fed one sample at a time). A user may also return a
|
|
3235
|
+
# supported (B, *) array; split it back into per-sample rows first (mirrors
|
|
3236
|
+
# LeapLoader._to_grouped_list) so both forms match the runtime path. Then add
|
|
3237
|
+
# a batch dim to each sample, mirroring the flat path's single-sample expand_dims.
|
|
3238
|
+
rows = result if isinstance(result, list) else [row for row in np.asarray(result)]
|
|
3239
|
+
result = [np.expand_dims(r, axis=0) for r in rows]
|
|
3235
3240
|
else:
|
|
3236
3241
|
batch_warning(result, user_function.__name__)
|
|
3237
3242
|
result = np.expand_dims(result, axis=0)
|
code_loader/leaploader.py
CHANGED
|
@@ -77,8 +77,6 @@ class LeapLoader(LeapLoaderBase):
|
|
|
77
77
|
preprocess_result = global_leap_binder.get_preprocess_result()
|
|
78
78
|
self._preprocess_result_cached = preprocess_result
|
|
79
79
|
is_grouped = any(r.is_grouped for r in preprocess_result.values())
|
|
80
|
-
except Exception:
|
|
81
|
-
is_grouped = False
|
|
82
80
|
finally:
|
|
83
81
|
os.environ[mapping_runtime_mode_env_var_mame] = 'TRUE'
|
|
84
82
|
|
code_loader/utils.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import io
|
|
1
2
|
import math
|
|
3
|
+
import pickle
|
|
2
4
|
import sys
|
|
3
5
|
from pathlib import Path
|
|
4
6
|
from types import TracebackType
|
|
@@ -15,10 +17,12 @@ from code_loader.contract.enums import DatasetMetadataType
|
|
|
15
17
|
def to_numpy_return_wrapper(encoder_function: SectionCallableInterface) -> SectionCallableInterface:
|
|
16
18
|
def numpy_encoder_function(idx: Union[int, str], samples: PreprocessResponse) -> npt.NDArray[np.float32]:
|
|
17
19
|
result = encoder_function(idx, samples)
|
|
18
|
-
if isinstance(
|
|
19
|
-
|
|
20
|
-
#
|
|
21
|
-
#
|
|
20
|
+
if isinstance(idx, list) and isinstance(result, list) and len(result) > 0 \
|
|
21
|
+
and all(isinstance(sample, np.ndarray) for sample in result):
|
|
22
|
+
# Grouped call (idx is a list of sample ids): keep the per-sample list, never stack
|
|
23
|
+
# it into a (B, *) batch — grouping is only a storage read-unit; batching the group to
|
|
24
|
+
# the model's B is the engine's single responsibility. Gate on the call shape (idx is a
|
|
25
|
+
# list), not the result shape, so a flat encoder returning a list of arrays still stacks.
|
|
22
26
|
return result
|
|
23
27
|
numpy_result: npt.NDArray[np.float32] = np.array(result)
|
|
24
28
|
return numpy_result
|
|
@@ -109,27 +113,31 @@ def get_metadata_type_from_variable(variable: Union[Optional[str], int, bool, Op
|
|
|
109
113
|
|
|
110
114
|
|
|
111
115
|
|
|
112
|
-
|
|
116
|
+
# The platform queue transports state as pickled payloads which the engine deserializes
|
|
117
|
+
# WITHOUT the integration code loaded, so a class defined in the user's modules round-trips
|
|
118
|
+
# locally but crashes on the engine. Only modules importable on the engine may resolve.
|
|
119
|
+
_STATE_SAFE_PICKLE_MODULES = ('builtins', 'copyreg', 'collections', 'numpy', 'datetime')
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class _EngineSafeUnpickler(pickle.Unpickler):
|
|
123
|
+
def find_class(self, module: str, name: str) -> Any:
|
|
124
|
+
if module.split('.')[0] in _STATE_SAFE_PICKLE_MODULES:
|
|
125
|
+
return super().find_class(module, name)
|
|
126
|
+
raise pickle.UnpicklingError(
|
|
127
|
+
f'{module}.{name} is defined in integration code, which is not importable on the '
|
|
128
|
+
f'platform engine')
|
|
113
129
|
|
|
114
130
|
|
|
115
131
|
def validate_autoregressive_state_types(value: Any, path: str = 'state') -> None:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
raise AssertionError(
|
|
120
|
-
f'autoregressive state validation failed: dict key {key!r} at {path} must be '
|
|
121
|
-
f'a string. Got {type(key).__name__}.')
|
|
122
|
-
validate_autoregressive_state_types(item, f'{path}[{key!r}]')
|
|
123
|
-
return
|
|
124
|
-
if isinstance(value, (list, tuple)):
|
|
125
|
-
for i, item in enumerate(value):
|
|
126
|
-
validate_autoregressive_state_types(item, f'{path}[{i}]')
|
|
127
|
-
return
|
|
128
|
-
if not isinstance(value, AUTOREGRESSIVE_STATE_LEAF_TYPES):
|
|
132
|
+
try:
|
|
133
|
+
_EngineSafeUnpickler(io.BytesIO(pickle.dumps(value))).load()
|
|
134
|
+
except Exception as e:
|
|
129
135
|
raise AssertionError(
|
|
130
|
-
f'autoregressive state validation failed: {path}
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
f'autoregressive state validation failed: {path} is not serializable ({e}). State '
|
|
137
|
+
'is serialized to the platform queue on every chain step and deserialized without '
|
|
138
|
+
'the integration code — any picklable nest of builtin/numpy values works (dicts, '
|
|
139
|
+
'lists, tuples, sets, numbers, strings, arrays), but user-defined classes, lambdas '
|
|
140
|
+
'and open resources do not.') from e
|
|
133
141
|
|
|
134
142
|
|
|
135
143
|
def autoregressive_nests_equal(a: Any, b: Any) -> bool:
|
|
@@ -21,18 +21,18 @@ code_loader/experiment_api/types.py,sha256=MY8xFARHwdVA7p4dxyhD60ShmttgTvb4qdp1o
|
|
|
21
21
|
code_loader/experiment_api/utils.py,sha256=XZHtxge12TS4H4-8PjV3sKuhp8Ud6ojAiIzTZJEqBqc,3304
|
|
22
22
|
code_loader/experiment_api/workingspace_config_utils.py,sha256=DLzXQCg4dgTV_YgaSbeTVzq-2ja_SQw4zi7LXwKL9cY,990
|
|
23
23
|
code_loader/inner_leap_binder/__init__.py,sha256=koOlJyMNYzGbEsoIbXathSmQ-L38N_pEXH_HvL7beXU,99
|
|
24
|
-
code_loader/inner_leap_binder/leapbinder.py,sha256=
|
|
25
|
-
code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=
|
|
26
|
-
code_loader/leaploader.py,sha256=
|
|
24
|
+
code_loader/inner_leap_binder/leapbinder.py,sha256=yW9EBA4E7YwWoWaiVELWoSP9uWTQjnPl5PfLbmX4cFk,56617
|
|
25
|
+
code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=GyuyffnSmkELj63q_NBAxa6Z0szP6MsaNxDodwCo-pE,183746
|
|
26
|
+
code_loader/leaploader.py,sha256=yWzSc-ynm_ykfup_tk8mwZX3TFq1ZW-fN18fEDXOrfc,83386
|
|
27
27
|
code_loader/leaploaderbase.py,sha256=PvBU_2OQqBfJLDMsbK1s372954eYr4Y3O4r18y5S7uY,10739
|
|
28
28
|
code_loader/mixpanel_tracker.py,sha256=rNwRmFifNbdUoqLQvvhhgpKczWpWiEmd8MfyJe27sxw,9131
|
|
29
29
|
code_loader/plot_functions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
30
|
code_loader/plot_functions/plot_functions.py,sha256=2DC-zlVaN13P4VNx5d8csgs80C6SisaeP1-Kq2LW7iM,16075
|
|
31
31
|
code_loader/plot_functions/visualize.py,sha256=gsBAYYkwMh7jIpJeDMPS8G4CW-pxwx6LznoQIvi4vpo,657
|
|
32
|
-
code_loader/utils.py,sha256=
|
|
32
|
+
code_loader/utils.py,sha256=Grrp8OLagrVAOYjt83DDmE0CPfjE22DuOQftgqDASyU,7215
|
|
33
33
|
code_loader/visualizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
34
|
code_loader/visualizers/default_visualizers.py,sha256=onRnLE_TXfgLN4o52hQIOOhUcFexGlqJ3xSpQDVLuZM,2604
|
|
35
|
-
code_loader-1.0.196.
|
|
36
|
-
code_loader-1.0.196.
|
|
37
|
-
code_loader-1.0.196.
|
|
38
|
-
code_loader-1.0.196.
|
|
35
|
+
code_loader-1.0.196.dev1.dist-info/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
|
|
36
|
+
code_loader-1.0.196.dev1.dist-info/METADATA,sha256=qjJUAz8M-nUFhOQa1jAFKQXk2Qm-pdh4zns9jWNEglY,1095
|
|
37
|
+
code_loader-1.0.196.dev1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
38
|
+
code_loader-1.0.196.dev1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|