sequence-base 0.4.15__tar.gz → 0.4.17__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.4.15 → sequence_base-0.4.17}/PKG-INFO +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/pyproject.toml +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/__init__.py +6 -4
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/constants/version.py +3 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/__init__.py +7 -4
- sequence_base-0.4.17/sequence_base/contract/adapters.py +181 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/benchmarks.py +3 -4
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/deployments.py +2 -26
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/eval.py +5 -27
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/flags.py +3 -6
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/policy.py +4 -9
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schema_export.py +2 -4
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ActRequest.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ActResponse.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ActionChunk.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ActionContract.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ActionStep.json +1 -1
- sequence_base-0.4.17/sequence_base/schemas/AdapterPair.json +21 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/AddLocal.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Autoscaler.json +1 -13
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/BenchmarkConditionSpec.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/BenchmarkRegisterRequest.json +2 -2
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/BenchmarkSpec.json +4 -13
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/BenchmarkStatusResponse.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/BootstrapResponse.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Camera.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/CodeBundle.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Concurrency.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Conditions.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ConnectRequest.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ConnectResponse.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/DeploymentAccepted.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/DeploymentPolicy.json +1 -13
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/DeploymentRequest.json +2 -58
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/DeploymentStatusResponse.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Embodiment.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ErrorBody.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ErrorCodes.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Estimate.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/EvalDryRunResponse.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/EvalReport.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/EvalRequest.json +2 -32
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/EvalResponse.json +1 -38
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ImageFrame.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ImageSpec.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ImageStepAddLocal.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ImageStepApt.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ImageStepEnv.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ImageStepRun.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ImageStepTemplateFiles.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ImageStepUvPip.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/InferParam.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Lease.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/MetricAgg.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Observation.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ObservationContract.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/PolicyRegistration.json +5 -76
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/PolicySpec.json +4 -72
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Proprioception.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/RenderSpec.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/ReplaySpec.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Resources.json +2 -2
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/RolloutResult.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/SecretCreateRequest.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/SecretInfo.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/SecretRef.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/SeqFlags.json +1 -3
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Step.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/TaskAgg.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/TemplateFiles.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Timeouts.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/UploadTarget.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/Variant.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/VolumeFile.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/VolumeInfo.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/VolumeMount.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/VolumeRef.json +2 -2
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/VolumeUploadRequest.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/VolumeUploadResponse.json +1 -1
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/schemas/WarmingError.json +1 -1
- sequence_base-0.4.15/sequence_base/schemas/ClampInfo.json +0 -27
- sequence_base-0.4.15/sequence_base/schemas/VolumeAttach.json +0 -26
- {sequence_base-0.4.15 → sequence_base-0.4.17}/.gitignore +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/README.md +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/auth.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/codec/__init__.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/codec/image.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/constants/__init__.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/constants/headers.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/constants/limits.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/accounts.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/act.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/connect.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/errors.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/io.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/templates.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/volumes.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/contract/wire.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/errors/__init__.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/errors/transport.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/obs/__init__.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/obs/log.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/obs/rid.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/presets/__init__.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/presets/frames.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/presets/robot_arm.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/sequence_base/telemetry/__init__.py +0 -0
- {sequence_base-0.4.15 → sequence_base-0.4.17}/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.4.
|
|
3
|
+
Version: 0.4.17
|
|
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.4.
|
|
3
|
+
version = "0.4.17"
|
|
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"]
|
|
@@ -33,6 +33,8 @@ from sequence_base.contract import (
|
|
|
33
33
|
parse_vol,
|
|
34
34
|
TEMPLATE_SCHEME,
|
|
35
35
|
parse_template,
|
|
36
|
+
AdapterPair,
|
|
37
|
+
parse_pairs,
|
|
36
38
|
ActionChunk,
|
|
37
39
|
ActionContract,
|
|
38
40
|
ActionSpace,
|
|
@@ -43,7 +45,6 @@ from sequence_base.contract import (
|
|
|
43
45
|
BenchmarkStatusResponse,
|
|
44
46
|
BenchmarkSpec,
|
|
45
47
|
BootstrapResponse,
|
|
46
|
-
ClampInfo,
|
|
47
48
|
CodeBundle,
|
|
48
49
|
Concurrency,
|
|
49
50
|
Conditions,
|
|
@@ -90,7 +91,6 @@ from sequence_base.contract import (
|
|
|
90
91
|
TaskAgg,
|
|
91
92
|
Timeouts,
|
|
92
93
|
Variant,
|
|
93
|
-
VolumeAttach,
|
|
94
94
|
VolumeMount,
|
|
95
95
|
VolumeRef,
|
|
96
96
|
WarmingError,
|
|
@@ -135,13 +135,13 @@ __all__ = [
|
|
|
135
135
|
"PolicySpec", "PolicyRegistration",
|
|
136
136
|
|
|
137
137
|
"MAX_CODE_BUNDLE_BYTES", "CodeBundle",
|
|
138
|
-
"Resources", "Autoscaler", "Timeouts", "
|
|
138
|
+
"Resources", "Autoscaler", "Timeouts", "DeploymentPolicy", "InferParam", "DeploymentRequest",
|
|
139
139
|
"DeploymentAccepted", "DeploymentState", "DeploymentStatusResponse",
|
|
140
140
|
|
|
141
141
|
"Lease", "ConnectRequest", "ConnectResponse",
|
|
142
142
|
|
|
143
143
|
"Variant", "Conditions", "RenderSpec", "ReplaySpec", "Step", "BenchmarkSpec", "BenchmarkConditionSpec", "BenchmarkRegisterRequest", "BenchmarkStatusResponse",
|
|
144
|
-
"EvalRequest", "
|
|
144
|
+
"EvalRequest", "Estimate", "EvalResponse", "EvalDryRunResponse", "RolloutResult",
|
|
145
145
|
"EvalStatus", "TaskAgg", "MetricAgg", "EvalReport",
|
|
146
146
|
|
|
147
147
|
"SecretRef", "SecretCreateRequest", "SecretInfo", "BootstrapResponse",
|
|
@@ -150,6 +150,8 @@ __all__ = [
|
|
|
150
150
|
|
|
151
151
|
"TEMPLATE_SCHEME", "parse_template",
|
|
152
152
|
|
|
153
|
+
"AdapterPair", "parse_pairs",
|
|
154
|
+
|
|
153
155
|
"ErrorCode", "ErrorBody", "WarmingError", "ERRORS", "ErrorSpec", "code_for_status", "CONTRACT_VERSION",
|
|
154
156
|
"MAX_ENVS", "MAX_USD", "TASK_DESCRIPTION_MAX",
|
|
155
157
|
|
|
@@ -53,7 +53,6 @@ from sequence_base.contract.deployments import (
|
|
|
53
53
|
DeploymentStatusResponse,
|
|
54
54
|
Resources,
|
|
55
55
|
Timeouts,
|
|
56
|
-
VolumeAttach,
|
|
57
56
|
)
|
|
58
57
|
|
|
59
58
|
|
|
@@ -72,7 +71,6 @@ from sequence_base.contract.benchmarks import (
|
|
|
72
71
|
Variant,
|
|
73
72
|
)
|
|
74
73
|
from sequence_base.contract.eval import (
|
|
75
|
-
ClampInfo,
|
|
76
74
|
Estimate,
|
|
77
75
|
EvalDryRunResponse,
|
|
78
76
|
EvalReport,
|
|
@@ -96,6 +94,9 @@ from sequence_base.contract.accounts import (
|
|
|
96
94
|
from sequence_base.contract.templates import TEMPLATE_SCHEME, parse_template
|
|
97
95
|
|
|
98
96
|
|
|
97
|
+
from sequence_base.contract.adapters import AdapterPair, parse_pairs
|
|
98
|
+
|
|
99
|
+
|
|
99
100
|
from sequence_base.contract.volumes import (
|
|
100
101
|
MAX_FILES,
|
|
101
102
|
MAX_UPLOAD_BYTES,
|
|
@@ -123,13 +124,13 @@ __all__ = [
|
|
|
123
124
|
"PolicySpec", "PolicyRegistration",
|
|
124
125
|
|
|
125
126
|
"MAX_CODE_BUNDLE_BYTES", "CodeBundle",
|
|
126
|
-
"Resources", "Autoscaler", "Timeouts", "
|
|
127
|
+
"Resources", "Autoscaler", "Timeouts", "DeploymentPolicy", "InferParam", "DeploymentRequest",
|
|
127
128
|
"DeploymentAccepted", "DeploymentState", "DeploymentStatusResponse",
|
|
128
129
|
|
|
129
130
|
"Lease", "ConnectRequest", "ConnectResponse",
|
|
130
131
|
|
|
131
132
|
"Variant", "Conditions", "RenderSpec", "ReplaySpec", "Step", "BenchmarkSpec", "BenchmarkConditionSpec", "BenchmarkRegisterRequest", "BenchmarkStatusResponse",
|
|
132
|
-
"EvalRequest", "
|
|
133
|
+
"EvalRequest", "Estimate", "EvalResponse", "EvalDryRunResponse", "RolloutResult",
|
|
133
134
|
"EvalStatus", "TaskAgg", "MetricAgg", "EvalReport",
|
|
134
135
|
|
|
135
136
|
"SecretRef", "SecretCreateRequest", "SecretInfo", "BootstrapResponse",
|
|
@@ -139,5 +140,7 @@ __all__ = [
|
|
|
139
140
|
|
|
140
141
|
"TEMPLATE_SCHEME", "parse_template",
|
|
141
142
|
|
|
143
|
+
"AdapterPair", "parse_pairs",
|
|
144
|
+
|
|
142
145
|
"ErrorCode", "ErrorBody", "WarmingError", "ERRORS", "ErrorSpec", "code_for_status",
|
|
143
146
|
]
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""
|
|
2
|
+
An adapter's pairs - the benchmark → policy pairs a registered adapter converts between.
|
|
3
|
+
|
|
4
|
+
In one sentence: an adapter's author writes in its code which pairs its conversion is for - `@seq.adapter(pairs=[
|
|
5
|
+
(benchmark, policy), ...])`, each side an account's name, `template:<name>` (anything made from that template, at any
|
|
6
|
+
version) or `*` (any one), or `pairs="any"` for every pair → `seq deploy` registers them with the version → as an eval
|
|
7
|
+
starts, the gateway matches the eval's benchmark and policy against them (match) and refuses the rest before anything
|
|
8
|
+
runs. The rules are defined once, here: the SDK reads them (the decorator, `seq adapter check`) and so does the
|
|
9
|
+
gateway (registration, the eval's check, which adapters fit a pair), so what can be chosen is what runs.
|
|
10
|
+
WHY in the code, with the version: which pairs a conversion is for is part of the conversion - changing them is a new
|
|
11
|
+
version, and an eval keeps the version it ran. WHY by name and never by version: a benchmark's or a policy's I/O
|
|
12
|
+
seldom changes with its version, and pinned pairs would make every upgrade a new adapter. WHY a pair need not exist
|
|
13
|
+
yet: an adapter may come before the policy it feeds; names are matched as an eval starts.
|
|
14
|
+
{the user 10-19, through TEST USER: "you need to specify which benchmark and which policy you want the conversion to
|
|
15
|
+
be and then you can specify multiple … you can only apply those that are stated here as the pairs"; "We should have
|
|
16
|
+
the option to open to all"}
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
from typing import Any, Iterable, Literal, Union
|
|
23
|
+
|
|
24
|
+
from pydantic import BaseModel, ConfigDict
|
|
25
|
+
|
|
26
|
+
ANY = "any"
|
|
27
|
+
WILDCARD = "*"
|
|
28
|
+
TEMPLATE = "template:"
|
|
29
|
+
MAX_PAIRS = 64
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
_NAME = re.compile(r"[A-Za-z0-9][A-Za-z0-9._-]{0,63}")
|
|
34
|
+
_TEMPLATE_NAME = re.compile(r"[a-z0-9][a-z0-9-]{0,63}")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class AdapterPair(BaseModel):
|
|
38
|
+
"""One pair an adapter converts between: its benchmark side and its policy side, each an account's name,
|
|
39
|
+
`template:<name>` or `*`."""
|
|
40
|
+
|
|
41
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
42
|
+
|
|
43
|
+
benchmark: str
|
|
44
|
+
policy: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
Pairs = Union[Literal["any"], list[AdapterPair]]
|
|
48
|
+
|
|
49
|
+
_EXAMPLE = 'pairs=[("libero-10", "my-pi05"), ("template:libero-spatial", "*")], or pairs="any"'
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _side(value: Any, which: str, i: int) -> str:
|
|
53
|
+
if not isinstance(value, str) or not value.strip():
|
|
54
|
+
raise ValueError(f"pair {i}: its {which} is {value!r}, not a name")
|
|
55
|
+
side = value.strip()
|
|
56
|
+
if side == WILDCARD:
|
|
57
|
+
return side
|
|
58
|
+
if side.startswith(TEMPLATE):
|
|
59
|
+
if not _TEMPLATE_NAME.fullmatch(side[len(TEMPLATE):]):
|
|
60
|
+
raise ValueError(f"pair {i}: {which} {value!r}: a template is template:<name>, the name `seq init` takes "
|
|
61
|
+
"(lowercase letters, digits or '-'), e.g. template:libero-10")
|
|
62
|
+
return side
|
|
63
|
+
if not _NAME.fullmatch(side):
|
|
64
|
+
raise ValueError(f"pair {i}: {which} {value!r} is no name: 1-64 letters, digits, '.', '_' or '-', starting "
|
|
65
|
+
"with a letter or digit - or template:<name>, or *")
|
|
66
|
+
return side
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def parse_pairs(value: Any) -> Pairs:
|
|
70
|
+
"""`"any"`, or the pairs as [(benchmark, policy), ...] or [{"benchmark", "policy"}, ...] → "any" or [AdapterPair,
|
|
71
|
+
...] in their order, each once. Raises ValueError saying which pair and which side is wrong; None and [] are wrong
|
|
72
|
+
too - an adapter says which pairs it is for, or "any"."""
|
|
73
|
+
if isinstance(value, str):
|
|
74
|
+
if value == ANY:
|
|
75
|
+
return ANY
|
|
76
|
+
raise ValueError(f"pairs is {value!r}: write the (benchmark, policy) pairs the adapter converts between - "
|
|
77
|
+
f"{_EXAMPLE}")
|
|
78
|
+
if value is None:
|
|
79
|
+
raise ValueError(f"the adapter declares no pairs: say which benchmark → policy pairs it converts between - "
|
|
80
|
+
f"{_EXAMPLE}")
|
|
81
|
+
try:
|
|
82
|
+
items = list(value)
|
|
83
|
+
except TypeError:
|
|
84
|
+
raise ValueError(f"pairs is {value!r}, not a list of (benchmark, policy) pairs - {_EXAMPLE}") from None
|
|
85
|
+
if not items:
|
|
86
|
+
raise ValueError(f"pairs is empty: name at least one (benchmark, policy) pair - {_EXAMPLE}")
|
|
87
|
+
out: list[AdapterPair] = []
|
|
88
|
+
for i, item in enumerate(items, 1):
|
|
89
|
+
if isinstance(item, AdapterPair):
|
|
90
|
+
bench, policy = item.benchmark, item.policy
|
|
91
|
+
elif isinstance(item, dict) and set(item) == {"benchmark", "policy"}:
|
|
92
|
+
bench, policy = item["benchmark"], item["policy"]
|
|
93
|
+
elif isinstance(item, (list, tuple)) and len(item) == 2:
|
|
94
|
+
bench, policy = item
|
|
95
|
+
else:
|
|
96
|
+
raise ValueError(f"pair {i} is {item!r}: a pair is (benchmark, policy)")
|
|
97
|
+
pair = AdapterPair(benchmark=_side(bench, "benchmark", i), policy=_side(policy, "policy", i))
|
|
98
|
+
if pair not in out:
|
|
99
|
+
out.append(pair)
|
|
100
|
+
if len(out) > MAX_PAIRS:
|
|
101
|
+
raise ValueError(f"{len(out)} pairs; at most {MAX_PAIRS} - template:<name> or * names many at once")
|
|
102
|
+
return out
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def as_json(pairs: Pairs | None) -> str | list[dict] | None:
|
|
106
|
+
"""The pairs as the wire, the API and the table carry them: "any", [{"benchmark", "policy"}, ...], or None (a
|
|
107
|
+
version registered before pairs)."""
|
|
108
|
+
if pairs is None or pairs == ANY:
|
|
109
|
+
return pairs
|
|
110
|
+
return [p.model_dump() for p in pairs]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _stored(pairs: Any) -> Pairs | None:
|
|
114
|
+
"""Pairs as kept (as_json's form) or as parsed; None for none - never raises on what parse_pairs once accepted."""
|
|
115
|
+
if pairs is None or pairs == ANY:
|
|
116
|
+
return pairs
|
|
117
|
+
return [p if isinstance(p, AdapterPair) else AdapterPair(**p) for p in pairs]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def image_templates(image: Any) -> set[str]:
|
|
121
|
+
"""The templates an image installs the files of - each `template_files` step's template, the line `seq init` writes
|
|
122
|
+
into a template's entry file and a user who edits the code keeps: what makes a benchmark or a policy one of the
|
|
123
|
+
template's for `template:<name>`. `image`: an ImageSpec, or its dict as a request or a stored spec carries it."""
|
|
124
|
+
if image is None:
|
|
125
|
+
return set()
|
|
126
|
+
steps = image.get("steps") if isinstance(image, dict) else getattr(image, "steps", None)
|
|
127
|
+
out: set[str] = set()
|
|
128
|
+
for step in steps or ():
|
|
129
|
+
files = step.get("template_files") if isinstance(step, dict) else getattr(step, "template_files", None)
|
|
130
|
+
name = files.get("template") if isinstance(files, dict) else getattr(files, "template", None)
|
|
131
|
+
if isinstance(name, str) and name:
|
|
132
|
+
out.add(name)
|
|
133
|
+
return out
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def side_matches(side: str, name: str, templates: Iterable[str] = ()) -> bool:
|
|
137
|
+
"""Whether one side of a pair is this benchmark or policy: `*`; `template:<t>` for one made from t; or its name."""
|
|
138
|
+
if side == WILDCARD:
|
|
139
|
+
return True
|
|
140
|
+
if side.startswith(TEMPLATE):
|
|
141
|
+
return side[len(TEMPLATE):] in set(templates or ())
|
|
142
|
+
return side == name
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _rank_side(side: str) -> int:
|
|
146
|
+
return 3 if side == WILDCARD else 1 if side.startswith(TEMPLATE) else 0
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def rank(hit: AdapterPair | str) -> int:
|
|
150
|
+
"""How specific a matching pair is, the most specific lowest: name and name 0, name and template 1, template and
|
|
151
|
+
template 2, a side `*` 3 and over, "any" 7 - the order an eval's adapters are offered in."""
|
|
152
|
+
if hit == ANY:
|
|
153
|
+
return 7
|
|
154
|
+
return _rank_side(hit.benchmark) + _rank_side(hit.policy)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def match(pairs: Any, benchmark: tuple[str, Iterable[str]],
|
|
158
|
+
policy: tuple[str, Iterable[str]]) -> AdapterPair | str | None:
|
|
159
|
+
"""The pair of `pairs` that lets `benchmark` and `policy` - each (its name in the account, the templates it is
|
|
160
|
+
made from) - run with the adapter: the most specific one (rank); "any" for an adapter open to every pair; None
|
|
161
|
+
when none does, and for no pairs (a version registered before pairs)."""
|
|
162
|
+
pairs = _stored(pairs)
|
|
163
|
+
if pairs is None:
|
|
164
|
+
return None
|
|
165
|
+
if pairs == ANY:
|
|
166
|
+
return ANY
|
|
167
|
+
(bench_name, bench_templates), (policy_name, policy_templates) = benchmark, policy
|
|
168
|
+
hits = [p for p in pairs if side_matches(p.benchmark, bench_name, bench_templates)
|
|
169
|
+
and side_matches(p.policy, policy_name, policy_templates)]
|
|
170
|
+
return min(hits, key=rank) if hits else None
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def describe(pairs: Any) -> list[str]:
|
|
174
|
+
"""The pairs as lines a person reads: ["any"], or ["template:libero-10 → template:pi05-libero", ...]; [] for
|
|
175
|
+
none."""
|
|
176
|
+
pairs = _stored(pairs)
|
|
177
|
+
if pairs is None:
|
|
178
|
+
return []
|
|
179
|
+
if pairs == ANY:
|
|
180
|
+
return [ANY]
|
|
181
|
+
return [f"{p.benchmark} → {p.policy}" for p in pairs]
|
|
@@ -113,8 +113,7 @@ class BenchmarkSpec(BaseModel):
|
|
|
113
113
|
⑦: a benchmark also references secrets by name). `assets` are versioned scene/mesh/URDF/MJCF/USD volumes
|
|
114
114
|
the worker mounts at /assets (reusing S2's Volume mechanism). `render` optionally declares the mp4.
|
|
115
115
|
`max_steps` is the platform SAFETY cap (cost backstop, records `truncated` — NOT semantic termination;
|
|
116
|
-
`done` is decided by @seq.check). `bindings` covers SETUP / RESET / CHECK / SCORE (
|
|
117
|
-
and must not appear)."""
|
|
116
|
+
`done` is decided by @seq.check). `bindings` covers SETUP / RESET / CHECK / SCORE (+ OBSERVE / STEP)."""
|
|
118
117
|
|
|
119
118
|
model_config = ConfigDict(extra="forbid")
|
|
120
119
|
|
|
@@ -124,7 +123,8 @@ class BenchmarkSpec(BaseModel):
|
|
|
124
123
|
max_steps: int = Field(..., description="Platform safety cap; truncates and records truncated")
|
|
125
124
|
handler_ref: str
|
|
126
125
|
bindings: dict[SeqFlags, str] = Field(..., description="SETUP / RESET / CHECK / SCORE (+ OBSERVE / STEP) → method name")
|
|
127
|
-
|
|
126
|
+
|
|
127
|
+
gpu: str | None = None
|
|
128
128
|
|
|
129
129
|
envs: int | None = Field(default=None, ge=1, le=MAX_ENVS)
|
|
130
130
|
assets: list[VolumeRef] = Field(default_factory=list)
|
|
@@ -146,7 +146,6 @@ class BenchmarkSpec(BaseModel):
|
|
|
146
146
|
names = ", ".join(sorted(f.name or str(f.value) for f in bad))
|
|
147
147
|
raise ValueError(
|
|
148
148
|
f"benchmark bindings may only cover SETUP / RESET / CHECK / SCORE / OBSERVE / STEP; got disallowed {names}"
|
|
149
|
-
" (ROLLOUT is deprecated and must not be bound)"
|
|
150
149
|
)
|
|
151
150
|
batched = set(self.bindings) & set(BENCHMARK_BATCHED)
|
|
152
151
|
if batched and batched != set(BENCHMARK_BATCHED):
|
|
@@ -36,7 +36,6 @@ __all__ = [
|
|
|
36
36
|
"Resources",
|
|
37
37
|
"Autoscaler",
|
|
38
38
|
"Timeouts",
|
|
39
|
-
"VolumeAttach",
|
|
40
39
|
"DeploymentPolicy",
|
|
41
40
|
"DeploymentRequest",
|
|
42
41
|
"DeploymentAccepted",
|
|
@@ -46,7 +45,8 @@ __all__ = [
|
|
|
46
45
|
|
|
47
46
|
|
|
48
47
|
class Resources(BaseModel):
|
|
49
|
-
"""The hardware a worker runs on. `gpu` is list[str]
|
|
48
|
+
"""The hardware a worker runs on. `gpu` is list[str], the PolicySpec's one card as a list of one - the shape a
|
|
49
|
+
deployment's spec is kept in, so one stored from before a list was refused (0.4.15) still reads."""
|
|
50
50
|
|
|
51
51
|
model_config = ConfigDict(extra="forbid")
|
|
52
52
|
|
|
@@ -83,9 +83,6 @@ class Autoscaler(BaseModel):
|
|
|
83
83
|
min_containers: int = 0
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
max_containers: int | None = None
|
|
87
|
-
|
|
88
|
-
|
|
89
86
|
max_gpus: int | None = Field(default=None, ge=1, le=256)
|
|
90
87
|
buffer_containers: int | None = None
|
|
91
88
|
scaledown_window: int = 600
|
|
@@ -108,21 +105,6 @@ class Timeouts(BaseModel):
|
|
|
108
105
|
startup: int = Field(..., ge=60, le=18000)
|
|
109
106
|
|
|
110
107
|
|
|
111
|
-
class VolumeAttach(BaseModel):
|
|
112
|
-
"""A non-weights volume mount in the deploy body (goal 7). Distinct from `weights` (a `VolumeMount`,
|
|
113
|
-
a provisioned pull at the reserved `/data`): an explicit `volumes=` attachment names a persistent
|
|
114
|
-
volume by `vol://<name>` ref, pins its container `mount`, and carries the `create_if_missing`
|
|
115
|
-
provisioning intent so the gateway either binds an existing volume or creates it — the semantic the
|
|
116
|
-
wire `VolumeMount` deliberately does not carry. Not reused/extended from `VolumeMount` because
|
|
117
|
-
`create_if_missing` is meaningless for the weights pull."""
|
|
118
|
-
|
|
119
|
-
model_config = ConfigDict(extra="forbid")
|
|
120
|
-
|
|
121
|
-
uri: str
|
|
122
|
-
mount: str
|
|
123
|
-
create_if_missing: bool
|
|
124
|
-
|
|
125
|
-
|
|
126
108
|
class InferParam(BaseModel):
|
|
127
109
|
"""One inference parameter the policy's `@seq.infer` declares — `def infer(self, obs, *, num_steps: int = 10)`
|
|
128
110
|
— with its type and default. An /act or an eval may set it; the worker passes only declared names, cast to
|
|
@@ -190,9 +172,6 @@ class DeploymentPolicy(BaseModel):
|
|
|
190
172
|
handler_ref: str
|
|
191
173
|
action: ActionContract | None = None
|
|
192
174
|
streaming: bool = False
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
frames_per_chunk: int | None = None
|
|
196
175
|
secrets: list[SecretRef] = Field(default_factory=list)
|
|
197
176
|
|
|
198
177
|
|
|
@@ -289,9 +268,6 @@ class DeploymentRequest(BaseModel):
|
|
|
289
268
|
|
|
290
269
|
|
|
291
270
|
image_context: CodeBundle | None = None
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
volumes: list[VolumeAttach] = Field(default_factory=list)
|
|
295
271
|
autoscaler: Autoscaler = Field(default_factory=Autoscaler)
|
|
296
272
|
|
|
297
273
|
concurrency: Concurrency = Field(default_factory=Concurrency)
|
|
@@ -18,7 +18,6 @@ from sequence_base.constants.limits import MAX_ENVS, MAX_USD
|
|
|
18
18
|
|
|
19
19
|
__all__ = [
|
|
20
20
|
"EvalRequest",
|
|
21
|
-
"ClampInfo",
|
|
22
21
|
"ArmReport",
|
|
23
22
|
"EvalTiming",
|
|
24
23
|
"Estimate",
|
|
@@ -45,10 +44,11 @@ class EvalRequest(BaseModel):
|
|
|
45
44
|
"""`POST /v1/eval`. A real eval names `model` + `benchmark`; a rerun (`rerun_of` / `rerun_unsuccessful_of`) may
|
|
46
45
|
leave them out and take the earlier eval's. `dry_run` selects the estimate-only response shape below.
|
|
47
46
|
|
|
48
|
-
The one body the platform accepts
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
model rather than keeping its own.
|
|
47
|
+
The one body the platform accepts, the newest SDK's: the names an older SDK sent (`gpus`, `envs_per_gpu`,
|
|
48
|
+
`benchmark_gpu`, `region`) are gone, refused as any field this body does not define, since every client the
|
|
49
|
+
platform serves is the newest (the user 10-19: "This is the latest version that we want everything to be based on,
|
|
50
|
+
so delete all the old stuff"). The gateway inherits this model rather than keeping its own.
|
|
51
|
+
"""
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
|
|
@@ -70,12 +70,6 @@ class EvalRequest(BaseModel):
|
|
|
70
70
|
policy_machines: int | None = Field(default=None, ge=1, le=64)
|
|
71
71
|
policy_gpu: str | None = Field(default=None, max_length=32)
|
|
72
72
|
benchmark_machines: int | None = Field(default=None, ge=1, le=64)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
benchmark_gpu: str | None = Field(default=None, max_length=32, json_schema_extra={"deprecated": True},
|
|
77
|
-
description="Not accepted: an eval runs on the card its benchmark was registered "
|
|
78
|
-
"on, so a card is refused. Omit it (an older SDK still sends it).")
|
|
79
73
|
envs: int | None = Field(default=None, ge=1)
|
|
80
74
|
adapter: str | None = Field(default=None, max_length=200)
|
|
81
75
|
|
|
@@ -107,11 +101,6 @@ class EvalRequest(BaseModel):
|
|
|
107
101
|
|
|
108
102
|
replay: Literal["3d", "none"] | None = None
|
|
109
103
|
|
|
110
|
-
|
|
111
|
-
region: str | None = Field(default=None, max_length=32, json_schema_extra={"deprecated": True},
|
|
112
|
-
description="Not accepted: an eval's machines run wherever there are cards, so a region "
|
|
113
|
-
"is refused. Omit it (an older SDK still sends it).")
|
|
114
|
-
|
|
115
104
|
@field_validator("envs")
|
|
116
105
|
@classmethod
|
|
117
106
|
def _envs_cap(cls, v: int | None) -> int | None:
|
|
@@ -141,16 +130,6 @@ class EvalRequest(BaseModel):
|
|
|
141
130
|
return self
|
|
142
131
|
|
|
143
132
|
|
|
144
|
-
class ClampInfo(BaseModel):
|
|
145
|
-
"""Why the granted GPU count was clamped below the request — structured, not a bare value."""
|
|
146
|
-
|
|
147
|
-
model_config = ConfigDict(extra="forbid")
|
|
148
|
-
|
|
149
|
-
limit: str = Field(..., description="Which limit bound it, e.g. 'account_quota'")
|
|
150
|
-
requested: int
|
|
151
|
-
granted: int
|
|
152
|
-
|
|
153
|
-
|
|
154
133
|
class Estimate(BaseModel):
|
|
155
134
|
model_config = ConfigDict(extra="forbid")
|
|
156
135
|
|
|
@@ -175,7 +154,6 @@ class EvalResponse(BaseModel):
|
|
|
175
154
|
eval_id: str
|
|
176
155
|
gpus_granted: int
|
|
177
156
|
estimate: Estimate
|
|
178
|
-
clamped_by: ClampInfo | None = None
|
|
179
157
|
|
|
180
158
|
queue: EvalQueue | None = None
|
|
181
159
|
|
|
@@ -9,12 +9,12 @@ plan step; and the benchmark SETUP / RESET / CHECK / SCORE quartet.
|
|
|
9
9
|
eval-raw revision: the platform provides the reset→step→check loop as a tool; the user defines the goal
|
|
10
10
|
through four hooks — SETUP (load sim + assets), RESET (build one episode's env), CHECK (per-step: read raw
|
|
11
11
|
env state → done + user-named metrics), SCORE (cross-episode aggregate). RESET=32768 and CHECK=65536 are
|
|
12
|
-
the new hook bits.
|
|
13
|
-
another member
|
|
12
|
+
the new hook bits. Bit 8192 was the old single-hook ROLLOUT, gone with every SDK that knew it (sequence-base 0.4.15):
|
|
13
|
+
it stays unused, never given to another member, so nothing serialized before reads as a hook it never was.
|
|
14
14
|
|
|
15
15
|
The exact bit values are the contract: a registration serialized by one version must decode the same in
|
|
16
16
|
another. A member taking the wrong value, WARMUP collapsing back into LOAD, RESET/CHECK overlapping an
|
|
17
|
-
existing bit, or
|
|
17
|
+
existing bit, or bit 8192 being given out again is caught bit-by-bit (see tests), not waved away with "an IntFlag
|
|
18
18
|
is naturally bit-composable".
|
|
19
19
|
"""
|
|
20
20
|
from __future__ import annotations
|
|
@@ -48,9 +48,6 @@ class SeqFlags(IntFlag):
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
ROLLOUT = 8192
|
|
52
|
-
|
|
53
|
-
|
|
54
51
|
|
|
55
52
|
|
|
56
53
|
BENCHMARK_BINDABLE: frozenset[SeqFlags] = frozenset(
|
|
@@ -172,7 +172,7 @@ class VolumeMount(BaseModel):
|
|
|
172
172
|
|
|
173
173
|
|
|
174
174
|
class VolumeRef(BaseModel):
|
|
175
|
-
"""
|
|
175
|
+
"""A volume a benchmark mounts (BenchmarkSpec.assets): at least a `uri`; a `mount` may pin the container path."""
|
|
176
176
|
|
|
177
177
|
model_config = ConfigDict(extra="forbid")
|
|
178
178
|
|
|
@@ -243,17 +243,15 @@ class PolicySpec(BaseModel):
|
|
|
243
243
|
model_config = ConfigDict(extra="forbid")
|
|
244
244
|
|
|
245
245
|
name: str
|
|
246
|
-
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
gpu: str = Field(..., description='The one card a worker runs on: "L4", "H100:2" for two of one type, or "cpu"')
|
|
247
249
|
image: ImageSpec
|
|
248
250
|
|
|
249
251
|
weights: str | None = Field(None, description="Weights URI: template:// (an official template), hf:// or vol:// "
|
|
250
252
|
"(an uploaded volume); none for a policy without a checkpoint")
|
|
251
|
-
volumes: dict[str, VolumeRef] = Field(default_factory=dict)
|
|
252
253
|
secrets: list[SecretRef] = Field(default_factory=list)
|
|
253
254
|
min_containers: int = 0
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
max_containers: int | None = None
|
|
257
255
|
max_gpus: int | None = Field(default=None, ge=1, le=256)
|
|
258
256
|
buffer_containers: int | None = None
|
|
259
257
|
scaledown_window: int = 600
|
|
@@ -262,9 +260,6 @@ class PolicySpec(BaseModel):
|
|
|
262
260
|
concurrency: Concurrency | None = None
|
|
263
261
|
streaming: bool = False
|
|
264
262
|
|
|
265
|
-
|
|
266
|
-
frames_per_chunk: int | None = None
|
|
267
|
-
|
|
268
263
|
action: ActionContract | None = None
|
|
269
264
|
|
|
270
265
|
observation: ObservationContract | None = None
|
|
@@ -56,8 +56,8 @@ from sequence_base.contract.deployments import (
|
|
|
56
56
|
DeploymentStatusResponse,
|
|
57
57
|
Resources,
|
|
58
58
|
Timeouts,
|
|
59
|
-
VolumeAttach,
|
|
60
59
|
)
|
|
60
|
+
from sequence_base.contract.adapters import AdapterPair
|
|
61
61
|
from sequence_base.contract.errors import ErrorBody, WarmingError, error_codes_json_schema
|
|
62
62
|
from sequence_base.contract.volumes import (
|
|
63
63
|
UploadTarget,
|
|
@@ -67,7 +67,6 @@ from sequence_base.contract.volumes import (
|
|
|
67
67
|
VolumeUploadResponse,
|
|
68
68
|
)
|
|
69
69
|
from sequence_base.contract.eval import (
|
|
70
|
-
ClampInfo,
|
|
71
70
|
Estimate,
|
|
72
71
|
EvalDryRunResponse,
|
|
73
72
|
EvalReport,
|
|
@@ -136,7 +135,6 @@ WIRE_MODELS: dict[str, type[BaseModel]] = {
|
|
|
136
135
|
"Resources": Resources,
|
|
137
136
|
"Autoscaler": Autoscaler,
|
|
138
137
|
"Timeouts": Timeouts,
|
|
139
|
-
"VolumeAttach": VolumeAttach,
|
|
140
138
|
"CodeBundle": CodeBundle,
|
|
141
139
|
"DeploymentPolicy": DeploymentPolicy,
|
|
142
140
|
"InferParam": InferParam,
|
|
@@ -159,7 +157,6 @@ WIRE_MODELS: dict[str, type[BaseModel]] = {
|
|
|
159
157
|
"BenchmarkStatusResponse": BenchmarkStatusResponse,
|
|
160
158
|
|
|
161
159
|
"EvalRequest": EvalRequest,
|
|
162
|
-
"ClampInfo": ClampInfo,
|
|
163
160
|
"Estimate": Estimate,
|
|
164
161
|
"EvalResponse": EvalResponse,
|
|
165
162
|
"EvalDryRunResponse": EvalDryRunResponse,
|
|
@@ -167,6 +164,7 @@ WIRE_MODELS: dict[str, type[BaseModel]] = {
|
|
|
167
164
|
"TaskAgg": TaskAgg,
|
|
168
165
|
"MetricAgg": MetricAgg,
|
|
169
166
|
"EvalReport": EvalReport,
|
|
167
|
+
"AdapterPair": AdapterPair,
|
|
170
168
|
|
|
171
169
|
"SecretRef": SecretRef,
|
|
172
170
|
"SecretCreateRequest": SecretCreateRequest,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"additionalProperties": false,
|
|
3
|
+
"description": "One pair an adapter converts between: its benchmark side and its policy side, each an account's name,\n`template:<name>` or `*`.",
|
|
4
|
+
"properties": {
|
|
5
|
+
"benchmark": {
|
|
6
|
+
"title": "Benchmark",
|
|
7
|
+
"type": "string"
|
|
8
|
+
},
|
|
9
|
+
"policy": {
|
|
10
|
+
"title": "Policy",
|
|
11
|
+
"type": "string"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"required": [
|
|
15
|
+
"benchmark",
|
|
16
|
+
"policy"
|
|
17
|
+
],
|
|
18
|
+
"title": "AdapterPair",
|
|
19
|
+
"type": "object",
|
|
20
|
+
"x-contract-version": "0.5.16"
|
|
21
|
+
}
|