code-loader 1.0.192__py3-none-any.whl → 1.0.193.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/contract/datasetclasses.py +43 -10
- code_loader/inner_leap_binder/leapbinder.py +96 -1
- code_loader/inner_leap_binder/leapbinder_decorators.py +783 -70
- code_loader/leaploader.py +154 -40
- code_loader/utils.py +36 -0
- {code_loader-1.0.192.dist-info → code_loader-1.0.193.dev0.dist-info}/METADATA +1 -1
- {code_loader-1.0.192.dist-info → code_loader-1.0.193.dev0.dist-info}/RECORD +9 -9
- {code_loader-1.0.192.dist-info → code_loader-1.0.193.dev0.dist-info}/LICENSE +0 -0
- {code_loader-1.0.192.dist-info → code_loader-1.0.193.dev0.dist-info}/WHEEL +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import warnings
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
|
-
from typing import Any, Callable, List, Optional, Dict, Union, Type, Literal
|
|
3
|
+
from typing import Any, Callable, List, Optional, Dict, Union, Type, Literal, Tuple
|
|
4
4
|
import re
|
|
5
5
|
import numpy as np
|
|
6
6
|
import numpy.typing as npt
|
|
@@ -92,15 +92,19 @@ SectionCallableInterface = Callable[[Union[int, str], PreprocessResponse], npt.N
|
|
|
92
92
|
InstanceCallableInterface = Callable[[Union[int, str], PreprocessResponse, int], Optional[ElementInstance]]
|
|
93
93
|
InstanceLengthCallableInterface = Callable[[Union[int, str], PreprocessResponse], int]
|
|
94
94
|
|
|
95
|
-
# (sample_id, prev_inputs, prev_outputs, preprocess) -> next model inputs
|
|
96
|
-
# First call per chain receives prev_inputs=None, prev_outputs=None and returns the
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
95
|
+
# (sample_id, prev_inputs, prev_outputs, state, preprocess) -> (next model inputs | None, state).
|
|
96
|
+
# First call per chain receives prev_inputs=None, prev_outputs=None, state=None and returns the
|
|
97
|
+
# initial model inputs plus the initial state. Returning next_inputs=None ends the chain — the
|
|
98
|
+
# terminating call still returns state, so the final step participates in state aggregation.
|
|
99
|
+
# State is an arbitrary nest of dicts/lists holding numpy arrays, numbers, strings or bools; it is
|
|
100
|
+
# never fed to the model and rides the engine's redis queue on every step, so accumulate
|
|
101
|
+
# reductions, not raw per-step tensors. The hook must be stateless and deterministically seeded
|
|
102
|
+
# (the engine may replay a step after crash recovery and relies on identical results).
|
|
103
|
+
AutoregressiveChainState = Any
|
|
100
104
|
AutoregressiveStepCallableInterface = Callable[
|
|
101
105
|
[Union[int, str], Optional[Dict[str, npt.NDArray[np.float32]]], Optional[Dict[str, npt.NDArray[np.float32]]],
|
|
102
|
-
PreprocessResponse],
|
|
103
|
-
Optional[Dict[str, npt.NDArray[np.float32]]]]
|
|
106
|
+
AutoregressiveChainState, PreprocessResponse],
|
|
107
|
+
Tuple[Optional[Dict[str, npt.NDArray[np.float32]]], AutoregressiveChainState]]
|
|
104
108
|
|
|
105
109
|
MetadataSectionCallableInterface = Union[
|
|
106
110
|
Callable[[Union[int, str], PreprocessResponse], int],
|
|
@@ -256,16 +260,42 @@ class CustomLatentSpaceHandler:
|
|
|
256
260
|
# dominates the model inputs). 'mean': every latent space is the elementwise mean over all steps.
|
|
257
261
|
AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS = ('last_step', 'mean')
|
|
258
262
|
|
|
263
|
+
# Reserved argument names of autoregressive metrics/losses/visualizers, fed implicitly by the
|
|
264
|
+
# platform from the finished chain (per-chain dicts, no batch axis). Any other argument is wired
|
|
265
|
+
# to a ground-truth encoder through the integration test.
|
|
266
|
+
AUTOREGRESSIVE_IMPLICIT_ARG_NAMES = ('inputs', 'outputs', 'state')
|
|
267
|
+
|
|
259
268
|
|
|
260
269
|
@dataclass
|
|
261
270
|
class AutoregressiveStepHandler:
|
|
262
271
|
function: AutoregressiveStepCallableInterface
|
|
263
272
|
name: str = 'autoregressive_step'
|
|
264
|
-
# Per-model-input shapes (unbatched,
|
|
265
|
-
#
|
|
273
|
+
# Per-model-input shapes (unbatched), discovered by running the hook's first call at parse
|
|
274
|
+
# time. Fills the role InputHandler.shape plays for input encoders.
|
|
266
275
|
input_shapes: Optional[Dict[str, List[int]]] = None
|
|
267
276
|
latent_space_aggregation: str = 'last_step'
|
|
268
277
|
|
|
278
|
+
|
|
279
|
+
# Per-chain, unbatched callables: called once per finished chain with the final step's tensors —
|
|
280
|
+
# inputs/outputs/state are fed implicitly by the platform (dicts, no batch axis; outputs keyed by
|
|
281
|
+
# prediction-type names), remaining args are wired ground-truth encoder results.
|
|
282
|
+
@dataclass
|
|
283
|
+
class AutoregressiveMetricHandler:
|
|
284
|
+
metric_handler_data: MetricHandlerData
|
|
285
|
+
function: CustomCallableInterfaceMultiArgs
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
@dataclass
|
|
289
|
+
class AutoregressiveLossHandler:
|
|
290
|
+
custom_loss_handler_data: CustomLossHandlerData
|
|
291
|
+
function: CustomCallableInterface
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@dataclass
|
|
295
|
+
class AutoregressiveVisualizerHandler:
|
|
296
|
+
visualizer_handler_data: VisualizerHandlerData
|
|
297
|
+
function: VisualizerCallableInterface
|
|
298
|
+
|
|
269
299
|
@dataclass
|
|
270
300
|
class PredictionTypeHandler:
|
|
271
301
|
name: str
|
|
@@ -307,6 +337,9 @@ class DatasetIntegrationSetup:
|
|
|
307
337
|
custom_latent_space: Optional[CustomLatentSpaceHandler] = None
|
|
308
338
|
simulations: List[SimulationHandler] = field(default_factory=list)
|
|
309
339
|
autoregressive_step: Optional[AutoregressiveStepHandler] = None
|
|
340
|
+
autoregressive_metrics: List[AutoregressiveMetricHandler] = field(default_factory=list)
|
|
341
|
+
autoregressive_losses: List[AutoregressiveLossHandler] = field(default_factory=list)
|
|
342
|
+
autoregressive_visualizers: List[AutoregressiveVisualizerHandler] = field(default_factory=list)
|
|
310
343
|
|
|
311
344
|
|
|
312
345
|
@dataclass
|
|
@@ -14,7 +14,8 @@ from code_loader.contract.datasetclasses import SectionCallableInterface, InputH
|
|
|
14
14
|
RawInputsForHeatmap, VisualizerHandlerData, MetricHandlerData, CustomLossHandlerData, SamplePreprocessResponse, \
|
|
15
15
|
ElementInstanceMasksHandler, InstanceCallableInterface, CustomLatentSpaceHandler, InstanceMetricHandler, \
|
|
16
16
|
SimulationHandler, _simulation_context, AutoregressiveStepHandler, AutoregressiveStepCallableInterface, \
|
|
17
|
-
AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS
|
|
17
|
+
AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS, AUTOREGRESSIVE_IMPLICIT_ARG_NAMES, \
|
|
18
|
+
AutoregressiveMetricHandler, AutoregressiveLossHandler, AutoregressiveVisualizerHandler
|
|
18
19
|
from code_loader.contract.enums import LeapDataType, DataStateEnum, DataStateType, MetricDirection, DatasetMetadataType
|
|
19
20
|
from code_loader.contract.mapping import NodeConnection, NodeMapping, NodeMappingType
|
|
20
21
|
from code_loader.contract.responsedataclasses import DatasetTestResultPayload, LeapAnalysisConfiguration
|
|
@@ -553,6 +554,83 @@ class LeapBinder:
|
|
|
553
554
|
|
|
554
555
|
self.set_metadata(builtin_chain_metadata, 'builtin_chain')
|
|
555
556
|
|
|
557
|
+
def _autoregressive_arg_names(self, function: Callable[..., Any], decorator_name: str,
|
|
558
|
+
name: str) -> List[str]:
|
|
559
|
+
"""Split an autoregressive callable's signature into implicit chain args (validated
|
|
560
|
+
present) and wired arg names (returned) — the wired args connect to ground-truth
|
|
561
|
+
encoders through the integration test."""
|
|
562
|
+
argspec = inspect.getfullargspec(function)
|
|
563
|
+
for arg_name, arg_type in argspec.annotations.items():
|
|
564
|
+
_reject_stringized_sample_preprocess_response(function, arg_name, arg_type)
|
|
565
|
+
if arg_type == SamplePreprocessResponse:
|
|
566
|
+
raise Exception(
|
|
567
|
+
f'{decorator_name} "{name}": SamplePreprocessResponse arguments are not '
|
|
568
|
+
f'supported for autoregressive decorators yet. Derive what you need inside '
|
|
569
|
+
f'the autoregressive step hook and carry it in the state.')
|
|
570
|
+
implicit = [arg_name for arg_name in argspec[0]
|
|
571
|
+
if arg_name in AUTOREGRESSIVE_IMPLICIT_ARG_NAMES]
|
|
572
|
+
if not implicit:
|
|
573
|
+
raise Exception(
|
|
574
|
+
f'{decorator_name} "{name}": the function must declare at least one of the '
|
|
575
|
+
f'implicit chain arguments {list(AUTOREGRESSIVE_IMPLICIT_ARG_NAMES)} — they are '
|
|
576
|
+
f'fed by the platform from the finished chain.')
|
|
577
|
+
return [arg_name for arg_name in argspec[0]
|
|
578
|
+
if arg_name not in AUTOREGRESSIVE_IMPLICIT_ARG_NAMES]
|
|
579
|
+
|
|
580
|
+
def _assert_unique_metric_name(self, name: str) -> None:
|
|
581
|
+
existing = [handler.metric_handler_data.name for handler in self.setup_container.metrics] \
|
|
582
|
+
+ [handler.metric_handler_data.name
|
|
583
|
+
for handler in self.setup_container.autoregressive_metrics]
|
|
584
|
+
if name in existing:
|
|
585
|
+
raise Exception(f'Metric with name {name} already exists. Please choose another')
|
|
586
|
+
|
|
587
|
+
def _assert_unique_loss_name(self, name: str) -> None:
|
|
588
|
+
existing = [handler.custom_loss_handler_data.name
|
|
589
|
+
for handler in self.setup_container.custom_loss_handlers] \
|
|
590
|
+
+ [handler.custom_loss_handler_data.name
|
|
591
|
+
for handler in self.setup_container.autoregressive_losses]
|
|
592
|
+
if name in existing:
|
|
593
|
+
raise Exception(f'Custom loss with name {name} already exists. Please choose another')
|
|
594
|
+
|
|
595
|
+
def _assert_unique_visualizer_name(self, name: str) -> None:
|
|
596
|
+
existing = [handler.visualizer_handler_data.name
|
|
597
|
+
for handler in self.setup_container.visualizers] \
|
|
598
|
+
+ [handler.visualizer_handler_data.name
|
|
599
|
+
for handler in self.setup_container.autoregressive_visualizers]
|
|
600
|
+
if name in existing:
|
|
601
|
+
raise Exception(f'Visualizer with name {name} already exists. Please choose another')
|
|
602
|
+
|
|
603
|
+
def add_autoregressive_metric(self, function: CustomCallableInterfaceMultiArgs, name: str,
|
|
604
|
+
direction: Optional[Union[MetricDirection, Dict[str, MetricDirection]]]
|
|
605
|
+
= MetricDirection.Downward,
|
|
606
|
+
compute_insights: Optional[Union[bool, Dict[str, bool]]] = None) -> None:
|
|
607
|
+
self._assert_unique_metric_name(name)
|
|
608
|
+
arg_names = self._autoregressive_arg_names(function, 'tensorleap_autoregressive_metric',
|
|
609
|
+
name)
|
|
610
|
+
metric_handler_data = MetricHandlerData(name, arg_names, direction, compute_insights)
|
|
611
|
+
self.setup_container.autoregressive_metrics.append(
|
|
612
|
+
AutoregressiveMetricHandler(metric_handler_data, function))
|
|
613
|
+
|
|
614
|
+
def add_autoregressive_loss(self, function: CustomCallableInterface, name: str) -> None:
|
|
615
|
+
self._assert_unique_loss_name(name)
|
|
616
|
+
arg_names = self._autoregressive_arg_names(function, 'tensorleap_autoregressive_loss',
|
|
617
|
+
name)
|
|
618
|
+
self.setup_container.autoregressive_losses.append(
|
|
619
|
+
AutoregressiveLossHandler(CustomLossHandlerData(name, arg_names), function))
|
|
620
|
+
|
|
621
|
+
def add_autoregressive_visualizer(self, function: VisualizerCallableInterface, name: str,
|
|
622
|
+
visualizer_type: LeapDataType) -> None:
|
|
623
|
+
self._assert_unique_visualizer_name(name)
|
|
624
|
+
if visualizer_type.value not in map_leap_data_type_to_visualizer_class:
|
|
625
|
+
raise Exception(
|
|
626
|
+
f'The visualizer_type is invalid. current visualizer_type: {visualizer_type}, '
|
|
627
|
+
f'should be one of : {", ".join([arg.__name__ for arg in get_args(LeapData)])}')
|
|
628
|
+
arg_names = self._autoregressive_arg_names(
|
|
629
|
+
function, 'tensorleap_autoregressive_visualizer', name)
|
|
630
|
+
self.setup_container.autoregressive_visualizers.append(
|
|
631
|
+
AutoregressiveVisualizerHandler(VisualizerHandlerData(name, visualizer_type,
|
|
632
|
+
arg_names), function))
|
|
633
|
+
|
|
556
634
|
def set_custom_layer(self, custom_layer: Type[Any], name: str, inspect_layer: bool = False,
|
|
557
635
|
kernel_index: Optional[int] = None, use_custom_latent_space: bool = False) -> None:
|
|
558
636
|
"""
|
|
@@ -778,6 +856,23 @@ class LeapBinder:
|
|
|
778
856
|
appear in any order in the integration file.
|
|
779
857
|
"""
|
|
780
858
|
if self.setup_container.autoregressive_step is None:
|
|
859
|
+
declared_autoregressive = [
|
|
860
|
+
('tensorleap_autoregressive_metric',
|
|
861
|
+
[handler.metric_handler_data.name
|
|
862
|
+
for handler in self.setup_container.autoregressive_metrics]),
|
|
863
|
+
('tensorleap_autoregressive_loss',
|
|
864
|
+
[handler.custom_loss_handler_data.name
|
|
865
|
+
for handler in self.setup_container.autoregressive_losses]),
|
|
866
|
+
('tensorleap_autoregressive_visualizer',
|
|
867
|
+
[handler.visualizer_handler_data.name
|
|
868
|
+
for handler in self.setup_container.autoregressive_visualizers]),
|
|
869
|
+
]
|
|
870
|
+
for decorator_name, names in declared_autoregressive:
|
|
871
|
+
if names:
|
|
872
|
+
raise Exception(
|
|
873
|
+
f'{decorator_name} {names} requires a tensorleap_autoregressive_step '
|
|
874
|
+
f'hook — autoregressive decorators consume the finished chain the hook '
|
|
875
|
+
f'drives.')
|
|
781
876
|
return
|
|
782
877
|
if self.setup_container.inputs:
|
|
783
878
|
raise Exception(
|