code-loader 1.0.193.dev4__py3-none-any.whl → 1.0.195.dev0__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_decorators.py +11 -20
- code_loader/leaploader.py +33 -9
- code_loader/leaploaderbase.py +7 -2
- code_loader/utils.py +23 -17
- {code_loader-1.0.193.dev4.dist-info → code_loader-1.0.195.dev0.dist-info}/METADATA +1 -1
- {code_loader-1.0.193.dev4.dist-info → code_loader-1.0.195.dev0.dist-info}/RECORD +8 -8
- {code_loader-1.0.193.dev4.dist-info → code_loader-1.0.195.dev0.dist-info}/LICENSE +0 -0
- {code_loader-1.0.193.dev4.dist-info → code_loader-1.0.195.dev0.dist-info}/WHEEL +0 -0
|
@@ -1730,6 +1730,8 @@ def _ndarray_leaves(value):
|
|
|
1730
1730
|
|
|
1731
1731
|
|
|
1732
1732
|
def _squeeze_leading_batch_axis(tensors_dict):
|
|
1733
|
+
if tensors_dict is None:
|
|
1734
|
+
return None
|
|
1733
1735
|
squeezed = {}
|
|
1734
1736
|
for key, value in tensors_dict.items():
|
|
1735
1737
|
if isinstance(value, np.ndarray) and value.ndim > 0 and value.shape[0] == 1:
|
|
@@ -1931,9 +1933,10 @@ def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step'):
|
|
|
1931
1933
|
state returned by the previous call, and return the next step's full input dict together with
|
|
1932
1934
|
the updated state; returning (None, state) ends the chain — the terminating call still
|
|
1933
1935
|
returns state, so the final step participates in state aggregation. State is never fed to
|
|
1934
|
-
the model;
|
|
1935
|
-
|
|
1936
|
-
|
|
1936
|
+
the model; any picklable nest of builtin/numpy values works (dicts, lists, tuples, sets,
|
|
1937
|
+
numbers, strings, arrays — not user-defined classes, lambdas or open resources, since the
|
|
1938
|
+
platform deserializes state without the integration code), and it rides the platform queue
|
|
1939
|
+
on every step — accumulate reductions, not raw per-step tensors. The hook must be stateless and deterministically seeded (seed stochasticity from
|
|
1937
1940
|
sample_id) — the engine replays steps after crash recovery and relies on identical results.
|
|
1938
1941
|
|
|
1939
1942
|
latent_space_aggregation ('last_step' | 'mean') declares how the chain's latent-space
|
|
@@ -2077,21 +2080,6 @@ def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step'):
|
|
|
2077
2080
|
assert _nest_equal(value, second_inputs[key]), error_message
|
|
2078
2081
|
assert _nest_equal(first_state, second_state), error_message
|
|
2079
2082
|
|
|
2080
|
-
def _squeeze_test_batch_dim(tensors_dict):
|
|
2081
|
-
# Inside the integration test the model works on batch-1 tensors (this wrapper adds the
|
|
2082
|
-
# batch axis to returned inputs, and model outputs come back batched). The user's hook
|
|
2083
|
-
# body must see the same unbatched per-sample tensors it will see at engine runtime, so
|
|
2084
|
-
# strip the leading batch-1 axis before calling it.
|
|
2085
|
-
if tensors_dict is None:
|
|
2086
|
-
return None
|
|
2087
|
-
squeezed = {}
|
|
2088
|
-
for key, value in tensors_dict.items():
|
|
2089
|
-
if isinstance(value, np.ndarray) and value.ndim > 0 and value.shape[0] == 1:
|
|
2090
|
-
squeezed[key] = value[0]
|
|
2091
|
-
else:
|
|
2092
|
-
squeezed[key] = value
|
|
2093
|
-
return squeezed
|
|
2094
|
-
|
|
2095
2083
|
def inner_without_validate(sample_id, prev_inputs, prev_outputs, state, preprocess_response):
|
|
2096
2084
|
global _called_from_inside_tl_decorator
|
|
2097
2085
|
_called_from_inside_tl_decorator += 1
|
|
@@ -2129,8 +2117,11 @@ def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step'):
|
|
|
2129
2117
|
loop_context.on_hook_call(sample_id, prev_inputs, prev_outputs, state,
|
|
2130
2118
|
preprocess_response)
|
|
2131
2119
|
if is_top_level_in_test:
|
|
2132
|
-
|
|
2133
|
-
|
|
2120
|
+
# The wrapper adds the batch axis to returned inputs and model outputs come back
|
|
2121
|
+
# batched; the hook body must see the same unbatched per-sample tensors it will
|
|
2122
|
+
# see at engine runtime.
|
|
2123
|
+
prev_inputs = _squeeze_leading_batch_axis(prev_inputs)
|
|
2124
|
+
prev_outputs = _squeeze_leading_batch_axis(prev_outputs)
|
|
2134
2125
|
|
|
2135
2126
|
_validate_input_args(sample_id, prev_inputs, prev_outputs, state, preprocess_response)
|
|
2136
2127
|
|
code_loader/leaploader.py
CHANGED
|
@@ -581,8 +581,8 @@ class LeapLoader(LeapLoaderBase):
|
|
|
581
581
|
return handler.input_shapes
|
|
582
582
|
|
|
583
583
|
def run_simulation(self, sim_name, params=None, n_samples=1, seed=0,
|
|
584
|
-
sample_ids=None, extend_preprocess=True):
|
|
585
|
-
# type: (str, Optional[Dict[str, Any]], int, int, Optional[List[str]], bool) -> Dict[str, Any]
|
|
584
|
+
sample_ids=None, extend_preprocess=True, allow_partial=False):
|
|
585
|
+
# type: (str, Optional[Dict[str, Any]], int, int, Optional[List[str]], bool, bool) -> Dict[str, Any]
|
|
586
586
|
# extend_preprocess=True (default): also extend preprocess_result[additional] with the
|
|
587
587
|
# new synthetic sample_ids (producer-side behavior — synthetic worker needs this for
|
|
588
588
|
# enumeration / data_length tracking). Pass False from consumer-side populators that
|
|
@@ -609,19 +609,30 @@ class LeapLoader(LeapLoaderBase):
|
|
|
609
609
|
for sample_id in original_sample_ids:
|
|
610
610
|
for handler in global_leap_binder.setup_container.inputs:
|
|
611
611
|
per_encoder[handler.name].append(handler.function(sample_id, sim_preprocess))
|
|
612
|
-
encoded = {
|
|
612
|
+
encoded = {
|
|
613
|
+
name: np.stack(arrays) if arrays else np.empty((0,), dtype=np.float32)
|
|
614
|
+
for name, arrays in per_encoder.items()
|
|
615
|
+
}
|
|
613
616
|
if sample_ids is not None:
|
|
614
|
-
if len(sample_ids) != len(original_sample_ids):
|
|
615
|
-
raise ValueError(
|
|
616
|
-
"sample_ids length ({}) does not match simulation output length ({})".format(
|
|
617
|
-
len(sample_ids), len(original_sample_ids)
|
|
618
|
-
)
|
|
619
|
-
)
|
|
620
617
|
for sid in sample_ids:
|
|
621
618
|
if not isinstance(sid, str):
|
|
622
619
|
raise TypeError(
|
|
623
620
|
"All sample_ids must be of type str. Got: {}".format(type(sid))
|
|
624
621
|
)
|
|
622
|
+
if len(sample_ids) != len(original_sample_ids):
|
|
623
|
+
if not allow_partial:
|
|
624
|
+
raise ValueError(
|
|
625
|
+
"sample_ids length ({}) does not match simulation output length ({})".format(
|
|
626
|
+
len(sample_ids), len(original_sample_ids)
|
|
627
|
+
)
|
|
628
|
+
)
|
|
629
|
+
n_bound = min(len(sample_ids), len(original_sample_ids))
|
|
630
|
+
sample_ids = list(sample_ids)[:n_bound]
|
|
631
|
+
original_sample_ids = original_sample_ids[:n_bound]
|
|
632
|
+
# Over-generation trims sample_ids/original_sample_ids above but encoded was
|
|
633
|
+
# stacked from the full simulation output; slice it too so the encoded batch dim
|
|
634
|
+
# stays 1:1 with the returned sample_ids.
|
|
635
|
+
encoded = {name: arr[:n_bound] for name, arr in encoded.items()}
|
|
625
636
|
for synth_id, original_local_id in zip(sample_ids, original_sample_ids):
|
|
626
637
|
self._synthetic_lookup[synth_id] = (sim_preprocess, original_local_id)
|
|
627
638
|
if extend_preprocess:
|
|
@@ -631,6 +642,19 @@ class LeapLoader(LeapLoaderBase):
|
|
|
631
642
|
returned_sample_ids = original_sample_ids
|
|
632
643
|
return {"encoded": encoded, "sample_ids": returned_sample_ids}
|
|
633
644
|
|
|
645
|
+
def prune_synthetic_lookup(self, keep_ids):
|
|
646
|
+
# type: (List[str]) -> None
|
|
647
|
+
# Keep only the given synthetic sample_ids in the in-memory lookup and
|
|
648
|
+
# drop the rest, so preprocess responses don't accumulate across many
|
|
649
|
+
# run_simulation calls (e.g. a synthetic calibration loop keeps only its
|
|
650
|
+
# running top-K trials). Keep-set semantics (rather than evict-list) so
|
|
651
|
+
# the caller can bound the lookup to a known-good set each iteration
|
|
652
|
+
# without tracking everything it ever generated.
|
|
653
|
+
keep = set(keep_ids)
|
|
654
|
+
self._synthetic_lookup = {
|
|
655
|
+
sid: entry for sid, entry in self._synthetic_lookup.items() if sid in keep
|
|
656
|
+
}
|
|
657
|
+
|
|
634
658
|
def _extend_additional_preprocess(self, new_sample_ids: List[str]) -> None:
|
|
635
659
|
if self._preprocess_result_cached is None:
|
|
636
660
|
self._preprocess_result()
|
code_loader/leaploaderbase.py
CHANGED
|
@@ -223,8 +223,13 @@ class LeapLoaderBase:
|
|
|
223
223
|
pass
|
|
224
224
|
|
|
225
225
|
@abstractmethod
|
|
226
|
-
def run_simulation(self, sim_name, params=None, n_samples=1, seed=0, sample_ids=None
|
|
227
|
-
|
|
226
|
+
def run_simulation(self, sim_name, params=None, n_samples=1, seed=0, sample_ids=None,
|
|
227
|
+
extend_preprocess=True, allow_partial=False):
|
|
228
|
+
# type: (str, Optional[Dict[str, Any]], int, int, Optional[List[str]], bool, bool) -> Dict[str, Any]
|
|
229
|
+
pass
|
|
230
|
+
|
|
231
|
+
def prune_synthetic_lookup(self, keep_ids):
|
|
232
|
+
# type: (List[str]) -> None
|
|
228
233
|
pass
|
|
229
234
|
|
|
230
235
|
def is_custom_latent_space(self) -> bool:
|
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
|
|
@@ -104,27 +106,31 @@ def get_metadata_type_from_variable(variable: Union[Optional[str], int, bool, Op
|
|
|
104
106
|
|
|
105
107
|
|
|
106
108
|
|
|
107
|
-
|
|
109
|
+
# The platform queue transports state as pickled payloads which the engine deserializes
|
|
110
|
+
# WITHOUT the integration code loaded, so a class defined in the user's modules round-trips
|
|
111
|
+
# locally but crashes on the engine. Only modules importable on the engine may resolve.
|
|
112
|
+
_STATE_SAFE_PICKLE_MODULES = ('builtins', 'copyreg', 'collections', 'numpy', 'datetime')
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class _EngineSafeUnpickler(pickle.Unpickler):
|
|
116
|
+
def find_class(self, module: str, name: str) -> Any:
|
|
117
|
+
if module.split('.')[0] in _STATE_SAFE_PICKLE_MODULES:
|
|
118
|
+
return super().find_class(module, name)
|
|
119
|
+
raise pickle.UnpicklingError(
|
|
120
|
+
f'{module}.{name} is defined in integration code, which is not importable on the '
|
|
121
|
+
f'platform engine')
|
|
108
122
|
|
|
109
123
|
|
|
110
124
|
def validate_autoregressive_state_types(value: Any, path: str = 'state') -> None:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
raise AssertionError(
|
|
115
|
-
f'autoregressive state validation failed: dict key {key!r} at {path} must be '
|
|
116
|
-
f'a string. Got {type(key).__name__}.')
|
|
117
|
-
validate_autoregressive_state_types(item, f'{path}[{key!r}]')
|
|
118
|
-
return
|
|
119
|
-
if isinstance(value, (list, tuple)):
|
|
120
|
-
for i, item in enumerate(value):
|
|
121
|
-
validate_autoregressive_state_types(item, f'{path}[{i}]')
|
|
122
|
-
return
|
|
123
|
-
if not isinstance(value, AUTOREGRESSIVE_STATE_LEAF_TYPES):
|
|
125
|
+
try:
|
|
126
|
+
_EngineSafeUnpickler(io.BytesIO(pickle.dumps(value))).load()
|
|
127
|
+
except Exception as e:
|
|
124
128
|
raise AssertionError(
|
|
125
|
-
f'autoregressive state validation failed: {path}
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
f'autoregressive state validation failed: {path} is not serializable ({e}). State '
|
|
130
|
+
'is serialized to the platform queue on every chain step and deserialized without '
|
|
131
|
+
'the integration code — any picklable nest of builtin/numpy values works (dicts, '
|
|
132
|
+
'lists, tuples, sets, numbers, strings, arrays), but user-defined classes, lambdas '
|
|
133
|
+
'and open resources do not.') from e
|
|
128
134
|
|
|
129
135
|
|
|
130
136
|
def autoregressive_nests_equal(a: Any, b: Any) -> bool:
|
|
@@ -22,17 +22,17 @@ code_loader/experiment_api/utils.py,sha256=XZHtxge12TS4H4-8PjV3sKuhp8Ud6ojAiIzTZ
|
|
|
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
24
|
code_loader/inner_leap_binder/leapbinder.py,sha256=4cbSEbN6vVwjFUMxDEksxk1VSCip2ntLB32RxA81_JE,53194
|
|
25
|
-
code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=
|
|
26
|
-
code_loader/leaploader.py,sha256=
|
|
27
|
-
code_loader/leaploaderbase.py,sha256=
|
|
25
|
+
code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=eHdSRCYtfkHtq7NSlS4bF92TU8RGRzZ1gbb3ULeEV2c,176145
|
|
26
|
+
code_loader/leaploader.py,sha256=ME1Ypq9VV3o9XXOCV6voDWWVP0gB4Z0LoJh6u79qDYY,68370
|
|
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=gEJCKpDWf6p9_KoEz-0EGiJqxD6QfPgZN6zdKdtSAz8,6628
|
|
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.
|
|
36
|
-
code_loader-1.0.
|
|
37
|
-
code_loader-1.0.
|
|
38
|
-
code_loader-1.0.
|
|
35
|
+
code_loader-1.0.195.dev0.dist-info/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
|
|
36
|
+
code_loader-1.0.195.dev0.dist-info/METADATA,sha256=q8UczKAxuYThEseqP4aXcS5ET0DfpjPaRmIy4aKDl1I,1095
|
|
37
|
+
code_loader-1.0.195.dev0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
38
|
+
code_loader-1.0.195.dev0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|