code-loader 1.0.205.dev2__tar.gz → 1.0.206__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.
Files changed (37) hide show
  1. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/PKG-INFO +1 -1
  2. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/contract/datasetclasses.py +4 -0
  3. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/contract/responsedataclasses.py +0 -2
  4. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/inner_leap_binder/leapbinder_decorators.py +69 -13
  5. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/leaploader.py +3 -19
  6. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/utils.py +9 -0
  7. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/pyproject.toml +1 -1
  8. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/LICENSE +0 -0
  9. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/README.md +0 -0
  10. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/__init__.py +0 -0
  11. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/contract/__init__.py +0 -0
  12. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/contract/enums.py +0 -0
  13. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/contract/exceptions.py +0 -0
  14. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/contract/mapping.py +0 -0
  15. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/contract/sim_config.py +0 -0
  16. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/contract/visualizer_classes.py +0 -0
  17. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/default_losses.py +0 -0
  18. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/default_metrics.py +0 -0
  19. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/__init__.py +0 -0
  20. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/api.py +0 -0
  21. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/cli_config_utils.py +0 -0
  22. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/client.py +0 -0
  23. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/epoch.py +0 -0
  24. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/experiment.py +0 -0
  25. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/experiment_context.py +0 -0
  26. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/types.py +0 -0
  27. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/utils.py +0 -0
  28. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
  29. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/inner_leap_binder/__init__.py +0 -0
  30. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/inner_leap_binder/leapbinder.py +0 -0
  31. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/leaploaderbase.py +0 -0
  32. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/mixpanel_tracker.py +0 -0
  33. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/plot_functions/__init__.py +0 -0
  34. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/plot_functions/plot_functions.py +0 -0
  35. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/plot_functions/visualize.py +0 -0
  36. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/visualizers/__init__.py +0 -0
  37. {code_loader-1.0.205.dev2 → code_loader-1.0.206}/code_loader/visualizers/default_visualizers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: code-loader
3
- Version: 1.0.205.dev2
3
+ Version: 1.0.206
4
4
  Summary:
5
5
  Home-page: https://github.com/tensorleap/code-loader
6
6
  License: MIT
@@ -143,6 +143,10 @@ class ElementInstance:
143
143
  name: str
144
144
  mask: npt.NDArray[np.float32]
145
145
  instance_metadata: Optional[Dict[str, Union[Optional[str], int, bool, Optional[float]]]] = None
146
+ # Per-key "this value is absent", the same pair shape DatasetSample carries. Populated at the
147
+ # masks funnel (utils.to_numpy_return_masks_wrapper) so the engine copies flags rather than
148
+ # deriving them, exactly as it does for sample-level metadata.
149
+ instance_metadata_is_none: Optional[Dict[str, bool]] = None
146
150
 
147
151
  SectionCallableInterface = Callable[[Union[int, str], PreprocessResponse], npt.NDArray[np.float32]]
148
152
  InstanceCallableInterface = Callable[[Union[int, str], PreprocessResponse, int], Optional[ElementInstance]]
@@ -86,8 +86,6 @@ class DatasetSetup:
86
86
  custom_losses: List[CustomLossInstance]
87
87
  metrics: List[MetricInstance] = field(default_factory=list)
88
88
  simulations: List[SimulationInstance] = field(default_factory=list)
89
- # Structural: the integration registered an element-instance mask encoder.
90
- has_element_instances: bool = False
91
89
 
92
90
 
93
91
  @dataclass
@@ -15,7 +15,7 @@ from typing import Optional, Union, Callable, List, Dict, get_args, get_origin,
15
15
  import numpy as np
16
16
  import numpy.typing as npt
17
17
 
18
- from code_loader.utils import get_metadata_type_from_variable, map_dict_to_metadata_types, \
18
+ from code_loader.utils import map_dict_to_metadata_types, is_absent_metadata_value, \
19
19
  validate_autoregressive_state_types, autoregressive_nests_equal, \
