sequence-base 0.5.0__tar.gz → 0.5.1__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.
- {sequence_base-0.5.0 → sequence_base-0.5.1}/PKG-INFO +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/pyproject.toml +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/constants/version.py +2 -1
- sequence_base-0.5.1/sequence_base/construct.py +173 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/benchmarks.py +48 -19
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/connect.py +13 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/flags.py +2 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/policy.py +19 -12
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ActRequest.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ActResponse.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ActionChunk.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ActionContract.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ActionStep.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/AdapterPair.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/AddLocal.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Autoscaler.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/BenchmarkRegisterRequest.json +2 -2
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/BenchmarkSpec.json +50 -4
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/BenchmarkStatusResponse.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/BootstrapResponse.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Camera.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/CodeBundle.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Concurrency.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ConnectRequest.json +15 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ConnectResponse.json +16 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/DeploymentAccepted.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/DeploymentPolicy.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/DeploymentRequest.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/DeploymentStatusResponse.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ErrorBody.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ErrorCodes.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Estimate.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/EvalDryRunResponse.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/EvalReport.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/EvalRequest.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/EvalResponse.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/GroupObservation.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/GroupObserve.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/GroupObserved.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageFrame.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageSpec.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageStepAddLocal.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageStepApt.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageStepEnv.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageStepProject.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageStepRun.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageStepTemplateFiles.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ImageStepUvPip.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/InferParam.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Lease.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/MetricAgg.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Observation.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ObservationContract.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Observations.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ObserveRequest.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ObserveResponse.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/PlanAppend.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/PlanAppended.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/PolicyRegistration.json +3 -3
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/PolicySpec.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Project.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Proprioception.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/ReplaySpec.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Resources.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/RolloutResult.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/SecretCreateRequest.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/SecretInfo.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/SecretRef.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/SeqFlags.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/SettingsChange.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/SettingsChanged.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/SettingsView.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Standby.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Stream.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TaskAgg.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TeamGroup.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TeamGroups.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TeamGroupsRequest.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TeamMember.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TeamPlans.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TeamPlansWritten.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TeamSpec.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/TemplateFiles.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Tensors.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/Timeouts.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/UploadTarget.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/VolumeFile.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/VolumeInfo.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/VolumeMount.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/VolumeRef.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/VolumeUploadRequest.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/VolumeUploadResponse.json +1 -1
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/WarmingError.json +1 -1
- sequence_base-0.5.0/sequence_base/construct.py +0 -124
- {sequence_base-0.5.0 → sequence_base-0.5.1}/.gitignore +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/README.md +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/__init__.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/auth.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/by_name.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/codec/__init__.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/codec/image.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/codec/marked.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/constants/__init__.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/constants/cards.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/constants/headers.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/constants/limits.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/__init__.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/accounts.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/act.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/adapters.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/deployments.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/errors.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/eval.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/io.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/obs_schedule.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/observe.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/own_io.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/retired.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/settings.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/team.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/templates.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/volumes.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/contract/wire.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/episode.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/errors/__init__.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/errors/transport.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/msgpack_io.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/obs/__init__.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/obs/log.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/obs/rid.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/presets/__init__.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/presets/frames.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/presets/robot_arm.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schema_export.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/telemetry/__init__.py +0 -0
- {sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/telemetry/events.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sequence-base
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Shared foundation for the Sequences platform — wire contract, correlation, error taxonomy, constants. Used by the robot SDK, gateway, and container harness.
|
|
5
5
|
Project-URL: Changelog, https://generalsequences.com/docs/changelog/
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sequence-base"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.1"
|
|
4
4
|
description = "Shared foundation for the Sequences platform — wire contract, correlation, error taxonomy, constants. Used by the robot SDK, gateway, and container harness."
|
|
5
5
|
requires-python = ">=3.10"
|
|
6
6
|
dependencies = ["pydantic>=2.0"]
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""
|
|
2
|
+
How a class built by its constructor is built - a policy's or a team's (PolicyRegistration.constructor), a benchmark's
|
|
3
|
+
(BenchmarkSpec.constructor): its constructor - or the factory it names, a classmethod of it or a module's function -
|
|
4
|
+
called with the arguments its decorator was given (init=), once the forms in them are filled in.
|
|
5
|
+
|
|
6
|
+
In one sentence: a value {"$config": path, "$set": {...}} becomes the YAML or JSON file at `path` - from the folder of
|
|
7
|
+
the class's file - read where the class runs, with `$set`'s keys laid over its top level → in every string, a policy's
|
|
8
|
+
"{weights}" becomes the weights directory and "{weights.<part>}" a named part's, a benchmark's "{num_worlds}" how many
|
|
9
|
+
worlds this eval builds and "{policy.<field>}" what the evaluated policy declares (POLICY_FIELDS) - a string that is one
|
|
10
|
+
form alone becomes its value as it is, an int or None, one among other text its value as text → `cls.<make>(*args,
|
|
11
|
+
**kwargs)`, or `function(*args, **kwargs)` for make="package.module:function" - the module imported where the class
|
|
12
|
+
runs - or `cls(*args, **kwargs)` without a factory.
|
|
13
|
+
|
|
14
|
+
WHY a config file is read where the policy runs: it is part of the project (XPolicyLab's deploy.yml beside its
|
|
15
|
+
model.py) and goes up with it, so one copy - the one the policy runs with - is read, and "{weights}" in it means the
|
|
16
|
+
worker's directory.
|
|
17
|
+
|
|
18
|
+
WHY a benchmark's too: its worlds are built after the machine's snapshot by the class's own constructor - a repository's
|
|
19
|
+
env as it is, handed how many worlds and the policy's rate where its own code takes them - where a method of the
|
|
20
|
+
platform's (@seq.setup) built them before.
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import importlib
|
|
26
|
+
import json
|
|
27
|
+
import os
|
|
28
|
+
import re
|
|
29
|
+
from typing import Any
|
|
30
|
+
|
|
31
|
+
__all__ = ["CONFIG_KEY", "FORMS", "POLICY_FIELDS", "SET_KEY", "ConstructError", "build", "config", "expand",
|
|
32
|
+
"is_config", "maker", "read_config"]
|
|
33
|
+
|
|
34
|
+
CONFIG_KEY, SET_KEY = "$config", "$set"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
POLICY_FIELDS = ("hz", "action_chunk_len", "action_chunk_exec_len")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
FORMS = re.compile(r"\{(?:weights(?:\.(?P<part>[A-Za-z_][A-Za-z0-9_-]*))?|(?P<worlds>num_worlds)"
|
|
42
|
+
r"|policy\.(?P<field>[A-Za-z_][A-Za-z0-9_]*))\}")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ConstructError(ValueError):
|
|
46
|
+
"""Arguments that cannot be filled in: a config file missing, unreadable or of another kind, a weights placeholder
|
|
47
|
+
with no weights - or no such part - to fill it, "{num_worlds}" where no worlds are built, or a policy field no policy
|
|
48
|
+
declares."""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def config(path: str, **overrides: Any) -> dict:
|
|
52
|
+
"""A config file's contents with `overrides` laid over its top level, as the worker reads it (`seq.config`)."""
|
|
53
|
+
if not isinstance(path, str) or not path:
|
|
54
|
+
raise ConstructError("a config file is a path, from the folder of the class's file")
|
|
55
|
+
if os.path.isabs(path):
|
|
56
|
+
raise ConstructError(f"{path}: give a config file's path from the folder of the class's file - the policy runs "
|
|
57
|
+
"it where the upload puts it")
|
|
58
|
+
return {CONFIG_KEY: path, SET_KEY: dict(overrides)}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def is_config(value: Any) -> bool:
|
|
62
|
+
return isinstance(value, dict) and set(value) == {CONFIG_KEY, SET_KEY} and isinstance(value[CONFIG_KEY], str)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def read_config(path: str) -> Any:
|
|
66
|
+
"""The YAML (.yml, .yaml) or JSON (.json) file at `path`."""
|
|
67
|
+
kind = os.path.splitext(path)[1].lower()
|
|
68
|
+
if kind not in (".json", ".yml", ".yaml"):
|
|
69
|
+
raise ConstructError(f"{path}: a config file is .json, .yml or .yaml")
|
|
70
|
+
if not os.path.isfile(path):
|
|
71
|
+
raise ConstructError(f"{path}: no such config file")
|
|
72
|
+
with open(path, encoding="utf-8") as f:
|
|
73
|
+
if kind == ".json":
|
|
74
|
+
return json.load(f)
|
|
75
|
+
try:
|
|
76
|
+
import yaml
|
|
77
|
+
except ImportError:
|
|
78
|
+
raise ConstructError(f"{path}: reading YAML needs pyyaml") from None
|
|
79
|
+
return yaml.safe_load(f)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def expand(value: Any, *, base_dir: str, weights: Any = None, worlds: int | None = None, policy: Any = None) -> Any:
|
|
83
|
+
"""`value` with its config files read (from `base_dir`) and its forms filled: a policy's from `weights` - the
|
|
84
|
+
weights directory, or {part: directory} for named parts, or None for a policy without weights - a benchmark's from
|
|
85
|
+
`worlds`, how many worlds this eval builds, and `policy`, what the evaluated policy declares ({field: value}, or an
|
|
86
|
+
object with them; None where none is evaluated, each field None). A string that is one form alone becomes its value
|
|
87
|
+
as it is; one form among other text, its value as text."""
|
|
88
|
+
forms = {"base_dir": base_dir, "weights": weights, "worlds": worlds, "policy": policy}
|
|
89
|
+
if is_config(value):
|
|
90
|
+
loaded = read_config(os.path.join(base_dir, value[CONFIG_KEY]))
|
|
91
|
+
if value[SET_KEY] and not isinstance(loaded, dict):
|
|
92
|
+
raise ConstructError(f"{value[CONFIG_KEY]} holds a {type(loaded).__name__}, which has no keys to set")
|
|
93
|
+
merged = {**loaded, **value[SET_KEY]} if isinstance(loaded, dict) else loaded
|
|
94
|
+
return expand(merged, **forms)
|
|
95
|
+
if isinstance(value, dict):
|
|
96
|
+
return {k: expand(v, **forms) for k, v in value.items()}
|
|
97
|
+
if isinstance(value, (list, tuple)):
|
|
98
|
+
return [expand(v, **forms) for v in value]
|
|
99
|
+
if isinstance(value, str):
|
|
100
|
+
alone = FORMS.fullmatch(value)
|
|
101
|
+
if alone:
|
|
102
|
+
return _filled(alone, weights, worlds, policy)
|
|
103
|
+
return FORMS.sub(lambda m: str(_filled(m, weights, worlds, policy)), value)
|
|
104
|
+
return value
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _filled(form: re.Match, weights: Any, worlds: int | None, policy: Any) -> Any:
|
|
108
|
+
if form.group("worlds"):
|
|
109
|
+
if worlds is None:
|
|
110
|
+
raise ConstructError("{num_worlds} is how many worlds this eval builds, and none is handed: a benchmark of one "
|
|
111
|
+
"world an instance takes none")
|
|
112
|
+
return worlds
|
|
113
|
+
field = form.group("field")
|
|
114
|
+
if field is not None:
|
|
115
|
+
if field not in POLICY_FIELDS:
|
|
116
|
+
raise ConstructError(f"{{policy.{field}}}: a policy declares {', '.join(POLICY_FIELDS)}")
|
|
117
|
+
if policy is None:
|
|
118
|
+
return None
|
|
119
|
+
return policy.get(field) if isinstance(policy, dict) else getattr(policy, field, None)
|
|
120
|
+
return _weights_of(form.group("part"), weights)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _weights_of(part: str | None, weights: Any) -> str:
|
|
124
|
+
if weights is None:
|
|
125
|
+
raise ConstructError("{weights} names the weights directory, and this policy declares no weights=")
|
|
126
|
+
if isinstance(weights, dict):
|
|
127
|
+
if part is None:
|
|
128
|
+
raise ConstructError(f"its weights come in named parts ({', '.join(sorted(weights))}): name one, "
|
|
129
|
+
f"{{weights.<part>}}")
|
|
130
|
+
if part not in weights:
|
|
131
|
+
raise ConstructError(f"{{weights.{part}}}: its weights have no part {part!r} "
|
|
132
|
+
f"({', '.join(sorted(weights))})")
|
|
133
|
+
return str(weights[part])
|
|
134
|
+
if part is not None:
|
|
135
|
+
raise ConstructError(f"{{weights.{part}}} names a part, and its weights come whole: {{weights}}")
|
|
136
|
+
return str(weights)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def build(cls: type, constructor: Any, *, base_dir: str, weights: Any = None, worlds: int | None = None,
|
|
140
|
+
policy: Any = None, params: dict | None = None) -> Any:
|
|
141
|
+
"""The instance `constructor` (a PolicyConstructor) makes of `cls`: `cls.<make>(*args, **kwargs)`, the function
|
|
142
|
+
make="package.module:function" names called so, or `cls(...)` - its arguments filled (expand), and `params`, what
|
|
143
|
+
an eval set of the constructor's other arguments (--param benchmark.NAME=VALUE), laid over them. A keyword argument
|
|
144
|
+
that is "{policy.<field>}" alone is left out while that field is None - no policy evaluated, at a registration
|
|
145
|
+
check, or one that declares none - so the constructor's own default holds, as a benchmark's own code did with what
|
|
146
|
+
@seq.setup was handed before."""
|
|
147
|
+
forms = {"base_dir": base_dir, "weights": weights, "worlds": worlds, "policy": policy}
|
|
148
|
+
args = expand(list(constructor.args), **forms)
|
|
149
|
+
kwargs = {}
|
|
150
|
+
for name, value in dict(constructor.kwargs).items():
|
|
151
|
+
filled = expand(value, **forms)
|
|
152
|
+
alone = FORMS.fullmatch(value) if isinstance(value, str) else None
|
|
153
|
+
if filled is None and alone is not None and alone.group("field") is not None:
|
|
154
|
+
continue
|
|
155
|
+
kwargs[name] = filled
|
|
156
|
+
return maker(cls, constructor.make)(*args, **{**kwargs, **(params or {})})
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def maker(cls: type, make: str | None) -> Any:
|
|
160
|
+
"""What builds the instance: `cls` for no make=, its classmethod or staticmethod `make`, or - make written
|
|
161
|
+
"package.module:function" - that module's function, the module imported (as the policy's code imports it).
|
|
162
|
+
"""
|
|
163
|
+
if not make:
|
|
164
|
+
return cls
|
|
165
|
+
module, colon, name = make.rpartition(":")
|
|
166
|
+
if not colon:
|
|
167
|
+
return getattr(cls, make)
|
|
168
|
+
found = getattr(importlib.import_module(module), name, None)
|
|
169
|
+
if found is None:
|
|
170
|
+
raise ConstructError(f"make={make!r}: {module} has no function {name!r}")
|
|
171
|
+
if not callable(found):
|
|
172
|
+
raise ConstructError(f"make={make!r}: {module}.{name} is not callable ({type(found).__name__})")
|
|
173
|
+
return found
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Contract 5 (registration half) - a benchmark is the env you already have, run as it is:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
do. The eval *run* wire types
|
|
2
|
+
Contract 5 (registration half) - a benchmark is the env you already have, run as it is: its class is built by its own
|
|
3
|
+
constructor after the machine's snapshot (init= its arguments, "{num_worlds}" and "{policy.<field>}" filled), a short class
|
|
4
|
+
of yours marks two methods - @seq.reset starts an episode of a task at a seed, @seq.step plays one action and says what
|
|
5
|
+
came of it - and declares its tasks, its seeds and how long an episode may run. The platform reads none of its
|
|
6
|
+
observations or actions: they go to the policy, and come from it, as a robot's do. The eval *run* wire types
|
|
7
|
+
(RolloutResult, EvalReport, ...) live in contract/eval.py.
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
"""
|
|
@@ -18,7 +19,8 @@ from sequence_base.constants.limits import MAX_ENVS, TASK_DESCRIPTION_MAX
|
|
|
18
19
|
from sequence_base.contract.accounts import SecretRef
|
|
19
20
|
from sequence_base.contract.deployments import CodeBundle, DeploymentState, InferParam
|
|
20
21
|
from sequence_base.contract.flags import BENCHMARK_BINDABLE, SeqFlags
|
|
21
|
-
from sequence_base.contract.policy import KIND_NAME, ImageSpec, VolumeRef
|
|
22
|
+
from sequence_base.contract.policy import KIND_NAME, ImageSpec, PolicyConstructor, VolumeRef
|
|
23
|
+
from sequence_base.construct import FORMS
|
|
22
24
|
|
|
23
25
|
__all__ = [
|
|
24
26
|
"ReplaySpec",
|
|
@@ -31,6 +33,27 @@ __all__ = [
|
|
|
31
33
|
TASK_NAME = r"^[A-Za-z0-9][A-Za-z0-9._/:-]{0,127}$"
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
|
|
37
|
+
SETUP_GONE = ("@seq.setup is gone: a benchmark builds its worlds in its constructor, after the machine's snapshot - "
|
|
38
|
+
'init= its arguments, "{num_worlds}" how many worlds this eval builds and "{policy.<field>}" what the '
|
|
39
|
+
"evaluated policy declares; a benchmark registered with @seq.setup is registered again with sequence-ai "
|
|
40
|
+
"0.51.1 or later (seq deploy)")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _names_worlds(constructor: PolicyConstructor | None) -> bool:
|
|
44
|
+
"""Whether init= hands the constructor "{num_worlds}" anywhere - in a string, at any depth."""
|
|
45
|
+
def walk(value) -> bool:
|
|
46
|
+
if isinstance(value, str):
|
|
47
|
+
return any(m.group("worlds") for m in FORMS.finditer(value))
|
|
48
|
+
if isinstance(value, dict):
|
|
49
|
+
return any(walk(v) for v in value.values())
|
|
50
|
+
if isinstance(value, (list, tuple)):
|
|
51
|
+
return any(walk(v) for v in value)
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
return constructor is not None and walk([constructor.args, constructor.kwargs])
|
|
55
|
+
|
|
56
|
+
|
|
34
57
|
def _check_tasks(tasks: dict, seeds: list, max_seconds) -> None:
|
|
35
58
|
import re as _re
|
|
36
59
|
|
|
@@ -75,11 +98,11 @@ class ReplaySpec(BaseModel):
|
|
|
75
98
|
|
|
76
99
|
|
|
77
100
|
class BenchmarkSpec(BaseModel):
|
|
78
|
-
"""What `@seq.benchmark(...)` and its marked methods add up to, as an eval runs it. `bindings` names the methods
|
|
79
|
-
RESET and STEP
|
|
80
|
-
stepping `worlds` worlds a call (@seq.concurrent(sizes=[N]) on its step),
|
|
81
|
-
time on the robot's clock, the same for every task or {task: seconds};
|
|
82
|
-
at /assets; `secrets` by name."""
|
|
101
|
+
"""What `@seq.benchmark(...)` and its marked methods add up to, as an eval runs it. `bindings` names the methods,
|
|
102
|
+
RESET and STEP; `constructor` the arguments its class is built with after the machine's snapshot (init=) - which a
|
|
103
|
+
vectorized env, one stepping `worlds` worlds a call (@seq.concurrent(sizes=[N]) on its step), hands how many,
|
|
104
|
+
"{num_worlds}". `max_seconds` is an episode's time on the robot's clock, the same for every task or {task: seconds};
|
|
105
|
+
`assets` are versioned scene volumes mounted at /assets; `secrets` by name."""
|
|
83
106
|
|
|
84
107
|
model_config = ConfigDict(extra="forbid")
|
|
85
108
|
|
|
@@ -89,7 +112,7 @@ class BenchmarkSpec(BaseModel):
|
|
|
89
112
|
seeds: list[int] = Field(..., description="The seeds an episode starts at; trial k of a task runs seeds[k % len]")
|
|
90
113
|
max_seconds: float | dict[str, float] = Field(..., description="An episode's time limit, or {task: seconds}")
|
|
91
114
|
handler_ref: str
|
|
92
|
-
bindings: dict[SeqFlags, str] = Field(..., description="
|
|
115
|
+
bindings: dict[SeqFlags, str] = Field(..., description="RESET / STEP -> method name")
|
|
93
116
|
|
|
94
117
|
|
|
95
118
|
worlds: int | None = Field(default=None, ge=1, le=MAX_ENVS)
|
|
@@ -106,6 +129,10 @@ class BenchmarkSpec(BaseModel):
|
|
|
106
129
|
|
|
107
130
|
engine: str | None = Field(default=None, pattern=KIND_NAME)
|
|
108
131
|
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
constructor: PolicyConstructor | None = None
|
|
135
|
+
|
|
109
136
|
@model_validator(mode="after")
|
|
110
137
|
def _tasks(self) -> "BenchmarkSpec":
|
|
111
138
|
_check_tasks(self.tasks, self.seeds, self.max_seconds)
|
|
@@ -113,15 +140,18 @@ class BenchmarkSpec(BaseModel):
|
|
|
113
140
|
|
|
114
141
|
@model_validator(mode="after")
|
|
115
142
|
def _bindings(self) -> "BenchmarkSpec":
|
|
143
|
+
if SeqFlags.SETUP in self.bindings:
|
|
144
|
+
raise ValueError(SETUP_GONE)
|
|
116
145
|
bad = set(self.bindings) - set(BENCHMARK_BINDABLE)
|
|
117
146
|
if bad:
|
|
118
147
|
names = ", ".join(sorted(f.name or str(f.value) for f in bad))
|
|
119
|
-
raise ValueError(f"a benchmark marks @seq.
|
|
148
|
+
raise ValueError(f"a benchmark marks @seq.reset and @seq.step only; got {names}")
|
|
120
149
|
missing = [f.name for f in (SeqFlags.RESET, SeqFlags.STEP) if f not in self.bindings]
|
|
121
150
|
if missing:
|
|
122
151
|
raise ValueError(f"a benchmark marks @seq.reset and @seq.step; {', '.join(missing).lower()} is missing")
|
|
123
|
-
if self.worlds is not None and
|
|
124
|
-
raise ValueError("a vectorized benchmark (@seq.concurrent on its step) builds its worlds in
|
|
152
|
+
if self.worlds is not None and not _names_worlds(self.constructor):
|
|
153
|
+
raise ValueError("a vectorized benchmark (@seq.concurrent on its step) builds its worlds in its "
|
|
154
|
+
'constructor, handed how many by init= - init={"worlds": "{num_worlds}"}')
|
|
125
155
|
return self
|
|
126
156
|
|
|
127
157
|
@model_validator(mode="after")
|
|
@@ -132,7 +162,7 @@ class BenchmarkSpec(BaseModel):
|
|
|
132
162
|
|
|
133
163
|
class BenchmarkRegisterRequest(BaseModel):
|
|
134
164
|
"""POST /v1/benchmarks - what `seq benchmark register` sends: the declaration, the code, and the parameters its
|
|
135
|
-
|
|
165
|
+
constructor takes with a default beside what init= hands it (each settable by an eval's --param, with its type)."""
|
|
136
166
|
|
|
137
167
|
model_config = ConfigDict(extra="forbid")
|
|
138
168
|
|
|
@@ -172,9 +202,8 @@ class BenchmarkRegisterRequest(BaseModel):
|
|
|
172
202
|
@model_validator(mode="after")
|
|
173
203
|
def _param_names(self) -> "BenchmarkRegisterRequest":
|
|
174
204
|
for name in self.params or {}:
|
|
175
|
-
if not name.isidentifier() or name.startswith("_")
|
|
176
|
-
raise ValueError(f"
|
|
177
|
-
"policy")
|
|
205
|
+
if not name.isidentifier() or name.startswith("_"):
|
|
206
|
+
raise ValueError(f"parameter {name!r} is not a public Python identifier")
|
|
178
207
|
return self
|
|
179
208
|
|
|
180
209
|
@model_validator(mode="after")
|
|
@@ -54,6 +54,11 @@ class ConnectRequest(BaseModel):
|
|
|
54
54
|
team: str | None = Field(default=None, description="the team this robot joins, by name")
|
|
55
55
|
group: str | None = Field(default=None, description="its group in that team; None: the default group")
|
|
56
56
|
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
team_key: str | None = Field(default=None, max_length=256,
|
|
60
|
+
description="a team key of the group it joins (seq_team_…); its group is the key's")
|
|
61
|
+
|
|
57
62
|
@model_validator(mode="before")
|
|
58
63
|
@classmethod
|
|
59
64
|
def _retired(cls, data: Any) -> Any:
|
|
@@ -67,6 +72,8 @@ class ConnectRequest(BaseModel):
|
|
|
67
72
|
if self.team is None:
|
|
68
73
|
raise ValueError("a group is a team's: say the team too")
|
|
69
74
|
check_name(self.group, "group")
|
|
75
|
+
if self.team_key is not None and self.team is None:
|
|
76
|
+
raise ValueError("a team key is a team's: say the team too")
|
|
70
77
|
return self
|
|
71
78
|
|
|
72
79
|
|
|
@@ -116,6 +123,12 @@ class ConnectResponse(BaseModel):
|
|
|
116
123
|
|
|
117
124
|
standby: Standby | None = None
|
|
118
125
|
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
standby_retry_s: float | None = Field(default=None, gt=0, le=3600,
|
|
130
|
+
description="no standby could be held yet: ask again in this many seconds")
|
|
131
|
+
|
|
119
132
|
@model_validator(mode="before")
|
|
120
133
|
@classmethod
|
|
121
134
|
def _retired(cls, data: Any) -> Any:
|
|
@@ -62,7 +62,8 @@ class SeqFlags(IntFlag):
|
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
|
|
66
|
+
BENCHMARK_BINDABLE: frozenset[SeqFlags] = frozenset({SeqFlags.RESET, SeqFlags.STEP})
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
def seqflags_json_schema(contract_version: str) -> dict:
|
|
@@ -544,13 +544,15 @@ _MAKE = r"^(?:[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*:)?[A-Za-z_][A-
|
|
|
544
544
|
|
|
545
545
|
|
|
546
546
|
class PolicyConstructor(BaseModel):
|
|
547
|
-
"""How the worker builds a policy
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
547
|
+
"""How the worker builds a policy's, a team's or a benchmark's class (`init=`): its own constructor, or the factory
|
|
548
|
+
it names (`make`: a classmethod of it, e.g. LeRobot's `from_pretrained`, or a module's function,
|
|
549
|
+
"package.module:function", whose return is the instance its methods are called on), called with `args` and `kwargs`
|
|
550
|
+
- a policy's at the replica's cold start, the weights on disk, where one deployed before sequence-ai 0.51.1 ran its
|
|
551
|
+
`@seq.load`; a benchmark's after the machine's snapshot (BenchmarkSpec.constructor). The values are the user's own,
|
|
552
|
+
as JSON carries them, but for the forms the worker fills in first (sequence_base.construct.expand): a config file's
|
|
553
|
+
contents, `{"$config": <its path from the class's file>, "$set": {<keys laid over it>}}`, YAML or JSON, and in any
|
|
554
|
+
string a policy's `"{weights}"` (the weights directory) or `"{weights.<part>}"` (a named part's), a benchmark's
|
|
555
|
+
`"{num_worlds}"` (how many worlds this eval builds) or `"{policy.<field>}"` (what the evaluated policy declares).
|
|
554
556
|
|
|
555
557
|
"""
|
|
556
558
|
|
|
@@ -563,6 +565,10 @@ class PolicyConstructor(BaseModel):
|
|
|
563
565
|
kwargs: dict[str, Any] = Field(default_factory=dict, description="keyword arguments")
|
|
564
566
|
|
|
565
567
|
|
|
568
|
+
|
|
569
|
+
_TEAM_BINDS = frozenset({SeqFlags.LOAD, SeqFlags.PLAN, SeqFlags.SHUTDOWN, SeqFlags.SAMPLE})
|
|
570
|
+
|
|
571
|
+
|
|
566
572
|
class PolicyRegistration(BaseModel):
|
|
567
573
|
"""What the harness loader introspects: the spec, the SeqFlags→method-name bindings, and the
|
|
568
574
|
`handler_ref` it importlib-loads the policy class from. From one of these the loader recovers which
|
|
@@ -596,15 +602,15 @@ class PolicyRegistration(BaseModel):
|
|
|
596
602
|
def _a_team_plans(self) -> "PolicyRegistration":
|
|
597
603
|
|
|
598
604
|
|
|
605
|
+
|
|
606
|
+
|
|
599
607
|
if self.spec.team is not None:
|
|
600
|
-
other = sorted(f.name for f in self.bindings if f not in
|
|
608
|
+
other = sorted(f.name for f in self.bindings if f not in _TEAM_BINDS)
|
|
601
609
|
if other:
|
|
602
|
-
raise ValueError(f"a team answers no act: it binds @seq.
|
|
610
|
+
raise ValueError(f"a team answers no act: it binds @seq.plan, @seq.shutdown and @seq.sample alone, not "
|
|
603
611
|
f"{', '.join(other)}")
|
|
604
612
|
if SeqFlags.PLAN not in self.bindings or self.plan_every_s is None:
|
|
605
613
|
raise ValueError("a team plans: it binds one @seq.plan(every_s=...)")
|
|
606
|
-
if self.constructor is not None:
|
|
607
|
-
raise ValueError("a team is built as a policy with @seq.load is, not by a constructor")
|
|
608
614
|
return self
|
|
609
615
|
|
|
610
616
|
@model_validator(mode="after")
|
|
@@ -613,7 +619,8 @@ class PolicyRegistration(BaseModel):
|
|
|
613
619
|
if SeqFlags.LOAD in self.bindings:
|
|
614
620
|
raise ValueError("a policy built by its constructor (constructor) has no @seq.load: its constructor is "
|
|
615
621
|
"its load")
|
|
616
|
-
if SeqFlags.INFER not in self.bindings:
|
|
622
|
+
if SeqFlags.INFER not in self.bindings and self.spec.team is None:
|
|
623
|
+
|
|
617
624
|
raise ValueError("a policy built by its constructor (constructor) names the method that answers an act "
|
|
618
625
|
"(an INFER binding)")
|
|
619
626
|
return self
|
{sequence_base-0.5.0 → sequence_base-0.5.1}/sequence_base/schemas/BenchmarkRegisterRequest.json
RENAMED
|
@@ -561,7 +561,7 @@
|
|
|
561
561
|
}
|
|
562
562
|
},
|
|
563
563
|
"additionalProperties": false,
|
|
564
|
-
"description": "POST /v1/benchmarks - what `seq benchmark register` sends: the declaration, the code, and the parameters its\
|
|
564
|
+
"description": "POST /v1/benchmarks - what `seq benchmark register` sends: the declaration, the code, and the parameters its\nconstructor takes with a default beside what init= hands it (each settable by an eval's --param, with its type).",
|
|
565
565
|
"properties": {
|
|
566
566
|
"assets": {
|
|
567
567
|
"items": {
|
|
@@ -766,5 +766,5 @@
|
|
|
766
766
|
],
|
|
767
767
|
"title": "BenchmarkRegisterRequest",
|
|
768
768
|
"type": "object",
|
|
769
|
-
"x-contract-version": "0.5.
|
|
769
|
+
"x-contract-version": "0.5.33"
|
|
770
770
|
}
|
|
@@ -234,6 +234,41 @@
|
|
|
234
234
|
"title": "ImageStepUvPip",
|
|
235
235
|
"type": "object"
|
|
236
236
|
},
|
|
237
|
+
"PolicyConstructor": {
|
|
238
|
+
"additionalProperties": false,
|
|
239
|
+
"description": "How the worker builds a policy's, a team's or a benchmark's class (`init=`): its own constructor, or the factory\nit names (`make`: a classmethod of it, e.g. LeRobot's `from_pretrained`, or a module's function,\n\"package.module:function\", whose return is the instance its methods are called on), called with `args` and `kwargs`\n- a policy's at the replica's cold start, the weights on disk, where one deployed before sequence-ai 0.51.1 ran its\n`@seq.load`; a benchmark's after the machine's snapshot (BenchmarkSpec.constructor). The values are the user's own,\nas JSON carries them, but for the forms the worker fills in first (sequence_base.construct.expand): a config file's\ncontents, `{\"$config\": <its path from the class's file>, \"$set\": {<keys laid over it>}}`, YAML or JSON, and in any\nstring a policy's `\"{weights}\"` (the weights directory) or `\"{weights.<part>}\"` (a named part's), a benchmark's\n`\"{num_worlds}\"` (how many worlds this eval builds) or `\"{policy.<field>}\"` (what the evaluated policy declares).",
|
|
240
|
+
"properties": {
|
|
241
|
+
"args": {
|
|
242
|
+
"description": "positional arguments, in order",
|
|
243
|
+
"items": {},
|
|
244
|
+
"title": "Args",
|
|
245
|
+
"type": "array"
|
|
246
|
+
},
|
|
247
|
+
"kwargs": {
|
|
248
|
+
"additionalProperties": true,
|
|
249
|
+
"description": "keyword arguments",
|
|
250
|
+
"title": "Kwargs",
|
|
251
|
+
"type": "object"
|
|
252
|
+
},
|
|
253
|
+
"make": {
|
|
254
|
+
"anyOf": [
|
|
255
|
+
{
|
|
256
|
+
"maxLength": 512,
|
|
257
|
+
"pattern": "^(?:[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*:)?[A-Za-z_][A-Za-z0-9_]*$",
|
|
258
|
+
"type": "string"
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"type": "null"
|
|
262
|
+
}
|
|
263
|
+
],
|
|
264
|
+
"default": null,
|
|
265
|
+
"description": "a classmethod or staticmethod that returns the instance, or a module's function, 'package.module:function' (contract 0.5.27); None: the class",
|
|
266
|
+
"title": "Make"
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
"title": "PolicyConstructor",
|
|
270
|
+
"type": "object"
|
|
271
|
+
},
|
|
237
272
|
"Project": {
|
|
238
273
|
"additionalProperties": false,
|
|
239
274
|
"description": "A project's own dependency files, which the image installs from (`seq.Image.from_project`, or a policy that\ndeclares no image and whose project has them): each read from the deploy's code bundle. The platform turns them into\nthe install when the image builds - for Linux and the worker's card, whatever machine the author wrote them on: the\nlock's exact versions, else the declared ones held to the versions the author's machine has (`pins`), the local\npackages the code imports with their own, less `exclude`, then `extra`.",
|
|
@@ -400,7 +435,7 @@
|
|
|
400
435
|
],
|
|
401
436
|
"title": "SeqFlags",
|
|
402
437
|
"type": "integer",
|
|
403
|
-
"x-contract-version": "0.5.
|
|
438
|
+
"x-contract-version": "0.5.33",
|
|
404
439
|
"x-flag-names": {
|
|
405
440
|
"ACTION": 1048576,
|
|
406
441
|
"CHECK": 65536,
|
|
@@ -472,7 +507,7 @@
|
|
|
472
507
|
}
|
|
473
508
|
},
|
|
474
509
|
"additionalProperties": false,
|
|
475
|
-
"description": "What `@seq.benchmark(...)` and its marked methods add up to, as an eval runs it. `bindings` names the methods
|
|
510
|
+
"description": "What `@seq.benchmark(...)` and its marked methods add up to, as an eval runs it. `bindings` names the methods,\nRESET and STEP; `constructor` the arguments its class is built with after the machine's snapshot (init=) - which a\nvectorized env, one stepping `worlds` worlds a call (@seq.concurrent(sizes=[N]) on its step), hands how many,\n\"{num_worlds}\". `max_seconds` is an episode's time on the robot's clock, the same for every task or {task: seconds};\n`assets` are versioned scene volumes mounted at /assets; `secrets` by name.",
|
|
476
511
|
"properties": {
|
|
477
512
|
"assets": {
|
|
478
513
|
"items": {
|
|
@@ -485,7 +520,7 @@
|
|
|
485
520
|
"additionalProperties": {
|
|
486
521
|
"type": "string"
|
|
487
522
|
},
|
|
488
|
-
"description": "
|
|
523
|
+
"description": "RESET / STEP -> method name",
|
|
489
524
|
"propertyNames": {
|
|
490
525
|
"enum": [
|
|
491
526
|
"1",
|
|
@@ -508,6 +543,17 @@
|
|
|
508
543
|
"title": "Bindings",
|
|
509
544
|
"type": "object"
|
|
510
545
|
},
|
|
546
|
+
"constructor": {
|
|
547
|
+
"anyOf": [
|
|
548
|
+
{
|
|
549
|
+
"$ref": "#/$defs/PolicyConstructor"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
"type": "null"
|
|
553
|
+
}
|
|
554
|
+
],
|
|
555
|
+
"default": null
|
|
556
|
+
},
|
|
511
557
|
"cpu": {
|
|
512
558
|
"anyOf": [
|
|
513
559
|
{
|
|
@@ -656,5 +702,5 @@
|
|
|
656
702
|
],
|
|
657
703
|
"title": "BenchmarkSpec",
|
|
658
704
|
"type": "object",
|
|
659
|
-
"x-contract-version": "0.5.
|
|
705
|
+
"x-contract-version": "0.5.33"
|
|
660
706
|
}
|