humalab 0.0.5__py3-none-any.whl → 0.0.7__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 humalab might be problematic. Click here for more details.
- humalab/__init__.py +25 -0
- humalab/assets/__init__.py +8 -2
- humalab/assets/files/resource_file.py +96 -6
- humalab/assets/files/urdf_file.py +49 -11
- humalab/assets/resource_operator.py +139 -0
- humalab/constants.py +48 -5
- humalab/dists/__init__.py +7 -0
- humalab/dists/bernoulli.py +26 -1
- humalab/dists/categorical.py +25 -0
- humalab/dists/discrete.py +27 -2
- humalab/dists/distribution.py +11 -0
- humalab/dists/gaussian.py +27 -2
- humalab/dists/log_uniform.py +29 -3
- humalab/dists/truncated_gaussian.py +33 -4
- humalab/dists/uniform.py +24 -0
- humalab/episode.py +291 -11
- humalab/humalab.py +93 -38
- humalab/humalab_api_client.py +297 -95
- humalab/humalab_config.py +49 -0
- humalab/humalab_test.py +46 -17
- humalab/metrics/__init__.py +11 -5
- humalab/metrics/code.py +59 -0
- humalab/metrics/metric.py +69 -102
- humalab/metrics/scenario_stats.py +163 -0
- humalab/metrics/summary.py +45 -24
- humalab/run.py +224 -101
- humalab/scenarios/__init__.py +11 -0
- humalab/{scenario.py → scenarios/scenario.py} +130 -136
- humalab/scenarios/scenario_operator.py +114 -0
- humalab/{scenario_test.py → scenarios/scenario_test.py} +150 -269
- humalab/utils.py +37 -0
- {humalab-0.0.5.dist-info → humalab-0.0.7.dist-info}/METADATA +1 -1
- humalab-0.0.7.dist-info/RECORD +39 -0
- humalab/assets/resource_manager.py +0 -58
- humalab/evaluators/__init__.py +0 -16
- humalab/humalab_main.py +0 -119
- humalab/metrics/dist_metric.py +0 -22
- humalab-0.0.5.dist-info/RECORD +0 -37
- {humalab-0.0.5.dist-info → humalab-0.0.7.dist-info}/WHEEL +0 -0
- {humalab-0.0.5.dist-info → humalab-0.0.7.dist-info}/entry_points.txt +0 -0
- {humalab-0.0.5.dist-info → humalab-0.0.7.dist-info}/licenses/LICENSE +0 -0
- {humalab-0.0.5.dist-info → humalab-0.0.7.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import Any
|
|
2
|
+
from threading import RLock
|
|
3
|
+
|
|
2
4
|
import numpy as np
|
|
3
|
-
from omegaconf import OmegaConf,
|
|
5
|
+
from omegaconf import OmegaConf, DictConfig, ListConfig
|
|
4
6
|
import yaml
|
|
5
7
|
from humalab.dists.bernoulli import Bernoulli
|
|
6
8
|
from humalab.dists.categorical import Categorical
|
|
@@ -10,9 +12,7 @@ from humalab.dists.log_uniform import LogUniform
|
|
|
10
12
|
from humalab.dists.gaussian import Gaussian
|
|
11
13
|
from humalab.dists.truncated_gaussian import TruncatedGaussian
|
|
12
14
|
from functools import partial
|
|
13
|
-
from humalab.constants import
|
|
14
|
-
from humalab.metrics.dist_metric import DistributionMetric
|
|
15
|
-
from humalab.metrics.metric import MetricGranularity
|
|
15
|
+
from humalab.constants import GraphType, MetricDimType
|
|
16
16
|
import copy
|
|
17
17
|
import uuid
|
|
18
18
|
|
|
@@ -37,39 +37,40 @@ DISTRIBUTION_MAP = {
|
|
|
37
37
|
|
|
38
38
|
# 2D distributions
|
|
39
39
|
"uniform_2d": Uniform,
|
|
40
|
-
"bernoulli_2d": Bernoulli,
|
|
41
|
-
"categorical_2d": Categorical,
|
|
42
|
-
"discrete_2d": Discrete,
|
|
43
|
-
"log_uniform_2d": LogUniform,
|
|
40
|
+
# "bernoulli_2d": Bernoulli,
|
|
41
|
+
# "categorical_2d": Categorical,
|
|
42
|
+
# "discrete_2d": Discrete,
|
|
43
|
+
# "log_uniform_2d": LogUniform,
|
|
44
44
|
"gaussian_2d": Gaussian,
|
|
45
45
|
"truncated_gaussian_2d": TruncatedGaussian,
|
|
46
46
|
|
|
47
47
|
# 3D distributions
|
|
48
48
|
"uniform_3d": Uniform,
|
|
49
|
-
"bernoulli_3d": Bernoulli,
|
|
50
|
-
"categorical_3d": Categorical,
|
|
51
|
-
"discrete_3d": Discrete,
|
|
52
|
-
"log_uniform_3d": LogUniform,
|
|
49
|
+
# "bernoulli_3d": Bernoulli,
|
|
50
|
+
# "categorical_3d": Categorical,
|
|
51
|
+
# "discrete_3d": Discrete,
|
|
52
|
+
# "log_uniform_3d": LogUniform,
|
|
53
53
|
"gaussian_3d": Gaussian,
|
|
54
54
|
"truncated_gaussian_3d": TruncatedGaussian,
|
|
55
55
|
|
|
56
56
|
# 4D distributions
|
|
57
|
-
"uniform_4d": Uniform,
|
|
58
|
-
"bernoulli_4d": Bernoulli,
|
|
59
|
-
"categorical_4d": Categorical,
|
|
60
|
-
"discrete_4d": Discrete,
|
|
61
|
-
"log_uniform_4d": LogUniform,
|
|
62
|
-
"gaussian_4d": Gaussian,
|
|
63
|
-
"truncated_gaussian_4d": TruncatedGaussian,
|
|
64
|
-
|
|
57
|
+
# "uniform_4d": Uniform,
|
|
58
|
+
# "bernoulli_4d": Bernoulli,
|
|
59
|
+
# "categorical_4d": Categorical,
|
|
60
|
+
# "discrete_4d": Discrete,
|
|
61
|
+
# "log_uniform_4d": LogUniform,
|
|
62
|
+
# "gaussian_4d": Gaussian,
|
|
63
|
+
# "truncated_gaussian_4d": TruncatedGaussian,
|
|
64
|
+
|
|
65
65
|
# nD distributions
|
|
66
|
-
"uniform_nd": Uniform,
|
|
67
|
-
"bernoulli_nd": Bernoulli,
|
|
68
|
-
"categorical_nd": Categorical,
|
|
69
|
-
"discrete_nd": Discrete,
|
|
70
|
-
"log_uniform_nd": LogUniform,
|
|
71
|
-
"gaussian_nd": Gaussian,
|
|
72
|
-
"truncated_gaussian_nd": TruncatedGaussian,
|
|
66
|
+
# "uniform_nd": Uniform,
|
|
67
|
+
# "bernoulli_nd": Bernoulli,
|
|
68
|
+
# "categorical_nd": Categorical,
|
|
69
|
+
# "discrete_nd": Discrete,
|
|
70
|
+
# "log_uniform_nd": LogUniform,
|
|
71
|
+
# "gaussian_nd": Gaussian,
|
|
72
|
+
# "truncated_gaussian_nd": TruncatedGaussian,
|
|
73
|
+
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
DISTRIBUTION_DIMENSION_MAP = {
|
|
@@ -93,39 +94,13 @@ DISTRIBUTION_DIMENSION_MAP = {
|
|
|
93
94
|
|
|
94
95
|
# 2D distributions
|
|
95
96
|
"uniform_2d": 2,
|
|
96
|
-
"bernoulli_2d": 2,
|
|
97
|
-
"categorical_2d": 2,
|
|
98
|
-
"discrete_2d": 2,
|
|
99
|
-
"log_uniform_2d": 2,
|
|
100
97
|
"gaussian_2d": 2,
|
|
101
98
|
"truncated_gaussian_2d": 2,
|
|
102
99
|
|
|
103
100
|
# 3D distributions
|
|
104
101
|
"uniform_3d": 3,
|
|
105
|
-
"bernoulli_3d": 3,
|
|
106
|
-
"categorical_3d": 3,
|
|
107
|
-
"discrete_3d": 3,
|
|
108
|
-
"log_uniform_3d": 3,
|
|
109
102
|
"gaussian_3d": 3,
|
|
110
103
|
"truncated_gaussian_3d": 3,
|
|
111
|
-
|
|
112
|
-
# 4D distributions
|
|
113
|
-
"uniform_4d": 4,
|
|
114
|
-
"bernoulli_4d": 4,
|
|
115
|
-
"categorical_4d": 4,
|
|
116
|
-
"discrete_4d": 4,
|
|
117
|
-
"log_uniform_4d": 4,
|
|
118
|
-
"gaussian_4d": 4,
|
|
119
|
-
"truncated_gaussian_4d": 4,
|
|
120
|
-
|
|
121
|
-
# nD distributions
|
|
122
|
-
"uniform_nd": -1,
|
|
123
|
-
"bernoulli_nd": -1,
|
|
124
|
-
"categorical_nd": -1,
|
|
125
|
-
"discrete_nd": -1,
|
|
126
|
-
"log_uniform_nd": -1,
|
|
127
|
-
"gaussian_nd": -1,
|
|
128
|
-
"truncated_gaussian_nd": -1,
|
|
129
104
|
}
|
|
130
105
|
|
|
131
106
|
DISTRIBUTION_PARAM_NUM_MAP = {
|
|
@@ -149,79 +124,107 @@ DISTRIBUTION_PARAM_NUM_MAP = {
|
|
|
149
124
|
|
|
150
125
|
# 2D distributions
|
|
151
126
|
"uniform_2d": 2,
|
|
152
|
-
"bernoulli_2d": 1,
|
|
153
|
-
"categorical_2d": 2,
|
|
154
|
-
"discrete_2d": 3,
|
|
155
|
-
"log_uniform_2d": 2,
|
|
156
127
|
"gaussian_2d": 2,
|
|
157
128
|
"truncated_gaussian_2d": 4,
|
|
158
129
|
|
|
159
130
|
# 3D distributions
|
|
160
131
|
"uniform_3d": 2,
|
|
161
|
-
"bernoulli_3d": 1,
|
|
162
|
-
"categorical_3d": 2,
|
|
163
|
-
"discrete_3d": 3,
|
|
164
|
-
"log_uniform_3d": 2,
|
|
165
132
|
"gaussian_3d": 2,
|
|
166
133
|
"truncated_gaussian_3d": 4,
|
|
134
|
+
}
|
|
167
135
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
"
|
|
171
|
-
"
|
|
172
|
-
"
|
|
173
|
-
"
|
|
174
|
-
"
|
|
175
|
-
"
|
|
136
|
+
SCENARIO_STATS_DIM_TYPE_MAP = {
|
|
137
|
+
# 0D distributions
|
|
138
|
+
"uniform": MetricDimType.ONE_D,
|
|
139
|
+
"bernoulli": MetricDimType.ONE_D,
|
|
140
|
+
"categorical": MetricDimType.ONE_D,
|
|
141
|
+
"discrete": MetricDimType.ONE_D,
|
|
142
|
+
"log_uniform": MetricDimType.ONE_D,
|
|
143
|
+
"gaussian": MetricDimType.ONE_D,
|
|
144
|
+
"truncated_gaussian": MetricDimType.ONE_D,
|
|
176
145
|
|
|
177
|
-
#
|
|
178
|
-
"
|
|
179
|
-
"
|
|
180
|
-
"
|
|
181
|
-
"
|
|
182
|
-
"
|
|
183
|
-
"
|
|
184
|
-
"
|
|
146
|
+
# 1D distributions
|
|
147
|
+
"uniform_1d": MetricDimType.ONE_D,
|
|
148
|
+
"bernoulli_1d": MetricDimType.ONE_D,
|
|
149
|
+
"categorical_1d": MetricDimType.ONE_D,
|
|
150
|
+
"discrete_1d": MetricDimType.ONE_D,
|
|
151
|
+
"log_uniform_1d": MetricDimType.ONE_D,
|
|
152
|
+
"gaussian_1d": MetricDimType.ONE_D,
|
|
153
|
+
"truncated_gaussian_1d": MetricDimType.ONE_D,
|
|
154
|
+
|
|
155
|
+
# 2D distributions
|
|
156
|
+
"uniform_2d": MetricDimType.TWO_D,
|
|
157
|
+
"gaussian_2d": MetricDimType.TWO_D,
|
|
158
|
+
"truncated_gaussian_2d": MetricDimType.TWO_D,
|
|
159
|
+
|
|
160
|
+
# 3D distributions
|
|
161
|
+
"uniform_3d": MetricDimType.THREE_D,
|
|
162
|
+
"gaussian_3d": MetricDimType.THREE_D,
|
|
163
|
+
"truncated_gaussian_3d": MetricDimType.THREE_D,
|
|
185
164
|
}
|
|
186
165
|
|
|
187
166
|
class Scenario:
|
|
167
|
+
"""Manages scenario configurations with probabilistic distributions.
|
|
168
|
+
|
|
169
|
+
A Scenario encapsulates a configuration template that can contain distribution
|
|
170
|
+
resolvers (e.g., ${uniform:0,1}). When resolved, these distributions are sampled
|
|
171
|
+
to produce concrete scenario instances. Each resolution creates a new episode
|
|
172
|
+
with different sampled values.
|
|
173
|
+
|
|
174
|
+
Supported distributions include uniform, gaussian, bernoulli, categorical,
|
|
175
|
+
discrete, log_uniform, and truncated_gaussian, with support for 0D-3D variants.
|
|
176
|
+
|
|
177
|
+
Attributes:
|
|
178
|
+
template (DictConfig | ListConfig): The template scenario configuration.
|
|
179
|
+
yaml (str): The current scenario configuration as a YAML string.
|
|
180
|
+
"""
|
|
188
181
|
dist_cache = {}
|
|
189
182
|
def __init__(self) -> None:
|
|
190
183
|
self._generator = np.random.default_rng()
|
|
191
184
|
self._scenario_template = OmegaConf.create()
|
|
192
185
|
self._cur_scenario = OmegaConf.create()
|
|
193
186
|
self._scenario_id = None
|
|
187
|
+
self._seed = None
|
|
188
|
+
|
|
189
|
+
self._episode_vals = {}
|
|
190
|
+
self._lock = RLock()
|
|
194
191
|
|
|
195
192
|
def init(self,
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
scenario: str | list | dict | None = None,
|
|
199
|
-
seed: int | None=None,
|
|
193
|
+
scenario: str | list | dict | None = None,
|
|
194
|
+
seed: int | None=None,
|
|
200
195
|
scenario_id: str | None=None,
|
|
201
196
|
# num_env: int | None = None
|
|
202
197
|
) -> None:
|
|
203
198
|
"""
|
|
204
199
|
Initialize the scenario with the given parameters.
|
|
205
|
-
|
|
200
|
+
|
|
206
201
|
Args:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
scenario_id: Optional scenario ID
|
|
212
|
-
|
|
202
|
+
scenario (str | list | dict | None): The scenario configuration. Can be a YAML
|
|
203
|
+
string, list, or dict. If None, an empty configuration is used.
|
|
204
|
+
seed (int | None): Optional seed for random number generation. If None, uses
|
|
205
|
+
a non-deterministic seed.
|
|
206
|
+
scenario_id (str | None): Optional scenario ID in the format 'id' or 'id:version'.
|
|
207
|
+
If None, a new UUID is generated.
|
|
213
208
|
"""
|
|
214
|
-
self._run_id = run_id
|
|
215
|
-
self._episode_id = episode_id
|
|
216
|
-
self._metrics = {}
|
|
217
|
-
|
|
218
209
|
self._num_env = None # num_env
|
|
210
|
+
self._seed = seed
|
|
211
|
+
|
|
212
|
+
# Parse scenario id
|
|
213
|
+
scenario_version = 1
|
|
214
|
+
if scenario_id is not None:
|
|
215
|
+
scenario_arr = scenario_id.split(":")
|
|
216
|
+
if len(scenario_arr) < 1:
|
|
217
|
+
raise ValueError("Invalid scenario_id format. Expected 'scenario_id' or 'scenario_name:version'.")
|
|
218
|
+
scenario_id = scenario_arr[0]
|
|
219
|
+
scenario_version = int(scenario_arr[1]) if len(scenario_arr) > 1 else None
|
|
219
220
|
self._scenario_id = scenario_id or str(uuid.uuid4())
|
|
221
|
+
self._scenario_version = scenario_version
|
|
222
|
+
|
|
220
223
|
self._generator = np.random.default_rng(seed)
|
|
221
224
|
self._configure()
|
|
222
225
|
scenario = scenario or {}
|
|
226
|
+
|
|
223
227
|
self._scenario_template = OmegaConf.create(scenario)
|
|
224
|
-
self.reset(episode_id=episode_id)
|
|
225
228
|
|
|
226
229
|
def _validate_distribution_params(self, dist_name: str, *args: tuple) -> None:
|
|
227
230
|
dimensions = DISTRIBUTION_DIMENSION_MAP[dist_name]
|
|
@@ -291,13 +294,6 @@ class Scenario:
|
|
|
291
294
|
root_yaml = yaml.safe_load(OmegaConf.to_yaml(_root_))
|
|
292
295
|
key_path = self._get_node_path(root_yaml, str(_node_))
|
|
293
296
|
|
|
294
|
-
if key_path not in self._metrics:
|
|
295
|
-
self._metrics[key_path] = DistributionMetric(name=key_path,
|
|
296
|
-
distribution_type=dist_name,
|
|
297
|
-
run_id=self._run_id,
|
|
298
|
-
episode_id=self._episode_id,
|
|
299
|
-
granularity=MetricGranularity.EPISODE)
|
|
300
|
-
|
|
301
297
|
shape = None
|
|
302
298
|
|
|
303
299
|
if DISTRIBUTION_DIMENSION_MAP[dist_name] == -1:
|
|
@@ -315,7 +311,11 @@ class Scenario:
|
|
|
315
311
|
|
|
316
312
|
if isinstance(ret_val, list):
|
|
317
313
|
ret_val = ListConfig(ret_val)
|
|
318
|
-
|
|
314
|
+
|
|
315
|
+
self._episode_vals[key_path] = {
|
|
316
|
+
"value": ret_val,
|
|
317
|
+
"distribution": dist_name,
|
|
318
|
+
}
|
|
319
319
|
return ret_val
|
|
320
320
|
|
|
321
321
|
for dist_name in DISTRIBUTION_MAP.keys():
|
|
@@ -325,33 +325,36 @@ class Scenario:
|
|
|
325
325
|
self.dist_cache.clear()
|
|
326
326
|
OmegaConf.clear_resolvers()
|
|
327
327
|
|
|
328
|
-
def
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
def __getitem__(self, key: Any) -> Any:
|
|
334
|
-
if key in self._cur_scenario:
|
|
335
|
-
return self._cur_scenario[key]
|
|
336
|
-
raise KeyError(f"'Scenario' object has no key '{key}'")
|
|
337
|
-
|
|
338
|
-
def reset(self,
|
|
339
|
-
episode_id: str | None = None) -> None:
|
|
340
|
-
"""Reset the scenario for a new episode.
|
|
341
|
-
|
|
342
|
-
Args:
|
|
343
|
-
episode_id: Optional new episode ID. If None, keeps the current episode ID.
|
|
328
|
+
def resolve(self) -> tuple[DictConfig | ListConfig, dict]:
|
|
329
|
+
"""Resolve the scenario configuration, sampling all distributions.
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
tuple[DictConfig | ListConfig, dict]: The resolved scenario and episode values.
|
|
344
333
|
"""
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
334
|
+
with self._lock:
|
|
335
|
+
cur_scenario = copy.deepcopy(self._scenario_template)
|
|
336
|
+
self._episode_vals = {}
|
|
337
|
+
OmegaConf.resolve(cur_scenario)
|
|
338
|
+
episode_vals = copy.deepcopy(self._episode_vals)
|
|
339
|
+
return cur_scenario, episode_vals
|
|
340
|
+
|
|
341
|
+
@property
|
|
342
|
+
def scenario_id(self) -> str | None:
|
|
343
|
+
"""The scenario ID.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
str | None: The scenario ID, or None if not set.
|
|
347
|
+
"""
|
|
348
|
+
return self._scenario_id
|
|
349
|
+
|
|
350
|
+
@property
|
|
351
|
+
def seed(self) -> int | None:
|
|
352
|
+
"""The random seed for the scenario.
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
int | None: The random seed, or None if not set.
|
|
352
356
|
"""
|
|
353
|
-
|
|
354
|
-
metric.finish()
|
|
357
|
+
return self._seed
|
|
355
358
|
|
|
356
359
|
@property
|
|
357
360
|
def template(self) -> Any:
|
|
@@ -362,15 +365,6 @@ class Scenario:
|
|
|
362
365
|
"""
|
|
363
366
|
return self._scenario_template
|
|
364
367
|
|
|
365
|
-
@property
|
|
366
|
-
def cur_scenario(self) -> Any:
|
|
367
|
-
"""The current scenario configuration.
|
|
368
|
-
|
|
369
|
-
Returns:
|
|
370
|
-
Any: The current scenario as an OmegaConf object.
|
|
371
|
-
"""
|
|
372
|
-
return self._cur_scenario
|
|
373
|
-
|
|
374
368
|
@property
|
|
375
369
|
def yaml(self) -> str:
|
|
376
370
|
"""The current scenario configuration as a YAML string.
|
|
@@ -378,4 +372,4 @@ class Scenario:
|
|
|
378
372
|
Returns:
|
|
379
373
|
str: The current scenario as a YAML string.
|
|
380
374
|
"""
|
|
381
|
-
return OmegaConf.to_yaml(self.
|
|
375
|
+
return OmegaConf.to_yaml(self._scenario_template)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Operations for managing and retrieving scenarios."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
from humalab.humalab_api_client import HumaLabApiClient
|
|
7
|
+
from humalab.scenarios.scenario import Scenario
|
|
8
|
+
from humalab.constants import DEFAULT_PROJECT
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class ScenarioMetadata:
|
|
12
|
+
"""Metadata for a scenario stored in HumaLab.
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
id (str): Unique identifier for the scenario.
|
|
16
|
+
version (int): Version number of the scenario.
|
|
17
|
+
project (str): Project name the scenario belongs to.
|
|
18
|
+
name (str): Human-readable scenario name.
|
|
19
|
+
description (str | None): Optional scenario description.
|
|
20
|
+
created_at (str): ISO timestamp when scenario was created.
|
|
21
|
+
updated_at (str): ISO timestamp when scenario was last updated.
|
|
22
|
+
"""
|
|
23
|
+
id: str
|
|
24
|
+
version: int
|
|
25
|
+
project: str
|
|
26
|
+
name: str
|
|
27
|
+
description: str | None
|
|
28
|
+
created_at: str
|
|
29
|
+
updated_at: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def list_scenarios(project: str = DEFAULT_PROJECT,
|
|
33
|
+
limit: int = 20,
|
|
34
|
+
offset: int = 0,
|
|
35
|
+
include_inactive: bool = False,
|
|
36
|
+
search: Optional[str] = None,
|
|
37
|
+
status_filter: Optional[str] = None,
|
|
38
|
+
|
|
39
|
+
base_url: str | None = None,
|
|
40
|
+
api_key: str | None = None,
|
|
41
|
+
timeout: float | None = None,
|
|
42
|
+
) -> list[ScenarioMetadata]:
|
|
43
|
+
"""
|
|
44
|
+
List all scenarios for a given project.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
project (str): The project name to list scenarios from. Defaults to DEFAULT_PROJECT.
|
|
48
|
+
limit (int): Maximum number of scenarios to return. Defaults to 20.
|
|
49
|
+
offset (int): Number of scenarios to skip for pagination. Defaults to 0.
|
|
50
|
+
include_inactive (bool): Whether to include inactive scenarios. Defaults to False.
|
|
51
|
+
search (Optional[str]): Search query to filter scenarios by name or description. Defaults to None.
|
|
52
|
+
status_filter (Optional[str]): Filter scenarios by status. Defaults to None.
|
|
53
|
+
base_url (str | None): The base URL of the HumaLab API. If None, uses configured value.
|
|
54
|
+
api_key (str | None): The API key for authentication. If None, uses configured value.
|
|
55
|
+
timeout (float | None): The timeout for API requests in seconds. If None, uses configured value.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
list[ScenarioMetadata]: A list of scenario metadata objects.
|
|
59
|
+
"""
|
|
60
|
+
api_client = HumaLabApiClient(base_url=base_url,
|
|
61
|
+
api_key=api_key,
|
|
62
|
+
timeout=timeout)
|
|
63
|
+
resp = api_client.get_scenarios(project_name=project,
|
|
64
|
+
limit=limit,
|
|
65
|
+
offset=offset,
|
|
66
|
+
include_inactive=include_inactive,
|
|
67
|
+
search=search,
|
|
68
|
+
status_filter=status_filter)
|
|
69
|
+
ret_list = []
|
|
70
|
+
for scenario in resp.get("scenarios", []):
|
|
71
|
+
scenario["project"] = project
|
|
72
|
+
ret_list.append(ScenarioMetadata(id=scenario["uuid"],
|
|
73
|
+
version=scenario["version"],
|
|
74
|
+
project=project,
|
|
75
|
+
name=scenario["name"],
|
|
76
|
+
description=scenario.get("description"),
|
|
77
|
+
created_at=scenario.get("created_at"),
|
|
78
|
+
updated_at=scenario.get("updated_at")))
|
|
79
|
+
return ret_list
|
|
80
|
+
|
|
81
|
+
def get_scenario(scenario_id: str,
|
|
82
|
+
version: int | None = None,
|
|
83
|
+
project: str = DEFAULT_PROJECT,
|
|
84
|
+
seed: int | None=None,
|
|
85
|
+
|
|
86
|
+
base_url: str | None = None,
|
|
87
|
+
api_key: str | None = None,
|
|
88
|
+
timeout: float | None = None,) -> Scenario:
|
|
89
|
+
"""Retrieve and initialize a scenario from HumaLab.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
scenario_id (str): The unique identifier of the scenario.
|
|
93
|
+
version (int | None): Optional specific version to retrieve.
|
|
94
|
+
project (str): The project name. Defaults to DEFAULT_PROJECT.
|
|
95
|
+
seed (int | None): Optional seed for scenario randomization.
|
|
96
|
+
base_url (str | None): Optional API host override.
|
|
97
|
+
api_key (str | None): Optional API key override.
|
|
98
|
+
timeout (float | None): Optional timeout override.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Scenario: The initialized scenario instance.
|
|
102
|
+
"""
|
|
103
|
+
api_client = HumaLabApiClient(base_url=base_url,
|
|
104
|
+
api_key=api_key,
|
|
105
|
+
timeout=timeout)
|
|
106
|
+
scenario_resp = api_client.get_scenario(
|
|
107
|
+
project_name=project,
|
|
108
|
+
uuid=scenario_id, version=version)
|
|
109
|
+
scenario = Scenario()
|
|
110
|
+
|
|
111
|
+
scenario.init(scenario=scenario_resp["yaml_content"],
|
|
112
|
+
seed=seed,
|
|
113
|
+
scenario_id=f"{scenario_id}:{version}" if version is not None else scenario_id)
|
|
114
|
+
return scenario
|