20
20
  simulate_engine_float16_downcast_on_call_args, ENGINE_STORAGE_DTYPE, \
21
21
  TL_DISABLE_ENGINE_FLOAT16_SIMULATION_ENV_VAR
@@ -27,7 +27,8 @@ from code_loader.contract.datasetclasses import CustomCallableInterfaceMultiArgs
27
27
  VisualizerCallableInterface, MetadataSectionCallableInterface, PreprocessResponse, SectionCallableInterface, \
28
28
  ConfusionMatrixElement, SamplePreprocessResponse, PredictionTypeHandler, InstanceCallableInterface, ElementInstance, \
29
29
  InstanceLengthCallableInterface, InstanceSectionCallableInterface, AutoregressiveStepCallableInterface
30
- from code_loader.contract.enums import MetricDirection, LeapDataType, DatasetMetadataType, DataStateType
30
+ from code_loader.contract.enums import MetricDirection, LeapDataType, DatasetMetadataType, DataStateType, \
31
+ DataStateEnum
31
32
  from code_loader import leap_binder, LeapLoader
32
33
  from code_loader.contract.mapping import NodeMapping, NodeMappingType, NodeConnection
33
34
  from code_loader.contract.visualizer_classes import LeapImage, LeapImageMask, LeapTextMask, LeapText, LeapGraph, \
@@ -2981,12 +2982,72 @@ def tensorleap_simulation(name: str, sim_params: dict):
2981
2982
 
2982
2983
 
2983
2984
  def tensorleap_element_instance_preprocess(
2984
- instance_length_encoder: InstanceLengthCallableInterface, instance_mask_encoder: InstanceCallableInterface):
2985
+ instance_length_encoder: InstanceLengthCallableInterface,
2986
+ instance_mask_encoder: InstanceCallableInterface,
2987
+ instance_metadata_types: Optional[Dict[str, DatasetMetadataType]] = None):
2985
2988
  def decorating_function(user_function: Callable[[], List[PreprocessResponse]]):
2989
+ def register_instance_extra_metadata(metadata_types: Dict[str, DatasetMetadataType]) -> None:
2990
+ # Idempotent: set_metadata appends without deduping, and the probe path runs inside
2991
+ # preprocess, so a second preprocess call would register a duplicate handler.
2992
+ if any(handler.name == "builtin_instance_extra_metadata"
2993
+ for handler in leap_binder.setup_container.metadata):
2994
+ return
2995
+ names = list(metadata_types)
2996
+
2997
+ def builtin_instance_extra_metadata(idx: str, preprocess: PreprocessResponse) -> Dict[str, None]:
2998
+ # Sample rows declare the columns without claiming values; the engine injects the
2999
+ # real per-instance ones. A fresh dict, because nulling the probed
3000
+ # ElementInstance's own dict in place destroyed any encoder that returned a
3001
+ # reference into preprocess.data.
3002
+ return {name: None for name in names}
3003
+
3004
+ leap_binder.set_metadata(builtin_instance_extra_metadata,
3005
+ "builtin_instance_extra_metadata", metadata_types)
3006
+
3007
+ def resolve_instance_metadata_types(sample_id: Union[int, str], preprocess_response: PreprocessResponse,
3008
+ idx: int) -> Optional[Dict[str, DatasetMetadataType]]:
3009
+ # The probe enumerates the KEYS; the declaration, where given, supplies the TYPE.
3010
+ element_instance = instance_mask_encoder(sample_id, preprocess_response, idx)
3011
+ if element_instance is None or element_instance.instance_metadata is None:
3012
+ return dict(instance_metadata_types) if instance_metadata_types else None
3013
+ metadata = element_instance.instance_metadata
3014
+ declared = instance_metadata_types or {}
3015
+ # A key absent here and undeclared has no type from either side. Mechanism (a)'s own
3016
+ # message, so both paths read the same, plus where to declare it.
3017
+ absent = [name for name, value in metadata.items()
3018
+ if name not in declared and is_absent_metadata_value(value)]
3019
+ if absent:
3020
+ raise Exception(
3021
+ f"Metadata {absent[0]} is None and no metadata type is provided. It is absent "
3022
+ f"on instance {idx} of sample {sample_id!r}, so the type cannot come from the "
3023
+ f"value -- declare it: tensorleap_element_instance_preprocess(..., "
3024
+ f"instance_metadata_types={{'{absent[0]}': DatasetMetadataType.float}}).")
3025
+ # Every present value goes through the same helper the sample path uses, which is also
3026
+ # what rejects an unsupported type -- so declaring a key cannot smuggle a list past
3027
+ # validation. The declaration then wins on type, and a declared key gets a column even
3028
+ # when the probed instance lacks it.
3029
+ inferred = map_dict_to_metadata_types(
3030
+ {name: value for name, value in metadata.items()
3031
+ if not is_absent_metadata_value(value)})
3032
+ return {**(inferred or {}), **declared}
3033
+
2986
3034
  def user_function_instance() -> List[PreprocessResponse]:
