experimaestro 2.0.0a8__py3-none-any.whl → 2.0.0b4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of experimaestro might be problematic. Click here for more details.
- experimaestro/__init__.py +10 -11
- experimaestro/annotations.py +167 -206
- experimaestro/cli/__init__.py +130 -5
- experimaestro/cli/filter.py +42 -74
- experimaestro/cli/jobs.py +157 -106
- experimaestro/cli/refactor.py +249 -0
- experimaestro/click.py +0 -1
- experimaestro/commandline.py +19 -3
- experimaestro/connectors/__init__.py +20 -1
- experimaestro/connectors/local.py +12 -0
- experimaestro/core/arguments.py +182 -46
- experimaestro/core/identifier.py +107 -6
- experimaestro/core/objects/__init__.py +6 -0
- experimaestro/core/objects/config.py +542 -25
- experimaestro/core/objects/config_walk.py +20 -0
- experimaestro/core/serialization.py +91 -34
- experimaestro/core/subparameters.py +164 -0
- experimaestro/core/types.py +175 -38
- experimaestro/exceptions.py +26 -0
- experimaestro/experiments/cli.py +107 -25
- experimaestro/generators.py +50 -9
- experimaestro/huggingface.py +3 -1
- experimaestro/launcherfinder/parser.py +29 -0
- experimaestro/launchers/__init__.py +26 -1
- experimaestro/launchers/direct.py +12 -0
- experimaestro/launchers/slurm/base.py +154 -2
- experimaestro/mkdocs/metaloader.py +0 -1
- experimaestro/mypy.py +452 -7
- experimaestro/notifications.py +63 -13
- experimaestro/progress.py +0 -2
- experimaestro/rpyc.py +0 -1
- experimaestro/run.py +19 -6
- experimaestro/scheduler/base.py +489 -125
- experimaestro/scheduler/dependencies.py +43 -28
- experimaestro/scheduler/dynamic_outputs.py +259 -130
- experimaestro/scheduler/experiment.py +225 -30
- experimaestro/scheduler/interfaces.py +474 -0
- experimaestro/scheduler/jobs.py +216 -206
- experimaestro/scheduler/services.py +186 -12
- experimaestro/scheduler/state_db.py +388 -0
- experimaestro/scheduler/state_provider.py +2345 -0
- experimaestro/scheduler/state_sync.py +834 -0
- experimaestro/scheduler/workspace.py +52 -10
- experimaestro/scriptbuilder.py +7 -0
- experimaestro/server/__init__.py +147 -57
- experimaestro/server/data/index.css +0 -125
- experimaestro/server/data/index.css.map +1 -1
- experimaestro/server/data/index.js +194 -58
- experimaestro/server/data/index.js.map +1 -1
- experimaestro/settings.py +44 -5
- experimaestro/sphinx/__init__.py +3 -3
- experimaestro/taskglobals.py +20 -0
- experimaestro/tests/conftest.py +80 -0
- experimaestro/tests/core/test_generics.py +2 -2
- experimaestro/tests/identifier_stability.json +45 -0
- experimaestro/tests/launchers/bin/sacct +6 -2
- experimaestro/tests/launchers/bin/sbatch +4 -2
- experimaestro/tests/launchers/test_slurm.py +80 -0
- experimaestro/tests/tasks/test_dynamic.py +231 -0
- experimaestro/tests/test_cli_jobs.py +615 -0
- experimaestro/tests/test_deprecated.py +630 -0
- experimaestro/tests/test_environment.py +200 -0
- experimaestro/tests/test_file_progress_integration.py +1 -1
- experimaestro/tests/test_forward.py +3 -3
- experimaestro/tests/test_identifier.py +372 -41
- experimaestro/tests/test_identifier_stability.py +458 -0
- experimaestro/tests/test_instance.py +3 -3
- experimaestro/tests/test_multitoken.py +442 -0
- experimaestro/tests/test_mypy.py +433 -0
- experimaestro/tests/test_objects.py +312 -5
- experimaestro/tests/test_outputs.py +2 -2
- experimaestro/tests/test_param.py +8 -12
- experimaestro/tests/test_partial_paths.py +231 -0
- experimaestro/tests/test_progress.py +0 -48
- experimaestro/tests/test_resumable_task.py +480 -0
- experimaestro/tests/test_serializers.py +141 -1
- experimaestro/tests/test_state_db.py +434 -0
- experimaestro/tests/test_subparameters.py +160 -0
- experimaestro/tests/test_tags.py +136 -0
- experimaestro/tests/test_tasks.py +107 -121
- experimaestro/tests/test_token_locking.py +252 -0
- experimaestro/tests/test_tokens.py +17 -13
- experimaestro/tests/test_types.py +123 -1
- experimaestro/tests/test_workspace_triggers.py +158 -0
- experimaestro/tests/token_reschedule.py +4 -2
- experimaestro/tests/utils.py +2 -2
- experimaestro/tokens.py +154 -57
- experimaestro/tools/diff.py +1 -1
- experimaestro/tui/__init__.py +8 -0
- experimaestro/tui/app.py +2303 -0
- experimaestro/tui/app.tcss +353 -0
- experimaestro/tui/log_viewer.py +228 -0
- experimaestro/utils/__init__.py +23 -0
- experimaestro/utils/environment.py +148 -0
- experimaestro/utils/git.py +129 -0
- experimaestro/utils/resources.py +1 -1
- experimaestro/version.py +34 -0
- {experimaestro-2.0.0a8.dist-info → experimaestro-2.0.0b4.dist-info}/METADATA +68 -38
- experimaestro-2.0.0b4.dist-info/RECORD +181 -0
- {experimaestro-2.0.0a8.dist-info → experimaestro-2.0.0b4.dist-info}/WHEEL +1 -1
- experimaestro-2.0.0b4.dist-info/entry_points.txt +16 -0
- experimaestro/compat.py +0 -6
- experimaestro/core/objects.pyi +0 -221
- experimaestro/server/data/0c35d18bf06992036b69.woff2 +0 -0
- experimaestro/server/data/219aa9140e099e6c72ed.woff2 +0 -0
- experimaestro/server/data/3a4004a46a653d4b2166.woff +0 -0
- experimaestro/server/data/3baa5b8f3469222b822d.woff +0 -0
- experimaestro/server/data/4d73cb90e394b34b7670.woff +0 -0
- experimaestro/server/data/4ef4218c522f1eb6b5b1.woff2 +0 -0
- experimaestro/server/data/5d681e2edae8c60630db.woff +0 -0
- experimaestro/server/data/6f420cf17cc0d7676fad.woff2 +0 -0
- experimaestro/server/data/c380809fd3677d7d6903.woff2 +0 -0
- experimaestro/server/data/f882956fd323fd322f31.woff +0 -0
- experimaestro-2.0.0a8.dist-info/RECORD +0 -166
- experimaestro-2.0.0a8.dist-info/entry_points.txt +0 -17
- {experimaestro-2.0.0a8.dist-info → experimaestro-2.0.0b4.dist-info}/licenses/LICENSE +0 -0
|
@@ -29,6 +29,26 @@ class ConfigWalkContext:
|
|
|
29
29
|
return self.path / self._configpath
|
|
30
30
|
return self.path
|
|
31
31
|
|
|
32
|
+
def partial_path(self, subparameters, config) -> Path:
|
|
33
|
+
"""Returns the partial directory path for a given subparameters instance.
|
|
34
|
+
|
|
35
|
+
This method should be overridden in subclasses that have access to
|
|
36
|
+
workspace information (like JobContext).
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
subparameters: The Subparameters instance defining which groups to exclude
|
|
40
|
+
config: The configuration to compute the partial identifier for
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
The partial directory path.
|
|
44
|
+
|
|
45
|
+
Raises:
|
|
46
|
+
NotImplementedError: If the context doesn't support partial paths.
|
|
47
|
+
"""
|
|
48
|
+
raise NotImplementedError(
|
|
49
|
+
"Partial paths require a context with workspace information (like JobContext)"
|
|
50
|
+
)
|
|
51
|
+
|
|
32
52
|
@contextmanager
|
|
33
53
|
def push(self, key: str):
|
|
34
54
|
"""Push a new key to contextualize paths"""
|
|
@@ -31,10 +31,14 @@ def json_object(context: SerializationContext, value: Any, objects=[]):
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def state_dict(context: SerializationContext, obj: Any):
|
|
34
|
-
"""
|
|
34
|
+
"""Convert an object to a state dictionary for serialization.
|
|
35
|
+
|
|
36
|
+
Returns a dictionary representation that can be serialized to JSON
|
|
37
|
+
and later restored with :func:`from_state_dict`.
|
|
35
38
|
|
|
36
39
|
:param context: The serialization context
|
|
37
|
-
:param obj:
|
|
40
|
+
:param obj: The object to serialize
|
|
41
|
+
:return: A dictionary with 'objects' and 'data' keys
|
|
38
42
|
"""
|
|
39
43
|
objects: list[Any] = []
|
|
40
44
|
data = json_object(context, obj, objects)
|
|
@@ -48,14 +52,19 @@ def save_definition(obj: Any, context: SerializationContext, path: Path):
|
|
|
48
52
|
|
|
49
53
|
|
|
50
54
|
def save(obj: Any, save_directory: Optional[Path]):
|
|
51
|
-
"""
|
|
55
|
+
"""Save a configuration to a directory.
|
|
56
|
+
|
|
57
|
+
The serialization process stores the configuration in "definition.json"
|
|
58
|
+
and copies any files or folders registered as DataPath parameters.
|
|
59
|
+
|
|
60
|
+
Example::
|
|
52
61
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
meta-parameters).
|
|
62
|
+
config = MyConfig.C(data_path=Path("/data/file.txt"))
|
|
63
|
+
save(config, Path("/output/saved_config"))
|
|
56
64
|
|
|
65
|
+
:param obj: The configuration to save
|
|
57
66
|
:param save_directory: The directory in which the object and its data will
|
|
58
|
-
be saved (
|
|
67
|
+
be saved (object is saved in "definition.json")
|
|
59
68
|
"""
|
|
60
69
|
context = SerializationContext(save_directory=save_directory)
|
|
61
70
|
save_definition(
|
|
@@ -89,19 +98,32 @@ def from_state_dict(
|
|
|
89
98
|
state: Dict[str, Any],
|
|
90
99
|
path: Union[None, str, Path, SerializedPathLoader] = None,
|
|
91
100
|
*,
|
|
92
|
-
as_instance: bool = False
|
|
101
|
+
as_instance: bool = False,
|
|
102
|
+
partial_loading: Optional[bool] = None,
|
|
93
103
|
):
|
|
94
|
-
"""Load an object from a state dictionary
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
:
|
|
98
|
-
|
|
99
|
-
:param
|
|
104
|
+
"""Load an object from a state dictionary.
|
|
105
|
+
|
|
106
|
+
Restores a configuration from a dictionary previously created by
|
|
107
|
+
:func:`state_dict`.
|
|
108
|
+
|
|
109
|
+
:param state: The state dictionary to load from
|
|
110
|
+
:param path: Directory containing data files, or a function that resolves
|
|
111
|
+
relative paths to absolute ones
|
|
112
|
+
:param as_instance: If True, return an instance instead of a config
|
|
113
|
+
:param partial_loading: If True, skip loading task references. If None
|
|
114
|
+
(default), partial_loading is enabled when as_instance is True.
|
|
115
|
+
:return: The loaded configuration or instance
|
|
100
116
|
"""
|
|
117
|
+
# Determine effective partial_loading: as_instance implies partial_loading
|
|
118
|
+
effective_partial_loading = (
|
|
119
|
+
partial_loading if partial_loading is not None else as_instance
|
|
120
|
+
)
|
|
121
|
+
|
|
101
122
|
objects = ConfigInformation.load_objects(
|
|
102
123
|
state["objects"],
|
|
103
124
|
as_instance=as_instance,
|
|
104
125
|
data_loader=get_data_loader(path),
|
|
126
|
+
partial_loading=effective_partial_loading,
|
|
105
127
|
)
|
|
106
128
|
|
|
107
129
|
return ConfigInformation._objectFromParameters(state["data"], objects)
|
|
@@ -110,46 +132,72 @@ def from_state_dict(
|
|
|
110
132
|
def load(
|
|
111
133
|
path: Union[str, Path, SerializedPathLoader],
|
|
112
134
|
as_instance: bool = False,
|
|
135
|
+
partial_loading: Optional[bool] = None,
|
|
113
136
|
) -> Tuple[Any, List["LightweightTask"]]:
|
|
114
|
-
"""Load
|
|
137
|
+
"""Load a configuration from a directory.
|
|
138
|
+
|
|
139
|
+
Restores a configuration previously saved with :func:`save`.
|
|
140
|
+
|
|
141
|
+
Example::
|
|
115
142
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
:param
|
|
143
|
+
config = load(Path("/output/saved_config"))
|
|
144
|
+
|
|
145
|
+
:param path: Directory containing the saved configuration, or a function
|
|
146
|
+
that resolves relative paths to absolute ones
|
|
147
|
+
:param as_instance: If True, return an instance instead of a config
|
|
148
|
+
:param partial_loading: If True, skip loading task references. If None
|
|
149
|
+
(default), partial_loading is enabled when as_instance is True.
|
|
150
|
+
:return: The loaded configuration or instance
|
|
119
151
|
"""
|
|
120
152
|
data_loader = get_data_loader(path)
|
|
121
153
|
|
|
122
154
|
with data_loader("definition.json").open("rt") as fh:
|
|
123
155
|
content = json.load(fh)
|
|
124
|
-
return from_state_dict(
|
|
156
|
+
return from_state_dict(
|
|
157
|
+
content, as_instance=as_instance, partial_loading=partial_loading
|
|
158
|
+
)
|
|
125
159
|
|
|
126
160
|
|
|
127
161
|
def from_task_dir(
|
|
128
162
|
path: Union[str, Path, SerializedPathLoader],
|
|
129
163
|
as_instance: bool = False,
|
|
164
|
+
partial_loading: Optional[bool] = None,
|
|
130
165
|
):
|
|
131
|
-
"""
|
|
166
|
+
"""Load a task configuration from a task directory.
|
|
167
|
+
|
|
168
|
+
Loads the task parameters from a job directory (containing params.json).
|
|
169
|
+
This is useful for reloading task configurations after execution.
|
|
170
|
+
|
|
171
|
+
:param path: Task directory containing params.json, or a function that
|
|
172
|
+
resolves relative paths to absolute ones
|
|
173
|
+
:param as_instance: If True, return an instance instead of a config
|
|
174
|
+
:param partial_loading: If True, skip loading task references. If None
|
|
175
|
+
(default), partial_loading is enabled when as_instance is True.
|
|
176
|
+
:return: The loaded task configuration or instance
|
|
177
|
+
"""
|
|
132
178
|
data_loader = get_data_loader(path)
|
|
133
179
|
with data_loader("params.json").open("rt") as fh:
|
|
134
180
|
content = json.load(fh)
|
|
135
181
|
|
|
136
182
|
content["data"] = {"type": "python", "value": content["objects"][-1]["id"]}
|
|
137
183
|
|
|
138
|
-
return from_state_dict(
|
|
184
|
+
return from_state_dict(
|
|
185
|
+
content, as_instance=as_instance, partial_loading=partial_loading
|
|
186
|
+
)
|
|
139
187
|
|
|
140
188
|
|
|
141
189
|
def serialize(
|
|
142
190
|
obj: Any, save_directory: Path, *, init_tasks: list["LightweightTask"] = []
|
|
143
191
|
):
|
|
144
|
-
"""
|
|
192
|
+
"""Serialize a configuration to a directory with initialization tasks.
|
|
145
193
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
meta-parameters).
|
|
194
|
+
Similar to :func:`save`, but also stores lightweight initialization tasks
|
|
195
|
+
that should be run when the configuration is deserialized.
|
|
149
196
|
|
|
197
|
+
:param obj: The configuration to serialize
|
|
150
198
|
:param save_directory: The directory in which the object and its data will
|
|
151
|
-
be saved (
|
|
152
|
-
:param init_tasks:
|
|
199
|
+
be saved (object is saved in "definition.json")
|
|
200
|
+
:param init_tasks: List of lightweight tasks to run on deserialization
|
|
153
201
|
"""
|
|
154
202
|
context = SerializationContext(save_directory=save_directory)
|
|
155
203
|
save_definition((obj, init_tasks), context, save_directory / "definition.json")
|
|
@@ -158,20 +206,29 @@ def serialize(
|
|
|
158
206
|
def deserialize(
|
|
159
207
|
path: Union[str, Path, SerializedPathLoader],
|
|
160
208
|
as_instance: bool = False,
|
|
209
|
+
partial_loading: Optional[bool] = None,
|
|
161
210
|
) -> tuple[Any, List["LightweightTask"]] | Any:
|
|
162
|
-
"""
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
:
|
|
211
|
+
"""Deserialize a configuration from a directory.
|
|
212
|
+
|
|
213
|
+
Restores a configuration previously saved with :func:`serialize`.
|
|
214
|
+
When ``as_instance=True``, runs any stored initialization tasks.
|
|
215
|
+
|
|
216
|
+
:param path: Directory containing the serialized configuration, or a function
|
|
217
|
+
that resolves relative paths to absolute ones
|
|
218
|
+
:param as_instance: If True, return an instance and run init tasks
|
|
219
|
+
:param partial_loading: If True, skip loading task references. If None
|
|
220
|
+
(default), partial_loading is enabled when as_instance is True.
|
|
221
|
+
:return: The configuration/instance (if as_instance), or tuple of
|
|
222
|
+
(configuration, init_tasks)
|
|
168
223
|
"""
|
|
169
224
|
data_loader = get_data_loader(path)
|
|
170
225
|
|
|
171
226
|
with data_loader("definition.json").open("rt") as fh:
|
|
172
227
|
content = json.load(fh)
|
|
173
228
|
|
|
174
|
-
object, init_tasks = from_state_dict(
|
|
229
|
+
object, init_tasks = from_state_dict(
|
|
230
|
+
content, data_loader, as_instance=as_instance, partial_loading=partial_loading
|
|
231
|
+
)
|
|
175
232
|
|
|
176
233
|
if as_instance:
|
|
177
234
|
for init_task in init_tasks:
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Subparameters for partial identifier computation.
|
|
2
|
+
|
|
3
|
+
This module provides the `subparameters` function and `Subparameters` class
|
|
4
|
+
for defining parameter subsets that compute partial identifiers. This enables
|
|
5
|
+
sharing directories (like checkpoints) across tasks that differ only in
|
|
6
|
+
excluded parameter groups.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
iter_group = param_group("iter")
|
|
10
|
+
|
|
11
|
+
class Learn(Task):
|
|
12
|
+
checkpoints = subparameters(exclude_groups=[iter_group])
|
|
13
|
+
|
|
14
|
+
max_iter: Param[int] = field(groups=[iter_group])
|
|
15
|
+
learning_rate: Param[float]
|
|
16
|
+
|
|
17
|
+
# Path will be in WORKSPACE/partials/TASK_ID/checkpoints/PARTIAL_ID/
|
|
18
|
+
checkpoints_path: Param[Path] = field(
|
|
19
|
+
default_factory=PathGenerator(partial=checkpoints)
|
|
20
|
+
)
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from dataclasses import dataclass, field as dataclass_field
|
|
24
|
+
from typing import Set, Optional
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class ParameterGroup:
|
|
29
|
+
"""A parameter group with a name
|
|
30
|
+
|
|
31
|
+
The name is just for reference, what is important is the identity of the
|
|
32
|
+
object. The dataclass is frozen to make it hashable.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
name: str
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def param_group(name: str) -> ParameterGroup:
|
|
39
|
+
"""Create a parameter group for use with subparameters.
|
|
40
|
+
|
|
41
|
+
Parameter groups allow computing partial identifiers that exclude
|
|
42
|
+
certain parameters, enabling shared directories across related tasks.
|
|
43
|
+
|
|
44
|
+
Example::
|
|
45
|
+
|
|
46
|
+
training_group = param_group("training")
|
|
47
|
+
|
|
48
|
+
class MyTask(Task):
|
|
49
|
+
model_size: Param[int]
|
|
50
|
+
learning_rate: Param[float] = field(groups=[training_group])
|
|
51
|
+
|
|
52
|
+
:param name: Unique name for this parameter group
|
|
53
|
+
:return: A ParameterGroup object
|
|
54
|
+
"""
|
|
55
|
+
return ParameterGroup(name)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class Subparameters:
|
|
60
|
+
"""Defines a subset of parameters for partial identifier computation.
|
|
61
|
+
|
|
62
|
+
A Subparameters instance defines which parameter groups to include or exclude
|
|
63
|
+
when computing a partial identifier. This enables sharing directories
|
|
64
|
+
(like checkpoints) across experiments that only differ in excluded groups.
|
|
65
|
+
|
|
66
|
+
The inclusion/exclusion logic follows these rules:
|
|
67
|
+
1. If `exclude_all` is True, all parameters are excluded by default
|
|
68
|
+
2. Parameters in `exclude_groups` are excluded
|
|
69
|
+
3. Parameters with no group are excluded if `exclude_no_group` is True
|
|
70
|
+
4. Parameters in `include_groups` are always included (overrides exclusion)
|
|
71
|
+
|
|
72
|
+
Attributes:
|
|
73
|
+
exclude_groups: Set of group names to exclude from identifier computation
|
|
74
|
+
include_groups: Set of group names to always include (overrides exclusion)
|
|
75
|
+
exclude_no_group: If True, exclude parameters with no group assigned
|
|
76
|
+
exclude_all: If True, exclude all parameters by default
|
|
77
|
+
name: The name of this parameter set (auto-set from class attribute name)
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
#: Set of group names to exclude from identifier computation
|
|
81
|
+
exclude_groups: Set[ParameterGroup] = dataclass_field(default_factory=set)
|
|
82
|
+
|
|
83
|
+
#: Set of group names to always include (overrides exclusion)
|
|
84
|
+
include_groups: Set[ParameterGroup] = dataclass_field(default_factory=set)
|
|
85
|
+
|
|
86
|
+
#: If True, exclude parameters with no group assigned
|
|
87
|
+
exclude_no_group: bool = False
|
|
88
|
+
|
|
89
|
+
#: If True, exclude all parameters by default (use include_groups to select)
|
|
90
|
+
exclude_all: bool = False
|
|
91
|
+
|
|
92
|
+
#: Name of this parameter set (auto-set from class attribute)
|
|
93
|
+
name: Optional[ParameterGroup] = None
|
|
94
|
+
|
|
95
|
+
def __post_init__(self):
|
|
96
|
+
# Ensure groups are sets
|
|
97
|
+
if not isinstance(self.exclude_groups, set):
|
|
98
|
+
self.exclude_groups = set(self.exclude_groups)
|
|
99
|
+
if not isinstance(self.include_groups, set):
|
|
100
|
+
self.include_groups = set(self.include_groups)
|
|
101
|
+
|
|
102
|
+
def is_excluded(self, groups: Set[ParameterGroup]) -> bool:
|
|
103
|
+
"""Check if a parameter with the given groups should be excluded.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
groups: The set of groups the parameter belongs to (empty if no groups).
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
True if the parameter should be excluded from partial identifier.
|
|
110
|
+
"""
|
|
111
|
+
# Include always overrides exclude - if any group is in include_groups
|
|
112
|
+
if groups and (groups & self.include_groups):
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
# Check exclusion rules
|
|
116
|
+
if self.exclude_all:
|
|
117
|
+
return True
|
|
118
|
+
if not groups and self.exclude_no_group:
|
|
119
|
+
return True
|
|
120
|
+
if groups and (groups & self.exclude_groups):
|
|
121
|
+
return True
|
|
122
|
+
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def subparameters(
|
|
127
|
+
*,
|
|
128
|
+
exclude_groups: list[ParameterGroup] | None = None,
|
|
129
|
+
include_groups: list[ParameterGroup] | None = None,
|
|
130
|
+
exclude_no_group: bool = False,
|
|
131
|
+
exclude_all: bool = False,
|
|
132
|
+
) -> Subparameters:
|
|
133
|
+
"""Create a subparameters specification for partial identifier computation.
|
|
134
|
+
|
|
135
|
+
Subparameters allow tasks to share directories when they differ only
|
|
136
|
+
in certain parameter groups (e.g., training hyperparameters).
|
|
137
|
+
|
|
138
|
+
Example::
|
|
139
|
+
|
|
140
|
+
training_group = param_group("training")
|
|
141
|
+
|
|
142
|
+
class Train(Task):
|
|
143
|
+
model: Param[Model]
|
|
144
|
+
epochs: Param[int] = field(groups=[training_group])
|
|
145
|
+
|
|
146
|
+
checkpoint: Meta[Path] = field(
|
|
147
|
+
default_factory=PathGenerator(
|
|
148
|
+
"model.pt",
|
|
149
|
+
subparameters=subparameters(exclude=[training_group])
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
:param exclude_groups: Parameter groups to exclude from identifier
|
|
154
|
+
:param include_groups: Parameter groups to always include (overrides exclusion)
|
|
155
|
+
:param exclude_no_group: If True, exclude parameters with no group assigned
|
|
156
|
+
:param exclude_all: If True, exclude all parameters by default
|
|
157
|
+
:return: A Subparameters object
|
|
158
|
+
"""
|
|
159
|
+
return Subparameters(
|
|
160
|
+
exclude_groups=set(exclude_groups or []),
|
|
161
|
+
include_groups=set(include_groups or []),
|
|
162
|
+
exclude_no_group=exclude_no_group,
|
|
163
|
+
exclude_all=exclude_all,
|
|
164
|
+
)
|