code-loader 1.0.202.dev0__tar.gz → 1.0.203.dev0__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.202.dev0 → code_loader-1.0.203.dev0}/PKG-INFO +3 -4
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/datasetclasses.py +0 -5
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/inner_leap_binder/leapbinder.py +26 -49
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/inner_leap_binder/leapbinder_decorators.py +15 -113
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/leaploader.py +0 -14
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/leaploaderbase.py +0 -5
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/pyproject.toml +1 -1
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/LICENSE +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/README.md +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/__init__.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/__init__.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/enums.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/exceptions.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/mapping.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/responsedataclasses.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/sim_config.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/visualizer_classes.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/default_losses.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/default_metrics.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/__init__.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/api.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/cli_config_utils.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/client.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/epoch.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/experiment.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/experiment_context.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/types.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/utils.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/inner_leap_binder/__init__.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/mixpanel_tracker.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/plot_functions/__init__.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/plot_functions/plot_functions.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/plot_functions/visualize.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/utils.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/visualizers/__init__.py +0 -0
- {code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/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.203.dev0
|
|
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
|
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/datasetclasses.py
RENAMED
|
@@ -332,11 +332,6 @@ class AutoregressiveStepHandler:
|
|
|
332
332
|
# time. Fills the role InputHandler.shape plays for input encoders.
|
|
333
333
|
input_shapes: Optional[Dict[str, List[int]]] = None
|
|
334
334
|
latent_space_aggregation: str = 'last_step'
|
|
335
|
-
# {model_input_name: model_output_name} for a KV-cache (or any threaded state): inputs whose
|
|
336
|
-
# value is the named output from the previous step. The platform threads these itself — they
|
|
337
|
-
# are never passed to the hook and never reported — so the hook must NOT return them. Empty
|
|
338
|
-
# when the model has no cache, in which case the chain re-feeds its full prompt each step.
|
|
339
|
-
cache_tensors: Optional[Dict[str, str]] = None
|
|
340
335
|
|
|
341
336
|
|
|
342
337
|
# Per-chain, unbatched callables: called once per finished chain with the final step's tensors —
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/inner_leap_binder/leapbinder.py
RENAMED
|
@@ -590,41 +590,8 @@ class LeapBinder:
|
|
|
590
590
|
self.setup_container.custom_latent_spaces[name] = CustomLatentSpaceHandler(
|
|
591
591
|
function, name, use_ls_for_analysis)
|
|
592
592
|
|
|
593
|
-
@staticmethod
|
|
594
|
-
def _validated_cache_tensors(cache_tensors: Optional[Dict[str, str]]
|
|
595
|
-
) -> Optional[Dict[str, str]]:
|
|
596
|
-
"""Structural checks only — shape/dtype/existence are validated by the platform, which
|
|
597
|
-
is the side that has the model graph. This catches the typos that are cheap to catch
|
|
598
|
-
here, at integration-test time, instead of at push."""
|
|
599
|
-
if not cache_tensors:
|
|
600
|
-
return None
|
|
601
|
-
if not isinstance(cache_tensors, dict):
|
|
602
|
-
raise Exception(f'tensorleap_autoregressive_step: cache_tensors must be a dict of '
|
|
603
|
-
f'{{model_input_name: model_output_name}}, got '
|
|
604
|
-
f'{type(cache_tensors).__name__}.')
|
|
605
|
-
seen_outputs: Dict[str, str] = {}
|
|
606
|
-
for input_name, output_name in cache_tensors.items():
|
|
607
|
-
for role, name in (('key', input_name), ('value', output_name)):
|
|
608
|
-
if not isinstance(name, str) or not name:
|
|
609
|
-
raise Exception(
|
|
610
|
-
f'tensorleap_autoregressive_step: cache_tensors {role}s must be '
|
|
611
|
-
f'non-empty model tensor names, got {name!r}.')
|
|
612
|
-
if input_name == output_name:
|
|
613
|
-
raise Exception(
|
|
614
|
-
f'tensorleap_autoregressive_step: cache_tensors maps "{input_name}" to '
|
|
615
|
-
f'itself. A model input and output cannot share a name — the mapping is '
|
|
616
|
-
f'{{input_name: output_name}}.')
|
|
617
|
-
if output_name in seen_outputs:
|
|
618
|
-
raise Exception(
|
|
619
|
-
f'tensorleap_autoregressive_step: model output "{output_name}" is declared '
|
|
620
|
-
f'as the cache source for both "{seen_outputs[output_name]}" and '
|
|
621
|
-
f'"{input_name}". Each cache output feeds exactly one input.')
|
|
622
|
-
seen_outputs[output_name] = input_name
|
|
623
|
-
return dict(cache_tensors)
|
|
624
|
-
|
|
625
593
|
def set_autoregressive_step(self, function: AutoregressiveStepCallableInterface,
|
|
626
|
-
latent_space_aggregation: str = 'last_step'
|
|
627
|
-
cache_tensors: Optional[Dict[str, str]] = None) -> None:
|
|
594
|
+
latent_space_aggregation: str = 'last_step') -> None:
|
|
628
595
|
"""
|
|
629
596
|
Set the autoregressive step hook — the feedback function that drives a chain:
|
|
630
597
|
it supplies the model's initial inputs on its first call (prev_inputs=None, prev_outputs=None)
|
|
@@ -632,8 +599,6 @@ class LeapBinder:
|
|
|
632
599
|
An autoregressive integration has no input encoders; the hook is the sole input source.
|
|
633
600
|
latent_space_aggregation declares how the chain's latent-space vectors are derived from
|
|
634
601
|
its steps (see AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS).
|
|
635
|
-
cache_tensors declares a KV-cache as {model_input_name: model_output_name}; the platform
|
|
636
|
-
threads those tensors itself and the hook neither receives nor returns them.
|
|
637
602
|
"""
|
|
638
603
|
if self.setup_container.autoregressive_step is not None:
|
|
639
604
|
raise Exception('tensorleap_autoregressive_step is already defined. '
|
|
@@ -642,10 +607,8 @@ class LeapBinder:
|
|
|
642
607
|
raise Exception(f'tensorleap_autoregressive_step: unknown latent_space_aggregation '
|
|
643
608
|
f'{latent_space_aggregation!r}. Supported values: '
|
|
644
609
|
f'{", ".join(AUTOREGRESSIVE_LATENT_SPACE_AGGREGATIONS)}.')
|
|
645
|
-
cache_tensors = self._validated_cache_tensors(cache_tensors)
|
|
646
610
|
self.setup_container.autoregressive_step = AutoregressiveStepHandler(
|
|
647
|
-
function, latent_space_aggregation=latent_space_aggregation
|
|
648
|
-
cache_tensors=cache_tensors)
|
|
611
|
+
function, latent_space_aggregation=latent_space_aggregation)
|
|
649
612
|
|
|
650
613
|
# Builtin chain metadata, declared at parse time so it survives the reporter's
|
|
651
614
|
# metadata type mapping; the placeholder values are overwritten by the engine when a
|
|
@@ -1054,17 +1017,18 @@ class LeapBinder:
|
|
|
1054
1017
|
|
|
1055
1018
|
Each entry must be one of:
|
|
1056
1019
|
- "foreground" (the friendly name for the max-pooled default LS)
|
|
1020
|
+
- "balanced" (the friendly name for the universal fallback default LS),
|
|
1021
|
+
allowed only when a custom latent space is registered with
|
|
1022
|
+
use_ls_for_analysis=True — that flagged LS is what replaces it
|
|
1057
1023
|
- An input name registered via set_input(name=...)
|
|
1058
1024
|
- A prediction name registered via add_prediction(name=...)
|
|
1059
1025
|
|
|
1060
1026
|
Forbidden tokens (raise with a clear message):
|
|
1061
|
-
- "balanced" — the friendly name for the universal fallback default
|
|
1062
|
-
LS; cannot be disabled.
|
|
1063
1027
|
- "user_custom" — populated by set_custom_latent_space; if the user
|
|
1064
1028
|
registered a custom LS they should use it, not ignore it.
|
|
1065
1029
|
|
|
1066
|
-
Order-independent: this runs after all set_input / add_prediction
|
|
1067
|
-
because it consults setup_container.
|
|
1030
|
+
Order-independent: this runs after all set_input / add_prediction /
|
|
1031
|
+
set_custom_latent_space calls because it consults setup_container.
|
|
1068
1032
|
"""
|
|
1069
1033
|
if not self.leap_analysis_configuration:
|
|
1070
1034
|
return
|
|
@@ -1072,24 +1036,37 @@ class LeapBinder:
|
|
|
1072
1036
|
if not names:
|
|
1073
1037
|
return
|
|
1074
1038
|
|
|
1075
|
-
forbidden = {"
|
|
1039
|
+
forbidden = {"user_custom"}
|
|
1076
1040
|
input_names = {h.name for h in self.setup_container.inputs}
|
|
1077
1041
|
prediction_names = {h.name for h in self.setup_container.prediction_types}
|
|
1078
|
-
allowed_tokens = {"foreground"} | input_names | prediction_names
|
|
1042
|
+
allowed_tokens = {"foreground", "balanced"} | input_names | prediction_names
|
|
1043
|
+
analysis_ls_names = [
|
|
1044
|
+
ls_name
|
|
1045
|
+
for ls_name, handler in self.setup_container.custom_latent_spaces.items()
|
|
1046
|
+
if handler.use_ls_for_analysis
|
|
1047
|
+
]
|
|
1079
1048
|
|
|
1080
1049
|
for name in names:
|
|
1081
1050
|
if name in forbidden:
|
|
1082
1051
|
raise Exception(
|
|
1083
|
-
f"Latent space '{name}' cannot be ignored. "
|
|
1084
|
-
f"
|
|
1085
|
-
|
|
1052
|
+
f"Latent space '{name}' cannot be ignored. 'user_custom' is reserved "
|
|
1053
|
+
f"for set_custom_latent_space."
|
|
1054
|
+
)
|
|
1055
|
+
if name == "balanced" and not analysis_ls_names:
|
|
1056
|
+
raise Exception(
|
|
1057
|
+
"Latent space 'balanced' (the model-derived default latent space) can "
|
|
1058
|
+
"only be ignored when a replacement is registered. Add "
|
|
1059
|
+
"@tensorleap_custom_latent_space(..., use_ls_for_analysis=True) to the "
|
|
1060
|
+
"latent space that should be analyzed instead, or drop 'balanced' from "
|
|
1061
|
+
"ignore_latent_spaces — ignoring it with nothing in its place would "
|
|
1062
|
+
"leave the analyses with no latent space."
|
|
1086
1063
|
)
|
|
1087
1064
|
if name not in allowed_tokens:
|
|
1088
1065
|
raise Exception(
|
|
1089
1066
|
f"Latent space name '{name}' in ignore_latent_spaces did not match "
|
|
1090
1067
|
f"any registered input or prediction. Available names: "
|
|
1091
1068
|
f"inputs={sorted(input_names)}, predictions={sorted(prediction_names)}, "
|
|
1092
|
-
f"tokens=['foreground']."
|
|
1069
|
+
f"tokens=['foreground', 'balanced']."
|
|
1093
1070
|
)
|
|
1094
1071
|
|
|
1095
1072
|
def set_batch_size_to_validate(self, batch_size: int) -> None:
|
|
@@ -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]
|
|
@@ -1893,29 +1883,12 @@ class _MappingStatePlaceholder:
|
|
|
1893
1883
|
self._unsupported()
|
|
1894
1884
|
|
|
1895
1885
|
|
|
1896
|
-
def _shares_base(leaf, original):
|
|
1897
|
-
"""True when `leaf` is `original` or a view onto it (e.g. original[None])."""
|
|
1898
|
-
if leaf is original:
|
|
1899
|
-
return True
|
|
1900
|
-
base = getattr(leaf, 'base', None)
|
|
1901
|
-
while base is not None:
|
|
1902
|
-
if base is original:
|
|
1903
|
-
return True
|
|
1904
|
-
base = getattr(base, 'base', None)
|
|
1905
|
-
return False
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
1886
|
class _ModelLoopContext:
|
|
1909
|
-
def __init__(self, sample_id, preprocess_response, prediction_names, is_mapping
|
|
1910
|
-
cache_tensors=None):
|
|
1887
|
+
def __init__(self, sample_id, preprocess_response, prediction_names, is_mapping):
|
|
1911
1888
|
self.sample_id = sample_id
|
|
1912
1889
|
self.preprocess_response = preprocess_response
|
|
1913
1890
|
self.prediction_names = prediction_names
|
|
1914
1891
|
self.is_mapping = is_mapping
|
|
1915
|
-
# Declared KV-cache, {model_input_name: model_output_name}. These tensors are supplied
|
|
1916
|
-
# by the loop (and by the platform at runtime), NOT by the hook, so both the fed-inputs
|
|
1917
|
-
# check and the output-count check have to account for them.
|
|
1918
|
-
self.cache_tensors = dict(cache_tensors or {})
|
|
1919
1892
|
self.phase = 'awaiting_first_hook'
|
|
1920
1893
|
self.steps = 0
|
|
1921
1894
|
self.fed_inputs = None
|
|
@@ -1924,9 +1897,6 @@ class _ModelLoopContext:
|
|
|
1924
1897
|
self.last_outputs_fingerprint = None
|
|
1925
1898
|
self.last_state = None
|
|
1926
1899
|
self.last_state_fingerprint = None
|
|
1927
|
-
# Declared-cache outputs of the last model call, in graph order (predictions first, so
|
|
1928
|
-
# this is the tail). Read by the loop through the model proxy.
|
|
1929
|
-
self.last_cache_outputs = []
|
|
1930
1900
|
|
|
1931
1901
|
def _fail(self, message):
|
|
1932
1902
|
raise LeapValidationError(f'tensorleap_model_loop validation failed: {message}')
|
|
@@ -2011,39 +1981,12 @@ class _ModelLoopContext:
|
|
|
2011
1981
|
'next_inputs the loop must exit without further hook or model calls.')
|
|
2012
1982
|
if self.is_mapping:
|
|
2013
1983
|
return
|
|
2014
|
-
|
|
2015
|
-
# returns it and the loop is expected to supply it. Exclude those keys from the
|
|
2016
|
-
# identity check rather than demanding the hook produce tensors it cannot see.
|
|
2017
|
-
if isinstance(fed, dict) and self.cache_tensors:
|
|
2018
|
-
fed = {key: value for key, value in fed.items() if key not in self.cache_tensors}
|
|
1984
|
+
fed_ids = {id(leaf) for leaf in _ndarray_leaves(fed)}
|
|
2019
1985
|
hook_ids = {id(value) for value in self.fed_inputs.values()}
|
|
2020
|
-
|
|
2021
|
-
# axis an ONNX model needs and shares its memory, so `.base` is the original. Allowing
|
|
2022
|
-
# views keeps the guarantee that matters — no tensor may be COMPUTED between the hook
|
|
2023
|
-
# and the model, since the platform would not see that work — while not forcing every
|
|
2024
|
-
# integration to choose between the identity check and a model that expects a batch
|
|
2025
|
-
# dimension. A genuinely new array has no base among the hook's tensors.
|
|
2026
|
-
def _from_hook(leaf):
|
|
2027
|
-
if id(leaf) in hook_ids:
|
|
2028
|
-
return True
|
|
2029
|
-
base = getattr(leaf, 'base', None)
|
|
2030
|
-
while base is not None:
|
|
2031
|
-
if id(base) in hook_ids:
|
|
2032
|
-
return True
|
|
2033
|
-
base = getattr(base, 'base', None)
|
|
2034
|
-
return False
|
|
2035
|
-
|
|
2036
|
-
fed_leaves = list(_ndarray_leaves(fed))
|
|
2037
|
-
matched = {id(value) for value in self.fed_inputs.values()
|
|
2038
|
-
if any(_from_hook(leaf) and (id(leaf) == id(value)
|
|
2039
|
-
or _shares_base(leaf, value))
|
|
2040
|
-
for leaf in fed_leaves)}
|
|
2041
|
-
if not all(_from_hook(leaf) for leaf in fed_leaves) or matched != hook_ids:
|
|
2042
|
-
extra = (' (the declared KV-cache inputs are exempt — those are threaded for you)'
|
|
2043
|
-
if self.cache_tensors else '')
|
|
1986
|
+
if fed_ids != hook_ids:
|
|
2044
1987
|
self._fail('the model must be fed exactly the tensors the last hook call returned — '
|
|
2045
1988
|
'any computation between the hook and the model is invisible to the '
|
|
2046
|
-
|
|
1989
|
+
'platform. Move it into the hook.')
|
|
2047
1990
|
if _nest_fingerprint(self.fed_inputs) != self.fed_inputs_fingerprint:
|
|
2048
1991
|
self._fail('the model inputs were mutated in place after the hook returned them — '
|
|
2049
1992
|
'the platform feeds the model the tensors exactly as the hook returned '
|
|
@@ -2055,24 +1998,12 @@ class _ModelLoopContext:
|
|
|
2055
1998
|
self.last_outputs = raw_outputs
|
|
2056
1999
|
return raw_outputs
|
|
2057
2000
|
outputs_list = raw_outputs if isinstance(raw_outputs, list) else [raw_outputs]
|
|
2058
|
-
|
|
2059
|
-
# and never reported, so they need no prediction type. Only the remainder is keyed.
|
|
2060
|
-
n_cache_outputs = len(self.cache_tensors)
|
|
2061
|
-
if len(outputs_list) - n_cache_outputs != len(self.prediction_names):
|
|
2062
|
-
cache_note = (f' ({n_cache_outputs} of them are the declared KV-cache, which needs '
|
|
2063
|
-
f'no prediction types)' if n_cache_outputs else '')
|
|
2001
|
+
if len(outputs_list) != len(self.prediction_names):
|
|
2064
2002
|
self._fail(f'the model returned {len(outputs_list)} outputs but '
|
|
2065
2003
|
f'{len(self.prediction_names)} prediction types are declared on '
|
|
2066
|
-
f'tensorleap_load_model
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
named_outputs = {name: np.asarray(output) for name, output
|
|
2070
|
-
in zip(self.prediction_names, outputs_list)}
|
|
2071
|
-
# The hook must receive predictions only, exactly as on the platform, and must receive
|
|
2072
|
-
# this very dict (on_hook_call checks identity). The loop still needs the cache, because
|
|
2073
|
-
# locally it stands in for the platform and threads it by hand — so that goes out on the
|
|
2074
|
-
# proxy rather than being mixed into the hook's view.
|
|
2075
|
-
self.last_cache_outputs = list(outputs_list[len(self.prediction_names):])
|
|
2004
|
+
f'tensorleap_load_model — declare one prediction type per model output.')
|
|
2005
|
+
named_outputs = {name: np.asarray(output)
|
|
2006
|
+
for name, output in zip(self.prediction_names, outputs_list)}
|
|
2076
2007
|
self.last_outputs = named_outputs
|
|
2077
2008
|
self.last_outputs_fingerprint = _nest_fingerprint(named_outputs)
|
|
2078
2009
|
return named_outputs
|
|
@@ -2094,19 +2025,8 @@ class _ModelLoopModelProxy:
|
|
|
2094
2025
|
def get_inputs(self):
|
|
2095
2026
|
return self._model.get_inputs()
|
|
2096
2027
|
|
|
2097
|
-
@property
|
|
2098
|
-
def cache_outputs(self):
|
|
2099
|
-
"""Declared-cache outputs of the last model call, in graph order.
|
|
2100
|
-
|
|
2101
|
-
Only the local loop needs these: it stands in for the platform, which threads the cache
|
|
2102
|
-
for you at runtime. They are kept off the hook's `prev_outputs` deliberately — the hook
|
|
2103
|
-
must not see the cache in either place, or the local run would diverge from the real one.
|
|
2104
|
-
"""
|
|
2105
|
-
return self._context.last_cache_outputs
|
|
2106
2028
|
|
|
2107
|
-
|
|
2108
|
-
def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step',
|
|
2109
|
-
cache_tensors: Optional[Dict[str, str]] = None):
|
|
2029
|
+
def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step'):
|
|
2110
2030
|
"""The feedback hook that drives an autoregressive chain.
|
|
2111
2031
|
|
|
2112
2032
|
Signature of the decorated function:
|
|
@@ -2130,22 +2050,6 @@ def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step',
|
|
|
2130
2050
|
space comes from the final step's forward pass, except input-kind latent spaces which come
|
|
2131
2051
|
from the first step — the original sample, before generated content dominates the model
|
|
2132
2052
|
inputs. 'mean': every latent space is the elementwise mean over all steps of the chain.
|
|
2133
|
-
|
|
2134
|
-
cache_tensors declares a KV-cache (or any threaded state) as
|
|
2135
|
-
{model_input_name: model_output_name} — model inputs whose value is the named output from
|
|
2136
|
-
the previous step. The platform threads those tensors itself and holds them on the GPU, so
|
|
2137
|
-
the hook neither receives them in prev_inputs/prev_outputs nor returns them in next_inputs;
|
|
2138
|
-
return only the inputs you actually compute (e.g. input_ids, position_ids, attention_mask).
|
|
2139
|
-
The cache must be fixed-capacity: the declared input and output must have the same, fully
|
|
2140
|
-
concrete shape, since chains at different steps are batched together and the cache is
|
|
2141
|
-
preallocated. Exports with a growing cache (past length P in, P+1 out) are rejected at push.
|
|
2142
|
-
|
|
2143
|
-
@tensorleap_autoregressive_step(cache_tensors={
|
|
2144
|
-
f'past_key_values.{i}.{kv}': f'present.{i}.{kv}'
|
|
2145
|
-
for i in range(30) for kv in ('key', 'value')
|
|
2146
|
-
})
|
|
2147
|
-
|
|
2148
|
-
Omit it for a model with no cache — the chain then re-feeds its whole prompt every step.
|
|
2149
2053
|
"""
|
|
2150
2054
|
assert isinstance(latent_space_aggregation, str), \
|
|
2151
2055
|
('tensorleap_autoregressive_step must be called with parentheses: '
|
|
@@ -2293,8 +2197,7 @@ def tensorleap_autoregressive_step(latent_space_aggregation: str = 'last_step',
|
|
|
2293
2197
|
return result
|
|
2294
2198
|
|
|
2295
2199
|
leap_binder.set_autoregressive_step(inner_without_validate,
|
|
2296
|
-
latent_space_aggregation=latent_space_aggregation
|
|
2297
|
-
cache_tensors=cache_tensors)
|
|
2200
|
+
latent_space_aggregation=latent_space_aggregation)
|
|
2298
2201
|
|
|
2299
2202
|
def inner(*args, **kwargs):
|
|
2300
2203
|
if not _call_from_tl_platform:
|
|
@@ -2494,9 +2397,8 @@ def tensorleap_model_loop():
|
|
|
2494
2397
|
if not prediction_names:
|
|
2495
2398
|
_fail('tensorleap_model_loop requires prediction types declared on '
|
|
2496
2399
|
'tensorleap_load_model — the loop keys the model outputs by their names.')
|
|
2497
|
-
context = _ModelLoopContext(
|
|
2498
|
-
|
|
2499
|
-
cache_tensors=leap_binder.setup_container.autoregressive_step.cache_tensors)
|
|
2400
|
+
context = _ModelLoopContext(sample_id, preprocess_response, prediction_names,
|
|
2401
|
+
is_mapping)
|
|
2500
2402
|
_active_model_loop = context
|
|
2501
2403
|
try:
|
|
2502
2404
|
result = user_function(_ModelLoopModelProxy(model, context), sample_id,
|
|
@@ -1382,20 +1382,6 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1382
1382
|
return 'last_step'
|
|
1383
1383
|
return handler.latent_space_aggregation
|
|
1384
1384
|
|
|
1385
|
-
@lru_cache()
|
|
1386
|
-
def get_autoregressive_cache_tensors(self) -> Dict[str, str]:
|
|
1387
|
-
"""Declared KV-cache pairing, {model_input_name: model_output_name}.
|
|
1388
|
-
|
|
1389
|
-
Empty when nothing is declared — the platform then runs the chain uncached. The platform
|
|
1390
|
-
validates these names against the real model graph at push time; only structural checks
|
|
1391
|
-
happen here.
|
|
1392
|
-
"""
|
|
1393
|
-
self.exec_script()
|
|
1394
|
-
handler = global_leap_binder.setup_container.autoregressive_step
|
|
1395
|
-
if handler is None or not handler.cache_tensors:
|
|
1396
|
-
return {}
|
|
1397
|
-
return dict(handler.cache_tensors)
|
|
1398
|
-
|
|
1399
1385
|
def run_autoregressive_step(self, sample_id: Union[int, str],
|
|
1400
1386
|
prev_inputs: Optional[Dict[str, npt.NDArray[np.float32]]],
|
|
1401
1387
|
prev_outputs: Optional[Dict[str, npt.NDArray[np.float32]]],
|
|
@@ -176,11 +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
179
|
@abstractmethod
|
|
185
180
|
def get_autoregressive_decorator_names(self) -> Dict[str, List[str]]:
|
|
186
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.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/responsedataclasses.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/contract/visualizer_classes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/cli_config_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/experiment_api/experiment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/inner_leap_binder/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/plot_functions/__init__.py
RENAMED
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/plot_functions/plot_functions.py
RENAMED
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/plot_functions/visualize.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.202.dev0 → code_loader-1.0.203.dev0}/code_loader/visualizers/default_visualizers.py
RENAMED
|
File without changes
|