2987
3035
  result = user_function()
2988
3036
  found_instance_metadata = False
2989
- for preprocess_response in result:
3037
+ # Resolve types on training, as mechanism (a) does: only training is allowed to fail
3038
+ # on an unresolvable absence (leapbinder.check_handler). `state` is still None here when
3039
+ # the integration left it to position, which is how get_preprocess_result assigns it,
3040
+ # and position 0 is training. Rank training against the rest rather than sorting on the
3041
+ # state value: mixing enum values with positions in one key lets validation tie with
3042
+ # position 1 and stay ahead of training.
3043
+ def _is_training(i: int) -> bool:
3044
+ response = result[i]
3045
+ if response.state is not None:
3046
+ return response.state == DataStateType.training
3047
+ return i == 0
3048
+
3049
+ probe_order = sorted(range(len(result)), key=lambda i: (0 if _is_training(i) else 1, i))
3050
+ for preprocess_response in (result[i] for i in probe_order):
2990
3051
  if preprocess_response.is_grouped:
2991
3052
  raise Exception(
2992
3053
  "tensorleap_element_instance_preprocess validation failed: a grouped "
@@ -3009,15 +3070,10 @@ def tensorleap_element_instance_preprocess(
3009
3070
  # "Index <id> with sample_id: <id> cannot be found!".
3010
3071
  for idx, instance_id in enumerate(instances_ids):
3011
3072
  if not found_instance_metadata:
3012
- element_instance = instance_mask_encoder(sample_id, preprocess_response, idx)
3013
- element_instance_metadata = element_instance.instance_metadata
3014
- if element_instance_metadata is not None:
3015
- element_instance_metadata_types = map_dict_to_metadata_types(element_instance_metadata)
3016
- def builtin_instance_extra_metadata(idx: str, preprocess: PreprocessResponse) -> Dict[str, str]:
3017
- for k, v in element_instance_metadata.items():
3018
- element_instance_metadata[k] = None
3019
- return element_instance_metadata
3020
- leap_binder.set_metadata(builtin_instance_extra_metadata,"builtin_instance_extra_metadata", element_instance_metadata_types)
3073
+ resolved_types = resolve_instance_metadata_types(
3074
+ sample_id, preprocess_response, idx)
3075
+ if resolved_types:
3076
+ register_instance_extra_metadata(resolved_types)
3021
3077
  found_instance_metadata = True
3022
3078
 
3023
3079
  instance_to_sample_ids_mappings[instance_id] = sample_id
@@ -28,7 +28,7 @@ from code_loader.inner_leap_binder import global_leap_binder
28
28
  from code_loader.inner_leap_binder.leapbinder import mapping_runtime_mode_env_var_mame
29
29
  from code_loader.leaploaderbase import LeapLoaderBase
30
30
  from code_loader.utils import get_root_exception_file_and_line_number, get_metadata_type_from_variable, \
31
- validate_autoregressive_state_types, autoregressive_nests_equal
31
+ validate_autoregressive_state_types, autoregressive_nests_equal, is_absent_metadata_value
32
32
 
33
33
 
34
34
  def _serialize_sim_bounds(bounds) -> dict:
@@ -935,23 +935,7 @@ class LeapLoader(LeapLoaderBase):
935
935
 
936
936
  return DatasetSetup(preprocess=dataset_preprocess, inputs=inputs, outputs=ground_truths,
937
937
  metadata=metadata_instances, visualizers=visualizers, prediction_types=prediction_types,
938
- custom_losses=custom_losses, metrics=metrics, simulations=simulations,
939
- has_element_instances=self._has_element_instances())
940
-
941
- def _has_element_instances(self) -> bool:
942
- """Does this dataset have element instances? Both halves, because either alone lies.
943
-
944
- A registered mask encoder without instance mappings is an integration that declares
945
- instances and produces none: the engine would take the pooling path with nothing to pool,
946
- and ask the UI to visualize an instance population that does not exist. Mappings without an
947
- encoder cannot be masked. Preprocessing has already run by the time this is called (the
948
- lengths above come from it), so reading the mappings costs nothing extra.
949
- """
950
- setup = global_leap_binder.setup_container
951
- if not setup.instance_masks:
952
- return False
953
- return any(response.instance_to_sample_ids_mappings
954
- for response in self._preprocess_result().values())
938
+ custom_losses=custom_losses, metrics=metrics, simulations=simulations)
955
939
 
956
940
  def get_model_setup_response(self) -> ModelSetup:
957
941
  setup = global_leap_binder.setup_container
@@ -1244,7 +1228,7 @@ class LeapLoader(LeapLoaderBase):
1244
1228
 
1245
1229
  try:
1246
1230
  is_none = False
1247
- if value is None or (isinstance(value, (int, float, np.integer, np.floating)) and not np.isfinite(value)):
1231
+ if is_absent_metadata_value(value):
1248
1232
  raise ValueError()
1249
1233
  converted_value = metadata_type_to_python_type[metadata_name_to_type[metadata_name]](value)
1250
1234
  except ValueError:
@@ -15,6 +15,12 @@ from code_loader.contract.datasetclasses import SectionCallableInterface, Prepro
15
15
  from code_loader.contract.enums import DatasetMetadataType
16
16
 
17
17
 
18
+ def is_absent_metadata_value(value: Any) -> bool:
19
+ """The one definition of an absent metadata value, shared by every mechanism."""
20
+ return value is None or (isinstance(value, (int, float, np.integer, np.floating))
21
+ and not np.isfinite(value))
22
+
23
+
18
24
  def to_numpy_return_wrapper(encoder_function: SectionCallableInterface) -> SectionCallableInterface:
19
25
  def numpy_encoder_function(idx: Union[int, str], samples: PreprocessResponse) -> npt.NDArray[np.float32]:
20
26
  result = encoder_function(idx, samples)
@@ -39,6 +45,9 @@ def to_numpy_return_masks_wrapper(encoder_function: InstanceCallableInterface) -
39
45
  if result is None:
40
46
  return None
41
47
  result.mask = np.array(result.mask)
48
+ if result.instance_metadata is not None and result.instance_metadata_is_none is None:
49
+ result.instance_metadata_is_none = {
50
+ k: is_absent_metadata_value(v) for k, v in result.instance_metadata.items()}
42
51
  return result
43
52
  return numpy_encoder_function
44
53
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "code-loader"
3
- version = "1.0.205.dev2"
3
+ version = "1.0.206"
4
4
  description = ""
5
5
  authors = ["dorhar <doron.harnoy@tensorleap.ai>"]
6
6
  license = "MIT"