code-loader 1.0.203__tar.gz → 1.0.204.dev1__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.203 → code_loader-1.0.204.dev1}/PKG-INFO +3 -4
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/contract/datasetclasses.py +3 -16
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/inner_leap_binder/leapbinder.py +10 -64
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/inner_leap_binder/leapbinder_decorators.py +89 -102
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/leaploader.py +68 -36
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/leaploaderbase.py +0 -10
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/pyproject.toml +1 -1
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/LICENSE +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/README.md +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/__init__.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/contract/__init__.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/contract/enums.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/contract/exceptions.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/contract/mapping.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/contract/responsedataclasses.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/contract/sim_config.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/contract/visualizer_classes.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/default_losses.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/default_metrics.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/__init__.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/api.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/cli_config_utils.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/client.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/epoch.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/experiment.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/experiment_context.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/types.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/utils.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/inner_leap_binder/__init__.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/mixpanel_tracker.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/plot_functions/__init__.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/plot_functions/plot_functions.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/plot_functions/visualize.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/utils.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/visualizers/__init__.py +0 -0
- {code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/visualizers/default_visualizers.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: code-loader
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.204.dev1
|
|
4
4
|
Summary:
|
|
5
|
+
Home-page: https://github.com/tensorleap/code-loader
|
|
5
6
|
License: MIT
|
|
6
|
-
License-File: LICENSE
|
|
7
7
|
Author: dorhar
|
|
8
8
|
Author-email: doron.harnoy@tensorleap.ai
|
|
9
9
|
Requires-Python: >=3.8,<3.13
|
|
@@ -20,7 +20,6 @@ Requires-Dist: numpy (>=2.3.2,<3.0.0) ; python_version >= "3.11" and python_vers
|
|
|
20
20
|
Requires-Dist: psutil (>=5.9.5,<6.0.0)
|
|
21
21
|
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
|
|
22
22
|
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
|
23
|
-
Project-URL: Homepage, https://github.com/tensorleap/code-loader
|
|
24
23
|
Project-URL: Repository, https://github.com/tensorleap/code-loader
|
|
25
24
|
Description-Content-Type: text/markdown
|
|
26
25
|
|
|
@@ -147,6 +147,8 @@ class ElementInstance:
|
|
|
147
147
|
SectionCallableInterface = Callable[[Union[int, str], PreprocessResponse], npt.NDArray[np.float32]]
|
|
148
148
|
InstanceCallableInterface = Callable[[Union[int, str], PreprocessResponse, int], Optional[ElementInstance]]
|
|
149
149
|
InstanceLengthCallableInterface = Callable[[Union[int, str], PreprocessResponse], int]
|
|
150
|
+
InstanceSectionCallableInterface = Callable[
|
|
151
|
+
[Union[int, str], PreprocessResponse, Optional[int]], npt.NDArray[np.float32]]
|
|
150
152
|
|
|
151
153
|
# (sample_id, prev_inputs, prev_outputs, state, preprocess) -> (next model inputs | None, state).
|
|
152
154
|
# First call per chain receives prev_inputs=None, prev_outputs=None, state=None and returns the
|
|
@@ -310,6 +312,7 @@ class CustomLatentSpaceHandler:
|
|
|
310
312
|
function: SectionCallableInterface
|
|
311
313
|
name: str = 'custom_latent_space'
|
|
312
314
|
use_ls_for_analysis: bool = False
|
|
315
|
+
instance_aware: bool = False
|
|
313
316
|
|
|
314
317
|
|
|
315
318
|
# How a chain's latent-space vectors are derived from its per-step forward passes.
|
|
@@ -318,11 +321,6 @@ class CustomLatentSpaceHandler:
|
|
|
318
321
|
# dominates the model inputs). 'mean': every latent space is the elementwise mean over all steps.
|
|
319
322
|
AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS = ('last_step', 'mean')
|
|
320
323
|
|
|
321
|
-
# Default axis of a KV-cache tensor that indexes token positions: (batch, heads, position,
|
|
322
|
-
# head_dim), the layout HF-style exports produce. Overridable per integration via
|
|
323
|
-
# tensorleap_autoregressive_step(cache_seq_axis=...).
|
|
324
|
-
DEFAULT_CACHE_SEQ_AXIS = 2
|
|
325
|
-
|
|
326
324
|
# Reserved argument names of autoregressive metrics/losses/visualizers, fed implicitly by the
|
|
327
325
|
# platform from the finished chain (per-chain dicts, no batch axis). Any other argument is wired
|
|
328
326
|
# to a ground-truth encoder through the integration test.
|
|
@@ -337,17 +335,6 @@ class AutoregressiveStepHandler:
|
|
|
337
335
|
# time. Fills the role InputHandler.shape plays for input encoders.
|
|
338
336
|
input_shapes: Optional[Dict[str, List[int]]] = None
|
|
339
337
|
latent_space_aggregation: str = 'last_step'
|
|
340
|
-
# {model_input_name: model_output_name} for a KV-cache (or any threaded state): inputs whose
|
|
341
|
-
# value is the named output from the previous step. The platform threads these itself — they
|
|
342
|
-
# are never passed to the hook and never reported — so the hook must NOT return them. Empty
|
|
343
|
-
# when the model has no cache, in which case the chain re-feeds its full prompt each step.
|
|
344
|
-
cache_tensors: Optional[Dict[str, str]] = None
|
|
345
|
-
# Which axis of a cache tensor indexes token positions, i.e. where its capacity is read from.
|
|
346
|
-
# 2 matches the (batch, heads, position, head_dim) layout every HF-style export uses. Declared
|
|
347
|
-
# rather than inferred because the platform cannot tell positions from heads or head_dim — in
|
|
348
|
-
# a (1, 3, 64, 64) tensor two of the dims are 64 — and reading the wrong axis silently caps
|
|
349
|
-
# chains at the number of heads instead of the cache capacity.
|
|
350
|
-
cache_seq_axis: int = DEFAULT_CACHE_SEQ_AXIS
|
|
351
338
|
|
|
352
339
|
|
|
353
340
|
# Per-chain, unbatched callables: called once per finished chain with the final step's tensors —
|
{code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/inner_leap_binder/leapbinder.py
RENAMED
|
@@ -15,10 +15,10 @@ from code_loader.contract.datasetclasses import SectionCallableInterface, InputH
|
|
|
15
15
|
CustomCallableInterfaceMultiArgs, ConfusionMatrixCallableInterfaceMultiArgs, LeapData, \
|
|
16
16
|
CustomMultipleReturnCallableInterfaceMultiArgs, DatasetBaseHandler, custom_latent_space_attribute, \
|
|
17
17
|
RawInputsForHeatmap, VisualizerHandlerData, MetricHandlerData, CustomLossHandlerData, SamplePreprocessResponse, \
|
|
18
|
-
ElementInstanceMasksHandler, InstanceCallableInterface,
|
|
18
|
+
ElementInstanceMasksHandler, InstanceCallableInterface, InstanceSectionCallableInterface, \
|
|
19
|
+
CustomLatentSpaceHandler, InstanceMetricHandler, \
|
|
19
20
|
SimulationHandler, _simulation_context, AutoregressiveStepHandler, AutoregressiveStepCallableInterface, \
|
|
20
21
|
AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS, AUTOREGRESSIVE_IMPLICIT_ARG_NAMES, \
|
|
21
|
-
DEFAULT_CACHE_SEQ_AXIS, \
|
|
22
22
|
AutoregressiveMetricHandler, AutoregressiveLossHandler, AutoregressiveVisualizerHandler
|
|
23
23
|
from code_loader.contract.enums import LeapDataType, DataStateEnum, DataStateType, MetricDirection, DatasetMetadataType, \
|
|
24
24
|
TestingSectionEnum
|
|
@@ -542,9 +542,10 @@ class LeapBinder:
|
|
|
542
542
|
f"@tensorleap_metadata('my_metadata', {{'key': DatasetMetadataType.int}}).")
|
|
543
543
|
self.setup_container.metadata.append(MetadataHandler(name, function, metadata_type))
|
|
544
544
|
|
|
545
|
-
def set_custom_latent_space(self, function: SectionCallableInterface,
|
|
545
|
+
def set_custom_latent_space(self, function: Union[SectionCallableInterface, InstanceSectionCallableInterface],
|
|
546
546
|
name: Optional[str] = None,
|
|
547
|
-
use_ls_for_analysis: bool = False
|
|
547
|
+
use_ls_for_analysis: bool = False,
|
|
548
|
+
instance_aware: bool = False) -> None:
|
|
548
549
|
"""
|
|
549
550
|
Register a custom latent space function.
|
|
550
551
|
|
|
@@ -565,6 +566,8 @@ class LeapBinder:
|
|
|
565
566
|
space for the Out-Of-Distribution and Domain-Gap insights instead of the
|
|
566
567
|
built-in defaults. At most one registered custom latent space may set this;
|
|
567
568
|
registering a second one with the flag raises.
|
|
569
|
+
instance_aware (bool): When True, `function` takes a third `instance_id` argument
|
|
570
|
+
and is called once per element-instance row instead of once per sample.
|
|
568
571
|
"""
|
|
569
572
|
if name is None:
|
|
570
573
|
name = custom_latent_space_attribute
|
|
@@ -589,59 +592,10 @@ class LeapBinder:
|
|
|
589
592
|
f"or '{already_flagged[0]}', not both."
|
|
590
593
|
)
|
|
591
594
|
self.setup_container.custom_latent_spaces[name] = CustomLatentSpaceHandler(
|
|
592
|
-
function, name, use_ls_for_analysis)
|
|
593
|
-
|
|
594
|
-
@staticmethod
|
|
595
|
-
def _validated_cache_tensors(cache_tensors: Optional[Dict[str, str]]
|
|
596
|
-
) -> Optional[Dict[str, str]]:
|
|
597
|
-
"""Structural checks only — shape/dtype/existence are validated by the platform, which
|
|
598
|
-
is the side that has the model graph. This catches the typos that are cheap to catch
|
|
599
|
-
here, at integration-test time, instead of at push."""
|
|
600
|
-
if not cache_tensors:
|
|
601
|
-
return None
|
|
602
|
-
if not isinstance(cache_tensors, dict):
|
|
603
|
-
raise Exception(f'tensorleap_autoregressive_step: cache_tensors must be a dict of '
|
|
604
|
-
f'{{model_input_name: model_output_name}}, got '
|
|
605
|
-
f'{type(cache_tensors).__name__}.')
|
|
606
|
-
seen_outputs: Dict[str, str] = {}
|
|
607
|
-
for input_name, output_name in cache_tensors.items():
|
|
608
|
-
for role, name in (('key', input_name), ('value', output_name)):
|
|
609
|
-
if not isinstance(name, str) or not name:
|
|
610
|
-
raise Exception(
|
|
611
|
-
f'tensorleap_autoregressive_step: cache_tensors {role}s must be '
|
|
612
|
-
f'non-empty model tensor names, got {name!r}.')
|
|
613
|
-
if input_name == output_name:
|
|
614
|
-
raise Exception(
|
|
615
|
-
f'tensorleap_autoregressive_step: cache_tensors maps "{input_name}" to '
|
|
616
|
-
f'itself. A model input and output cannot share a name — the mapping is '
|
|
617
|
-
f'{{input_name: output_name}}.')
|
|
618
|
-
if output_name in seen_outputs:
|
|
619
|
-
raise Exception(
|
|
620
|
-
f'tensorleap_autoregressive_step: model output "{output_name}" is declared '
|
|
621
|
-
f'as the cache source for both "{seen_outputs[output_name]}" and '
|
|
622
|
-
f'"{input_name}". Each cache output feeds exactly one input.')
|
|
623
|
-
seen_outputs[output_name] = input_name
|
|
624
|
-
return dict(cache_tensors)
|
|
625
|
-
|
|
626
|
-
@staticmethod
|
|
627
|
-
def _validated_cache_seq_axis(cache_seq_axis: int,
|
|
628
|
-
cache_tensors: Optional[Dict[str, str]]) -> int:
|
|
629
|
-
"""The axis must be a non-negative int, and declaring one without a cache is a mistake
|
|
630
|
-
worth naming — it reads as if it had an effect."""
|
|
631
|
-
if not isinstance(cache_seq_axis, int) or isinstance(cache_seq_axis, bool) \
|
|
632
|
-
or cache_seq_axis < 0:
|
|
633
|
-
raise Exception(f'tensorleap_autoregressive_step: cache_seq_axis must be a '
|
|
634
|
-
f'non-negative int axis index, got {cache_seq_axis!r}.')
|
|
635
|
-
if not cache_tensors and cache_seq_axis != DEFAULT_CACHE_SEQ_AXIS:
|
|
636
|
-
raise Exception('tensorleap_autoregressive_step: cache_seq_axis was declared without '
|
|
637
|
-
'cache_tensors. The axis describes the declared cache tensors, so it '
|
|
638
|
-
'has no meaning on its own.')
|
|
639
|
-
return cache_seq_axis
|
|
595
|
+
function=function, name=name, use_ls_for_analysis=use_ls_for_analysis, instance_aware=instance_aware)
|
|
640
596
|
|
|
641
597
|
def set_autoregressive_step(self, function: AutoregressiveStepCallableInterface,
|
|
642
|
-
latent_space_aggregation: str = 'last_step'
|
|
643
|
-
cache_tensors: Optional[Dict[str, str]] = None,
|
|
644
|
-
cache_seq_axis: int = DEFAULT_CACHE_SEQ_AXIS) -> None:
|
|
598
|
+
latent_space_aggregation: str = 'last_step') -> None:
|
|
645
599
|
"""
|
|
646
600
|
Set the autoregressive step hook — the feedback function that drives a chain:
|
|
647
601
|
it supplies the model's initial inputs on its first call (prev_inputs=None, prev_outputs=None)
|
|
@@ -649,11 +603,6 @@ class LeapBinder:
|
|
|
649
603
|
An autoregressive integration has no input encoders; the hook is the sole input source.
|
|
650
604
|
latent_space_aggregation declares how the chain's latent-space vectors are derived from
|
|
651
605
|
its steps (see AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS).
|
|
652
|
-
cache_tensors declares a KV-cache as {model_input_name: model_output_name}; the platform
|
|
653
|
-
threads those tensors itself and the hook neither receives nor returns them.
|
|
654
|
-
cache_seq_axis declares which axis of those tensors indexes token positions, i.e. where
|
|
655
|
-
the platform reads the cache capacity from (default 2, for (batch, heads, position,
|
|
656
|
-
head_dim)).
|
|
657
606
|
"""
|
|
658
607
|
if self.setup_container.autoregressive_step is not None:
|
|
659
608
|
raise Exception('tensorleap_autoregressive_step is already defined. '
|
|
@@ -662,11 +611,8 @@ class LeapBinder:
|
|
|
662
611
|
raise Exception(f'tensorleap_autoregressive_step: unknown latent_space_aggregation '
|
|
663
612
|
f'{latent_space_aggregation!r}. Supported values: '
|
|
664
613
|
f'{", ".join(AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS)}.')
|
|
665
|
-
cache_tensors = self._validated_cache_tensors(cache_tensors)
|
|
666
|
-
cache_seq_axis = self._validated_cache_seq_axis(cache_seq_axis, cache_tensors)
|
|
667
614
|
self.setup_container.autoregressive_step = AutoregressiveStepHandler(
|
|
668
|
-
function, latent_space_aggregation=latent_space_aggregation
|
|
669
|
-
cache_tensors=cache_tensors, cache_seq_axis=cache_seq_axis)
|
|
615
|
+
function, latent_space_aggregation=latent_space_aggregation)
|
|
670
616
|
|
|
671
617
|
# Builtin chain metadata, declared at parse time so it survives the reporter's
|
|
672
618
|
# metadata type mapping; the placeholder values are overwritten by the engine when a
|
|
@@ -24,7 +24,7 @@ from code_loader.contract.datasetclasses import CustomCallableInterfaceMultiArgs
|
|
|
24
24
|
CustomMultipleReturnCallableInterfaceMultiArgs, ConfusionMatrixCallableInterfaceMultiArgs, CustomCallableInterface, \
|
|
25
25
|
VisualizerCallableInterface, MetadataSectionCallableInterface, PreprocessResponse, SectionCallableInterface, \
|
|
26
26
|
ConfusionMatrixElement, SamplePreprocessResponse, PredictionTypeHandler, InstanceCallableInterface, ElementInstance, \
|
|
27
|
-
InstanceLengthCallableInterface,
|
|
27
|
+
InstanceLengthCallableInterface, InstanceSectionCallableInterface, AutoregressiveStepCallableInterface
|
|
28
28
|
from code_loader.contract.enums import MetricDirection, LeapDataType, DatasetMetadataType, DataStateType
|
|
29
29
|
from code_loader import leap_binder, LeapLoader
|
|
30
30
|
from code_loader.contract.mapping import NodeMapping, NodeMappingType, NodeConnection
|
|
@@ -560,22 +560,12 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
|
|
|
560
560
|
return result
|
|
561
561
|
|
|
562
562
|
def validate_declared_prediction_types(self, ret):
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
# the model and never reported, so they carry no prediction type. Count only
|
|
566
|
-
# the rest, or every cached model would demand 60 meaningless declarations.
|
|
567
|
-
step = leap_binder.setup_container.autoregressive_step
|
|
568
|
-
n_cache = len((step.cache_tensors if step else None) or {})
|
|
569
|
-
if len(self.prediction_types) != 0 and \
|
|
570
|
-
n_outputs - n_cache != len(self.prediction_types):
|
|
563
|
+
if not (len(self.prediction_types) == len(ret) if isinstance(ret, list) else 1) and len(
|
|
564
|
+
self.prediction_types) != 0:
|
|
571
565
|
if not _call_from_tl_platform:
|
|
572
566
|
update_env_params_func("tensorleap_load_model", "x")
|
|
573
|
-
cache_note = (f' ({n_cache} of them are the declared KV-cache, which '
|
|
574
|
-
f'needs none)' if n_cache else '')
|
|
575
567
|
raise Exception(
|
|
576
|
-
f"tensorleap_load_model validation failed: number of declared "
|
|
577
|
-
f"prediction types({len(prediction_types)}) != number of model "
|
|
578
|
-
f"outputs({n_outputs}){cache_note}")
|
|
568
|
+
f"tensorleap_load_model validation failed: number of declared prediction types({len(prediction_types)}) != number of model outputs({len(ret) if isinstance(ret, list) else 1})")
|
|
579
569
|
|
|
580
570
|
def _convert_onnx_inputs_to_correct_type(
|
|
581
571
|
self, float_arrays_inputs: Dict[str, np.ndarray]
|
|
@@ -733,22 +723,12 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
|
|
|
733
723
|
assert isinstance(input_dict, dict), \
|
|
734
724
|
f'Expected input_dict to be a dict, got {type(input_dict)} instead.'
|
|
735
725
|
seen: set = set()
|
|
736
|
-
|
|
737
|
-
# encoder, so those slots have no mapping node to assign — the loop feeds
|
|
738
|
-
# them real arrays even in mapping mode. Skip them, and count only the wired
|
|
739
|
-
# inputs so the remaining slot indices stay contiguous.
|
|
740
|
-
step_handler = leap_binder.setup_container.autoregressive_step
|
|
741
|
-
cache_tensors = (step_handler.cache_tensors if step_handler else None) or {}
|
|
742
|
-
slot = 0
|
|
743
|
-
for input_key, elem in input_dict.items():
|
|
744
|
-
if input_key in cache_tensors:
|
|
745
|
-
continue
|
|
726
|
+
for i, (input_key, elem) in enumerate(input_dict.items()):
|
|
746
727
|
self._reject_reused_input_source(elem, seen)
|
|
747
728
|
if isinstance(input_key, NodeMappingType):
|
|
748
729
|
elem.node_mapping.type = input_key
|
|
749
730
|
else:
|
|
750
|
-
elem.node_mapping.type = _safe_get_item(
|
|
751
|
-
slot += 1
|
|
731
|
+
elem.node_mapping.type = _safe_get_item(i)
|
|
752
732
|
|
|
753
733
|
return ModelOutputPlaceholder()
|
|
754
734
|
|
|
@@ -1807,6 +1787,73 @@ def tensorleap_custom_latent_space(name: Optional[str] = None, use_ls_for_analys
|
|
|
1807
1787
|
return decorating_function
|
|
1808
1788
|
|
|
1809
1789
|
|
|
1790
|
+
def tensorleap_instance_custom_latent_space(name: Optional[str] = None, use_ls_for_analysis: bool = False):
|
|
1791
|
+
assert isinstance(use_ls_for_analysis, bool), \
|
|
1792
|
+
("tensorleap_instance_custom_latent_space validation failed: use_ls_for_analysis must be a bool. "
|
|
1793
|
+
f"Got {type(use_ls_for_analysis)}.")
|
|
1794
|
+
|
|
1795
|
+
def decorating_function(user_function: InstanceSectionCallableInterface):
|
|
1796
|
+
ls_name = name if name is not None else user_function.__name__
|
|
1797
|
+
|
|
1798
|
+
argspec = inspect.getfullargspec(user_function)
|
|
1799
|
+
assert len(argspec.args) == 3, \
|
|
1800
|
+
(f'tensorleap_instance_custom_latent_space validation failed: '
|
|
1801
|
+
f'The function should take exactly 3 positional parameters '
|
|
1802
|
+
f'(sample_id, preprocess_response, instance_id). Got {len(argspec.args)}.')
|
|
1803
|
+
|
|
1804
|
+
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse,
|
|
1805
|
+
instance_id: int):
|
|
1806
|
+
_validate_id_or_group(sample_id, preprocess_response, 'tensorleap_instance_custom_latent_space')
|
|
1807
|
+
assert isinstance(instance_id, (int, np.integer)), \
|
|
1808
|
+
(f'tensorleap_instance_custom_latent_space validation failed: '
|
|
1809
|
+
f'Argument instance_id should be int. Got {type(instance_id)}.')
|
|
1810
|
+
|
|
1811
|
+
def _validate_result(result):
|
|
1812
|
+
assert isinstance(result, np.ndarray), \
|
|
1813
|
+
(f'tensorleap_instance_custom_latent_space validation failed: '
|
|
1814
|
+
f'The return type should be a numpy array. Got {type(result)}.')
|
|
1815
|
+
if result.ndim > 1:
|
|
1816
|
+
flat_dim = int(np.prod(result.shape))
|
|
1817
|
+
store_general_warning(
|
|
1818
|
+
key=("tensorleap_instance_custom_latent_space_flatten", ls_name, tuple(result.shape)),
|
|
1819
|
+
message=(
|
|
1820
|
+
f"tensorleap_instance_custom_latent_space '{ls_name}' returned per-sample shape "
|
|
1821
|
+
f"{tuple(result.shape)} (ndim={result.ndim}). Tensorleap assumes per-sample shape "
|
|
1822
|
+
f"(d, ...) and will flatten to ({flat_dim},) before downstream visualization and "
|
|
1823
|
+
f"clustering. If you want a different aggregation, do it inside your function."
|
|
1824
|
+
),
|
|
1825
|
+
)
|
|
1826
|
+
|
|
1827
|
+
def inner_without_validate(sample_id, preprocess_response, instance_id):
|
|
1828
|
+
global _called_from_inside_tl_decorator
|
|
1829
|
+
_called_from_inside_tl_decorator += 1
|
|
1830
|
+
|
|
1831
|
+
try:
|
|
1832
|
+
result = user_function(sample_id, preprocess_response, instance_id)
|
|
1833
|
+
finally:
|
|
1834
|
+
_called_from_inside_tl_decorator -= 1
|
|
1835
|
+
|
|
1836
|
+
return result
|
|
1837
|
+
|
|
1838
|
+
leap_binder.set_custom_latent_space(inner_without_validate, ls_name,
|
|
1839
|
+
use_ls_for_analysis=use_ls_for_analysis, instance_aware=True)
|
|
1840
|
+
|
|
1841
|
+
def inner(sample_id, preprocess_response, instance_id):
|
|
1842
|
+
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
1843
|
+
return None
|
|
1844
|
+
|
|
1845
|
+
_validate_input_args(sample_id, preprocess_response, instance_id)
|
|
1846
|
+
|
|
1847
|
+
result = inner_without_validate(sample_id, preprocess_response, instance_id)
|
|
1848
|
+
|
|
1849
|
+
_validate_result(result)
|
|
1850
|
+
return result
|
|
1851
|
+
|
|
1852
|
+
return inner
|
|
1853
|
+
|
|
1854
|
+
return decorating_function
|
|
1855
|
+
|
|
1856
|
+
|
|
1810
1857
|
_MODEL_LOOP_MAX_STEPS = 1000
|
|
1811
1858
|
|
|
1812
1859
|
_active_model_loop = None
|
|
@@ -1904,16 +1951,11 @@ class _MappingStatePlaceholder:
|
|
|
1904
1951
|
|
|
1905
1952
|
|
|
1906
1953
|
class _ModelLoopContext:
|
|
1907
|
-
def __init__(self, sample_id, preprocess_response, prediction_names, is_mapping
|
|
1908
|
-
cache_tensors=None):
|
|
1954
|
+
def __init__(self, sample_id, preprocess_response, prediction_names, is_mapping):
|
|
1909
1955
|
self.sample_id = sample_id
|
|
1910
1956
|
self.preprocess_response = preprocess_response
|
|
1911
1957
|
self.prediction_names = prediction_names
|
|
1912
1958
|
self.is_mapping = is_mapping
|
|
1913
|
-
# Declared KV-cache, {model_input_name: model_output_name}. These tensors are supplied
|
|
1914
|
-
# by the loop (and by the platform at runtime), NOT by the hook, so both the fed-inputs
|
|
1915
|
-
# check and the output-count check have to account for them.
|
|
1916
|
-
self.cache_tensors = dict(cache_tensors or {})
|
|
1917
1959
|
self.phase = 'awaiting_first_hook'
|
|
1918
1960
|
self.steps = 0
|
|
1919
1961
|
self.fed_inputs = None
|
|
@@ -1922,9 +1964,6 @@ class _ModelLoopContext:
|
|
|
1922
1964
|
self.last_outputs_fingerprint = None
|
|
1923
1965
|
self.last_state = None
|
|
1924
1966
|
self.last_state_fingerprint = None
|
|
1925
|
-
# Declared-cache outputs of the last model call, in graph order (predictions first, so
|
|
1926
|
-
# this is the tail). Read by the loop through the model proxy.
|
|
1927
|
-
self.last_cache_outputs = []
|
|
1928
1967
|
|
|
1929
1968
|
def _fail(self, message):
|
|
1930
1969
|
raise LeapValidationError(f'tensorleap_model_loop validation failed: {message}')
|
|
@@ -2009,19 +2048,12 @@ class _ModelLoopContext:
|
|
|
2009
2048
|
'next_inputs the loop must exit without further hook or model calls.')
|
|
2010
2049
|
if self.is_mapping:
|
|
2011
2050
|
return
|
|
2012
|
-
# A declared KV-cache is threaded by the platform, so the hook neither receives nor
|
|
2013
|
-
# returns it and the loop is expected to supply it. Exclude those keys from the
|
|
2014
|
-
# identity check rather than demanding the hook produce tensors it cannot see.
|
|
2015
|
-
if isinstance(fed, dict) and self.cache_tensors:
|
|
2016
|
-
fed = {key: value for key, value in fed.items() if key not in self.cache_tensors}
|
|
2017
2051
|
fed_ids = {id(leaf) for leaf in _ndarray_leaves(fed)}
|
|
2018
2052
|
hook_ids = {id(value) for value in self.fed_inputs.values()}
|
|
2019
2053
|
if fed_ids != hook_ids:
|
|
2020
|
-
extra = (' (the declared KV-cache inputs are exempt — those are threaded for you)'
|
|
2021
|
-
if self.cache_tensors else '')
|
|
2022
2054
|
self._fail('the model must be fed exactly the tensors the last hook call returned — '
|
|
2023
2055
|
'any computation between the hook and the model is invisible to the '
|
|
2024
|
-
|
|
2056
|
+
'platform. Move it into the hook.')
|
|
2025
2057
|
if _nest_fingerprint(self.fed_inputs) != self.fed_inputs_fingerprint:
|
|
2026
2058
|
self._fail('the model inputs were mutated in place after the hook returned them — '
|
|
2027
2059
|
'the platform feeds the model the tensors exactly as the hook returned '
|
|
@@ -2033,24 +2065,12 @@ class _ModelLoopContext:
|
|
|
2033
2065
|
self.last_outputs = raw_outputs
|
|
2034
2066
|
return raw_outputs
|
|
2035
2067
|
outputs_list = raw_outputs if isinstance(raw_outputs, list) else [raw_outputs]
|
|
2036
|
-
|
|
2037
|
-
# and never reported, so they need no prediction type. Only the remainder is keyed.
|
|
2038
|
-
n_cache_outputs = len(self.cache_tensors)
|
|
2039
|
-
if len(outputs_list) - n_cache_outputs != len(self.prediction_names):
|
|
2040
|
-
cache_note = (f' ({n_cache_outputs} of them are the declared KV-cache, which needs '
|
|
2041
|
-
f'no prediction types)' if n_cache_outputs else '')
|
|
2068
|
+
if len(outputs_list) != len(self.prediction_names):
|
|
2042
2069
|
self._fail(f'the model returned {len(outputs_list)} outputs but '
|
|
2043
2070
|
f'{len(self.prediction_names)} prediction types are declared on '
|
|
2044
|
-
f'tensorleap_load_model
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
named_outputs = {name: np.asarray(output) for name, output
|
|
2048
|
-
in zip(self.prediction_names, outputs_list)}
|
|
2049
|
-
# The hook must receive predictions only, exactly as on the platform, and must receive
|
|
2050
|
-
# this very dict (on_hook_call checks identity). The loop still needs the cache, because
|
|
2051
|
-
# locally it stands in for the platform and threads it by hand — so that goes out on the
|
|
2052
|
-
# proxy rather than being mixed into the hook's view.
|
|
2053
|
-
self.last_cache_outputs = list(outputs_list[len(self.prediction_names):])
|
|
2071
|
+
f'tensorleap_load_model — declare one prediction type per model output.')
|
|
2072
|
+
named_outputs = {name: np.asarray(output)
|
|
2073
|
+
for name, output in zip(self.prediction_names, outputs_list)}
|
|
2054
2074
|
self.last_outputs = named_outputs
|
|
2055
2075
|
self.last_outputs_fingerprint = _nest_fingerprint(named_outputs)
|
|
2056
2076
|
return named_outputs
|
|
@@ -2072,20 +2092,8 @@ class _ModelLoopModelProxy:
|
|
|
2072
2092
|
def get_inputs(self):
|
|
2073
2093
|
return self._model.get_inputs()
|
|
2074
2094
|
|
|
2075
|
-
@property
|
|
2076
|
-
def cache_outputs(self):
|
|
2077
|
-
"""Declared-cache outputs of the last model call, in graph order.
|
|
2078
2095
|
|
|
2079
|
-
|
|
2080
|
-
for you at runtime. They are kept off the hook's `prev_outputs` deliberately — the hook
|
|
2081
|
-
must not see the cache in either place, or the local run would diverge from the real one.
|
|
2082
|
-
"""
|
|
2083
|
-
return self._context.last_cache_outputs
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step',
|
|
2087
|
-
cache_tensors: Optional[Dict[str, str]] = None,
|
|
2088
|
-
cache_seq_axis: int = DEFAULT_CACHE_SEQ_AXIS):
|
|
2096
|
+
def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step'):
|
|
2089
2097
|
"""The feedback hook that drives an autoregressive chain.
|
|
2090
2098
|
|
|
2091
2099
|
Signature of the decorated function:
|
|
@@ -2109,29 +2117,6 @@ def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step',
|
|
|
2109
2117
|
space comes from the final step's forward pass, except input-kind latent spaces which come
|
|
2110
2118
|
from the first step — the original sample, before generated content dominates the model
|
|
2111
2119
|
inputs. 'mean': every latent space is the elementwise mean over all steps of the chain.
|
|
2112
|
-
|
|
2113
|
-
cache_tensors declares a KV-cache (or any threaded state) as
|
|
2114
|
-
{model_input_name: model_output_name} — model inputs whose value is the named output from
|
|
2115
|
-
the previous step. The platform threads those tensors itself and holds them on the GPU, so
|
|
2116
|
-
the hook neither receives them in prev_inputs/prev_outputs nor returns them in next_inputs;
|
|
2117
|
-
return only the inputs you actually compute (e.g. input_ids, position_ids, attention_mask).
|
|
2118
|
-
The cache must be fixed-capacity: the declared input and output must have the same, fully
|
|
2119
|
-
concrete shape, since chains at different steps are batched together and the cache is
|
|
2120
|
-
preallocated. Exports with a growing cache (past length P in, P+1 out) are rejected at push.
|
|
2121
|
-
|
|
2122
|
-
@tensorleap_autoregressive_step(cache_tensors={
|
|
2123
|
-
f'past_key_values.{i}.{kv}': f'present.{i}.{kv}'
|
|
2124
|
-
for i in range(30) for kv in ('key', 'value')
|
|
2125
|
-
})
|
|
2126
|
-
|
|
2127
|
-
Omit it for a model with no cache — the chain then re-feeds its whole prompt every step.
|
|
2128
|
-
|
|
2129
|
-
cache_seq_axis declares which axis of those cache tensors indexes token positions — the axis
|
|
2130
|
-
whose length IS the cache capacity, which the platform reads to cap chain length. The default
|
|
2131
|
-
2 matches (batch, heads, position, head_dim), the layout HF-style exports produce. Set it
|
|
2132
|
-
when yours differs, e.g. 1 for (batch, position, heads, head_dim). It cannot be inferred: in
|
|
2133
|
-
a (1, 3, 64, 64) tensor two dims are 64, so a wrong guess would silently cap chains at the
|
|
2134
|
-
number of heads and truncate every chain a few steps in.
|
|
2135
2120
|
"""
|
|
2136
2121
|
assert isinstance(latent_space_aggregation, str), \
|
|
2137
2122
|
('tensorleap_autoregressive_step must be called with parentheses: '
|
|
@@ -2279,9 +2264,7 @@ def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step',
|
|
|
2279
2264
|
return result
|
|
2280
2265
|
|
|
2281
2266
|
leap_binder.set_autoregressive_step(inner_without_validate,
|
|
2282
|
-
latent_space_aggregation=latent_space_aggregation
|
|
2283
|
-
cache_tensors=cache_tensors,
|
|
2284
|
-
cache_seq_axis=cache_seq_axis)
|
|
2267
|
+
latent_space_aggregation=latent_space_aggregation)
|
|
2285
2268
|
|
|
2286
2269
|
def inner(*args, **kwargs):
|
|
2287
2270
|
if not _call_from_tl_platform:
|
|
@@ -2481,9 +2464,8 @@ def tensorleap_model_loop():
|
|
|
2481
2464
|
if not prediction_names:
|
|
2482
2465
|
_fail('tensorleap_model_loop requires prediction types declared on '
|
|
2483
2466
|
'tensorleap_load_model — the loop keys the model outputs by their names.')
|
|
2484
|
-
context = _ModelLoopContext(
|
|
2485
|
-
|
|
2486
|
-
cache_tensors=leap_binder.setup_container.autoregressive_step.cache_tensors)
|
|
2467
|
+
context = _ModelLoopContext(sample_id, preprocess_response, prediction_names,
|
|
2468
|
+
is_mapping)
|
|
2487
2469
|
_active_model_loop = context
|
|
2488
2470
|
try:
|
|
2489
2471
|
result = user_function(_ModelLoopModelProxy(model, context), sample_id,
|
|
@@ -2973,7 +2955,12 @@ def tensorleap_element_instance_preprocess(
|
|
|
2973
2955
|
instances_length = instance_length_encoder(sample_id, preprocess_response)
|
|
2974
2956
|
instances_ids = [f'{sample_id}_{instance_id}' for instance_id in range(instances_length)]
|
|
2975
2957
|
sample_ids_to_instance_mappings[sample_id] = instances_ids
|
|
2976
|
-
instance_to_sample_ids_mappings
|
|
2958
|
+
# Only instance ids belong in instance_to_sample_ids_mappings: the engine uses
|
|
2959
|
+
# membership in it as "is this row an element instance?" (custometl.py,
|
|
2960
|
+
# samplesgenerator.py). Mapping an original id to itself made that test true for
|
|
2961
|
+
# every image row, routing it into construct_instance_sample, where looking the
|
|
2962
|
+
# original up in its own instance list raises
|
|
2963
|
+
# "Index <id> with sample_id: <id> cannot be found!".
|
|
2977
2964
|
for idx, instance_id in enumerate(instances_ids):
|
|
2978
2965
|
if not found_instance_metadata:
|
|
2979
2966
|
element_instance = instance_mask_encoder(sample_id, preprocess_response, idx)
|
|
@@ -16,8 +16,7 @@ from code_loader.contract.datasetclasses import DatasetSample, DatasetBaseHandle
|
|
|
16
16
|
PreprocessResponse, VisualizerHandler, LeapData, \
|
|
17
17
|
PredictionTypeHandler, MetadataHandler, CustomLayerHandler, MetricHandler, VisualizerHandlerData, MetricHandlerData, \
|
|
18
18
|
MetricCallableReturnType, CustomLossHandlerData, CustomLossHandler, RawInputsForHeatmap, SamplePreprocessResponse, \
|
|
19
|
-
ElementInstance, custom_latent_space_attribute, DatasetIntegrationSetup, InstanceMetricHandler,
|
|
20
|
-
_simulation_context, DEFAULT_CACHE_SEQ_AXIS
|
|
19
|
+
ElementInstance, custom_latent_space_attribute, DatasetIntegrationSetup, InstanceMetricHandler, _simulation_context
|
|
21
20
|
from code_loader.contract.enums import DataStateEnum, TestingSectionEnum, DataStateType, DatasetMetadataType
|
|
22
21
|
from code_loader.contract.exceptions import DatasetScriptException
|
|
23
22
|
from code_loader.contract.responsedataclasses import DatasetIntegParseResult, DatasetTestResultPayload, \
|
|
@@ -284,7 +283,7 @@ class LeapLoader(LeapLoaderBase):
|
|
|
284
283
|
|
|
285
284
|
metadata, metadata_is_none = self.get_metadata(state, sample_id)
|
|
286
285
|
|
|
287
|
-
custom_latent_spaces = self._get_custom_latent_spaces(sample_id, preprocess_result[state])
|
|
286
|
+
custom_latent_spaces = self._get_custom_latent_spaces(sample_id, preprocess_result[state], instance_id)
|
|
288
287
|
instance_mask = self._get_instances_masks(state, sample_id, instance_id)
|
|
289
288
|
sample = DatasetSample(inputs=self._get_inputs(state, sample_id),
|
|
290
289
|
gt=None if state == DataStateEnum.unlabeled else self._get_gt(state, sample_id),
|
|
@@ -350,6 +349,9 @@ class LeapLoader(LeapLoaderBase):
|
|
|
350
349
|
global_leap_binder.validate_autoregressive_setup()
|
|
351
350
|
preprocess_test_payload = self._check_preprocess()
|
|
352
351
|
test_payloads.append(preprocess_test_payload)
|
|
352
|
+
instance_ls_test_payload = self._check_instance_custom_latent_spaces()
|
|
353
|
+
if instance_ls_test_payload is not None:
|
|
354
|
+
test_payloads.append(instance_ls_test_payload)
|
|
353
355
|
handlers_test_payloads = self._check_handlers()
|
|
354
356
|
test_payloads.extend(handlers_test_payloads)
|
|
355
357
|
simulation_test_payloads = self._check_simulations()
|
|
@@ -423,6 +425,37 @@ class LeapLoader(LeapLoaderBase):
|
|
|
423
425
|
test_result.is_passed = False
|
|
424
426
|
return test_result
|
|
425
427
|
|
|
428
|
+
def _check_instance_custom_latent_spaces(self) -> Optional[DatasetTestResultPayload]:
|
|
429
|
+
instance_aware_names = [
|
|
430
|
+
name for name, handler in global_leap_binder.setup_container.custom_latent_spaces.items()
|
|
431
|
+
if handler.instance_aware
|
|
432
|
+
]
|
|
433
|
+
if not instance_aware_names:
|
|
434
|
+
return None
|
|
435
|
+
|
|
436
|
+
test_result = DatasetTestResultPayload('instance_custom_latent_space')
|
|
437
|
+
errors = []
|
|
438
|
+
if not global_leap_binder.setup_container.instance_masks:
|
|
439
|
+
errors.append(
|
|
440
|
+
f"Instance-aware custom latent space(s) {instance_aware_names} require "
|
|
441
|
+
f"@tensorleap_instances_masks_encoder to be registered."
|
|
442
|
+
)
|
|
443
|
+
preprocess_result = self._preprocess_result()
|
|
444
|
+
has_instance_mappings = any(
|
|
445
|
+
preprocess_response.instance_to_sample_ids_mappings
|
|
446
|
+
for preprocess_response in preprocess_result.values()
|
|
447
|
+
)
|
|
448
|
+
if not has_instance_mappings:
|
|
449
|
+
errors.append(
|
|
450
|
+
f"Instance-aware custom latent space(s) {instance_aware_names} require the preprocess "
|
|
451
|
+
f"function to be decorated with @tensorleap_element_instance_preprocess("
|
|
452
|
+
f"instance_length_encoder, instance_mask_encoder)."
|
|
453
|
+
)
|
|
454
|
+
if errors:
|
|
455
|
+
test_result.is_passed = False
|
|
456
|
+
test_result.display[TestingSectionEnum.Errors.name] = "\n".join(errors)
|
|
457
|
+
return test_result
|
|
458
|
+
|
|
426
459
|
def _check_handlers(self) -> List[DatasetTestResultPayload]:
|
|
427
460
|
preprocess_result = self._preprocess_result()
|
|
428
461
|
result_payloads: List[DatasetTestResultPayload] = []
|
|
@@ -1108,6 +1141,9 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1108
1141
|
latent_handlers = global_leap_binder.setup_container.custom_latent_spaces
|
|
1109
1142
|
custom_latent_spaces = None
|
|
1110
1143
|
if latent_handlers:
|
|
1144
|
+
if any(handler.instance_aware for handler in latent_handlers.values()):
|
|
1145
|
+
raise Exception(
|
|
1146
|
+
"instance-aware custom latent spaces are not supported with grouped preprocess responses")
|
|
1111
1147
|
custom_latent_spaces = {
|
|
1112
1148
|
name: self._to_grouped_list(handler.function(group_ids, preprocess_state))
|
|
1113
1149
|
for name, handler in latent_handlers.items()
|
|
@@ -1330,17 +1366,29 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1330
1366
|
def _get_custom_latent_spaces(
|
|
1331
1367
|
self,
|
|
1332
1368
|
sample_id: Union[int, str],
|
|
1333
|
-
preprocess: "PreprocessResponse"
|
|
1369
|
+
preprocess: "PreprocessResponse",
|
|
1370
|
+
instance_id: Optional[int] = None) -> Optional[Dict[str, npt.NDArray[np.float32]]]:
|
|
1334
1371
|
handlers = global_leap_binder.setup_container.custom_latent_spaces
|
|
1335
1372
|
if not handlers:
|
|
1336
1373
|
return None
|
|
1337
1374
|
if preprocess.is_grouped:
|
|
1338
1375
|
# Single-sample fetch: encode this sample only, not the whole group (same
|
|
1339
1376
|
# memory rationale as _get_dataset_handlers; see grouped-fetch-oom-bug.md).
|
|
1377
|
+
if any(handler.instance_aware for handler in handlers.values()):
|
|
1378
|
+
raise Exception(
|
|
1379
|
+
"instance-aware custom latent spaces are not supported with grouped preprocess responses")
|
|
1340
1380
|
self._locate_group(preprocess, sample_id) # validates group membership
|
|
1341
1381
|
return {name: self._to_grouped_list(handler.function([sample_id], preprocess))[0]
|
|
1342
1382
|
for name, handler in handlers.items()}
|
|
1343
|
-
|
|
1383
|
+
result: Dict[str, npt.NDArray[np.float32]] = {}
|
|
1384
|
+
for name, handler in handlers.items():
|
|
1385
|
+
if handler.instance_aware:
|
|
1386
|
+
if instance_id is None:
|
|
1387
|
+
continue
|
|
1388
|
+
result[name] = handler.function(sample_id, preprocess, instance_id)
|
|
1389
|
+
else:
|
|
1390
|
+
result[name] = handler.function(sample_id, preprocess)
|
|
1391
|
+
return result
|
|
1344
1392
|
|
|
1345
1393
|
@lru_cache()
|
|
1346
1394
|
def has_custom_latent_space_decorator(self) -> bool:
|
|
@@ -1349,14 +1397,26 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1349
1397
|
|
|
1350
1398
|
@lru_cache()
|
|
1351
1399
|
def get_custom_latent_space_names(self) -> Tuple[str, ...]:
|
|
1352
|
-
"""
|
|
1400
|
+
"""Names of all registered custom latent spaces, in registration order.
|
|
1353
1401
|
|
|
1354
|
-
|
|
1355
|
-
|
|
1402
|
+
The engine resolves each name to its `user_custom_i` index by sorted name, not
|
|
1403
|
+
registration order, so this order is not the index mapping. Returns a tuple so the
|
|
1404
|
+
lru_cache value is hashable.
|
|
1356
1405
|
"""
|
|
1357
1406
|
self.exec_script()
|
|
1358
1407
|
return tuple(global_leap_binder.setup_container.custom_latent_spaces.keys())
|
|
1359
1408
|
|
|
1409
|
+
@lru_cache()
|
|
1410
|
+
def get_instance_custom_latent_space_names(self) -> Tuple[str, ...]:
|
|
1411
|
+
"""Names of registered custom latent spaces that are instance-aware.
|
|
1412
|
+
|
|
1413
|
+
Names, not indices — the engine resolves each name to its `user_custom_i` index
|
|
1414
|
+
by sorted name.
|
|
1415
|
+
"""
|
|
1416
|
+
self.exec_script()
|
|
1417
|
+
return tuple(name for name, handler in global_leap_binder.setup_container.custom_latent_spaces.items()
|
|
1418
|
+
if handler.instance_aware)
|
|
1419
|
+
|
|
1360
1420
|
@lru_cache()
|
|
1361
1421
|
def get_custom_latent_space_for_analysis(self) -> Optional[str]:
|
|
1362
1422
|
"""Name of the custom latent space flagged with use_ls_for_analysis=True, if any.
|
|
@@ -1383,34 +1443,6 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1383
1443
|
return 'last_step'
|
|
1384
1444
|
return handler.latent_space_aggregation
|
|
1385
1445
|
|
|
1386
|
-
@lru_cache()
|
|
1387
|
-
def get_autoregressive_cache_tensors(self) -> Dict[str, str]:
|
|
1388
|
-
"""Declared KV-cache pairing, {model_input_name: model_output_name}.
|
|
1389
|
-
|
|
1390
|
-
Empty when nothing is declared — the platform then runs the chain uncached. The platform
|
|
1391
|
-
validates these names against the real model graph at push time; only structural checks
|
|
1392
|
-
happen here.
|
|
1393
|
-
"""
|
|
1394
|
-
self.exec_script()
|
|
1395
|
-
handler = global_leap_binder.setup_container.autoregressive_step
|
|
1396
|
-
if handler is None or not handler.cache_tensors:
|
|
1397
|
-
return {}
|
|
1398
|
-
return dict(handler.cache_tensors)
|
|
1399
|
-
|
|
1400
|
-
@lru_cache()
|
|
1401
|
-
def get_autoregressive_cache_seq_axis(self) -> int:
|
|
1402
|
-
"""Which axis of the declared cache tensors indexes token positions.
|
|
1403
|
-
|
|
1404
|
-
The platform reads the cache capacity off this axis to cap chain length. Defaults to 2
|
|
1405
|
-
((batch, heads, position, head_dim)) — including when nothing is declared, where it is
|
|
1406
|
-
simply unused.
|
|
1407
|
-
"""
|
|
1408
|
-
self.exec_script()
|
|
1409
|
-
handler = global_leap_binder.setup_container.autoregressive_step
|
|
1410
|
-
if handler is None:
|
|
1411
|
-
return DEFAULT_CACHE_SEQ_AXIS
|
|
1412
|
-
return int(handler.cache_seq_axis)
|
|
1413
|
-
|
|
1414
1446
|
def run_autoregressive_step(self, sample_id: Union[int, str],
|
|
1415
1447
|
prev_inputs: Optional[Dict[str, npt.NDArray[np.float32]]],
|
|
1416
1448
|
prev_outputs: Optional[Dict[str, npt.NDArray[np.float32]]],
|
|
@@ -176,16 +176,6 @@ class LeapLoaderBase:
|
|
|
176
176
|
raise NotImplementedError(f'{type(self).__name__} does not implement '
|
|
177
177
|
'get_autoregressive_latent_space_aggregation.')
|
|
178
178
|
|
|
179
|
-
@abstractmethod
|
|
180
|
-
def get_autoregressive_cache_tensors(self) -> Dict[str, str]:
|
|
181
|
-
raise NotImplementedError(f'{type(self).__name__} does not implement '
|
|
182
|
-
'get_autoregressive_cache_tensors.')
|
|
183
|
-
|
|
184
|
-
@abstractmethod
|
|
185
|
-
def get_autoregressive_cache_seq_axis(self) -> int:
|
|
186
|
-
raise NotImplementedError(f'{type(self).__name__} does not implement '
|
|
187
|
-
'get_autoregressive_cache_seq_axis.')
|
|
188
|
-
|
|
189
179
|
@abstractmethod
|
|
190
180
|
def get_autoregressive_decorator_names(self) -> Dict[str, List[str]]:
|
|
191
181
|
raise NotImplementedError(f'{type(self).__name__} does not implement '
|
|
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.203 → code_loader-1.0.204.dev1}/code_loader/contract/responsedataclasses.py
RENAMED
|
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.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/cli_config_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/experiment_api/experiment_context.py
RENAMED
|
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.203 → code_loader-1.0.204.dev1}/code_loader/plot_functions/plot_functions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.203 → code_loader-1.0.204.dev1}/code_loader/visualizers/default_visualizers.py
RENAMED
|
File without changes
|