abstract-client 0.2.0__tar.gz → 0.2.2__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.
- {abstract_client-0.2.0 → abstract_client-0.2.2}/PKG-INFO +50 -22
- {abstract_client-0.2.0 → abstract_client-0.2.2}/README.md +49 -21
- {abstract_client-0.2.0 → abstract_client-0.2.2}/pyproject.toml +1 -1
- abstract_client-0.2.2/src/abstract/__init__.py +43 -0
- {abstract_client-0.2.0 → abstract_client-0.2.2}/src/atoms/__init__.py +1 -1
- {abstract_client-0.2.0 → abstract_client-0.2.2}/src/atoms/client.py +1 -1
- abstract_client-0.2.2/src/atoms/py.typed +0 -0
- {abstract_client-0.2.0 → abstract_client-0.2.2}/.gitignore +0 -0
- {abstract_client-0.2.0 → abstract_client-0.2.2}/LICENSE +0 -0
- {abstract_client-0.2.0 → abstract_client-0.2.2}/NOTICE +0 -0
- {abstract_client-0.2.0/src/atoms → abstract_client-0.2.2/src/abstract}/py.typed +0 -0
- {abstract_client-0.2.0 → abstract_client-0.2.2}/src/atoms/errors.py +0 -0
- {abstract_client-0.2.0 → abstract_client-0.2.2}/src/atoms/harness.py +0 -0
- {abstract_client-0.2.0 → abstract_client-0.2.2}/src/atoms/policy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: abstract-client
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Abstract's robot API from Python: action chunks from served robot models, sync and asyncio.
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -19,6 +19,35 @@ action chunk per `predict()`.
|
|
|
19
19
|
uv add abstract-client
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
### Quickstart (0.2.2)
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
import abstract
|
|
26
|
+
|
|
27
|
+
checkpoint = "nvidia/dreamzero"
|
|
28
|
+
embodiment = "yam"
|
|
29
|
+
client = abstract.client(ABSTRACT_API_KEY, checkpoint, embodiment)
|
|
30
|
+
|
|
31
|
+
client.set_observation(frames, observation)
|
|
32
|
+
action = client.get_action()
|
|
33
|
+
client.reset_episode()
|
|
34
|
+
client.close()
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`ABSTRACT_API_KEY` is your key, `frames` maps each camera to JPEG bytes, and `observation`
|
|
38
|
+
holds `prompt` (the task) and `state` (measured alongside the frames). The YAM camera and
|
|
39
|
+
state fields are shown below. The returned `Chunk` contains targets, never hardware motion;
|
|
40
|
+
reset ends the model's episode without repositioning the robot.
|
|
41
|
+
|
|
42
|
+
`abstract.client()` checks the account's unmetered model catalogue before configuring an
|
|
43
|
+
`AtomsClient`. The checkpoint must be available and its `robot` must match `embodiment`.
|
|
44
|
+
It does not adapt models to other robots. Omit `api_key` to use the environment or saved
|
|
45
|
+
CLI credentials; connection options such as `base_url` and `timeout` pass through to the
|
|
46
|
+
existing client. Context managers and the existing `atoms` interface remain supported.
|
|
47
|
+
|
|
48
|
+
Release order: publish the matching 0.2.2 SDK before deploying the new landing snippet and
|
|
49
|
+
quickstart; older wheels do not provide `import abstract`.
|
|
50
|
+
|
|
22
51
|
This is all a robot with its own stack needs. The `abstract` command and the robot station are
|
|
23
52
|
`abstract-robots`, built on it, and `abstract-atoms` installs both (`apps/atoms`).
|
|
24
53
|
|
|
@@ -27,7 +56,7 @@ import atoms
|
|
|
27
56
|
|
|
28
57
|
client = atoms.Client() # the key: api_key=, else ABSTRACT_API_KEY, else `abstract login`'s file
|
|
29
58
|
|
|
30
|
-
with client.connect("
|
|
59
|
+
with client.connect("nvidia/dreamzero", "fold the towel") as policy:
|
|
31
60
|
frames = {"overhead": top_jpeg, "wrist_l": left_jpeg, "wrist_r": right_jpeg}
|
|
32
61
|
while not done:
|
|
33
62
|
state = {
|
|
@@ -58,10 +87,11 @@ These interfaces require `abstract-client` 0.2.0 or later.
|
|
|
58
87
|
`client.get_models()` is the availability source; an SDK adapter does not mean a checkpoint
|
|
59
88
|
is enabled on the account. These native contracts are separate from the YAM example:
|
|
60
89
|
|
|
61
|
-
| Model
|
|
62
|
-
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
90
|
+
| Model | Observation | Returned commands |
|
|
91
|
+
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
92
|
+
| `verne/v0.5` | The YAM example's poses and cameras, one frame per camera and then four; not trained on the YAM | 18 pose rows per arm at 30 Hz |
|
|
93
|
+
| `xiaomi/xiaomi-robotics-1` | RoboDojo ARX X5 world-frame poses, normalized grippers (0 closed, 1 open), and `left_joint_position` / `right_joint_position` with six measured radians each. Cameras retain `overhead`, `wrist_l`, `wrist_r`. | `chunk.left` / `chunk.right`: 30 end-effector targets at 25 Hz, in the same RoboDojo world frame. |
|
|
94
|
+
| `black-forest-labs/flux-3-action` | DROID Franka `joint_position` (seven radians), `gripper_position` (one closed fraction: 0 open, 1 closed), and cameras `exterior_image_0_left`, `exterior_image_1_left`, `wrist_image_left`. | `chunk.joints`: 32 rows of seven absolute joint targets plus gripper at 15 Hz; `chunk.action_space == "joint_position"`. `left` and `right` are empty. |
|
|
65
95
|
|
|
66
96
|
Use `chunk.row_count` for either command format. `elapsed_rows`, sync/async policies, retries
|
|
67
97
|
and the `AtomsClient` observation window work with both. Policies sharing one observation
|
|
@@ -77,7 +107,7 @@ pull a chunk when it says so.
|
|
|
77
107
|
from concurrent.futures import ThreadPoolExecutor
|
|
78
108
|
|
|
79
109
|
robot = atoms.AtomsClient() # the key, as atoms.Client finds it
|
|
80
|
-
robot.policy({"model": "
|
|
110
|
+
robot.policy({"model": "nvidia/dreamzero"})
|
|
81
111
|
with robot, ThreadPoolExecutor(1) as worker: # the request runs while the robot moves
|
|
82
112
|
chunk, row, pending = None, 0, None
|
|
83
113
|
while not done:
|
|
@@ -102,26 +132,24 @@ with its own episode, frames (DreamZero takes four per camera, MolmoAct2 one), p
|
|
|
102
132
|
One drives the arms; the others answer the same observations, to compare them.
|
|
103
133
|
|
|
104
134
|
```python
|
|
105
|
-
robot.policies(
|
|
106
|
-
{"dz": {"model": "abstract/dreamzero-astra"}, "molmo": {"model": "allenai/molmoact2"}}
|
|
107
|
-
)
|
|
135
|
+
robot.policies({"dz": {"model": "nvidia/dreamzero"}, "molmo": {"model": "allenai/molmoact2"}})
|
|
108
136
|
robot.set_observation(frames, observation) # one tick, every model
|
|
109
137
|
answers = robot.get_actions() # every model at once: {name: Chunk, or the error it raised}
|
|
110
138
|
drive = robot["dz"] # one model: get_action(), refill_due(), last, mode, last_timing
|
|
111
139
|
```
|
|
112
140
|
|
|
113
|
-
| DreamClient
|
|
114
|
-
|
|
115
|
-
| `DreamClient(api_key)`
|
|
116
|
-
| `get_models()`
|
|
117
|
-
| `policy({"checkpoint": ...})`
|
|
118
|
-
| `set_observation(frames, observation, timestamp=)`
|
|
119
|
-
| `get_action()` returns joint chunks
|
|
120
|
-
| `reset_episode()`, `refill_due()`, `close()`
|
|
121
|
-
| `mode`, `execution_horizon`, `action_hz`, `last_timing`, `checkpoint`, `session_id` | the same, `model` for `checkpoint`
|
|
122
|
-
| `obs_window`, `obs_fps`
|
|
123
|
-
| `DreamSlowNetworkWarning`
|
|
124
|
-
| one model per client
|
|
141
|
+
| DreamClient | atoms.AtomsClient |
|
|
142
|
+
| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
143
|
+
| `DreamClient(api_key)` | `AtomsClient(api_key)`, or `AtomsClient(client=...)` |
|
|
144
|
+
| `get_models()` | `get_models()`: served models and your fine-tunes, with their rates |
|
|
145
|
+
| `policy({"checkpoint": ...})` | `policy({"model": ...})`; `execution_horizon`, `action_hz`, `sync_above_ms`, `timeout_ms` as in DreamClient |
|
|
146
|
+
| `set_observation(frames, observation, timestamp=)` | the same: `video.<camera>` frames, `prompt` and `state` (a dict or `state.<name>` keys) |
|
|
147
|
+
| `get_action()` returns joint chunks | `get_action()` returns a `Chunk` in the selected model's action space: poses in `left` / `right`, native joint commands in `joints` |
|
|
148
|
+
| `reset_episode()`, `refill_due()`, `close()` | the same |
|
|
149
|
+
| `mode`, `execution_horizon`, `action_hz`, `last_timing`, `checkpoint`, `session_id` | the same, `model` for `checkpoint` |
|
|
150
|
+
| `obs_window`, `obs_fps` | none: each answer says how many frames the next observation carries |
|
|
151
|
+
| `DreamSlowNetworkWarning` | `atoms.SlowNetworkWarning` |
|
|
152
|
+
| one model per client | `policies({name: config})`, `get_actions()`, `robot[name]` |
|
|
125
153
|
|
|
126
154
|
Not here yet: DreamClient's seam smoothing (`commanded`), datasets and fine-tuning. Embodiments,
|
|
127
155
|
`ik` and Live View have no counterpart on this API.
|
|
@@ -8,6 +8,35 @@ action chunk per `predict()`.
|
|
|
8
8
|
uv add abstract-client
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
### Quickstart (0.2.2)
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import abstract
|
|
15
|
+
|
|
16
|
+
checkpoint = "nvidia/dreamzero"
|
|
17
|
+
embodiment = "yam"
|
|
18
|
+
client = abstract.client(ABSTRACT_API_KEY, checkpoint, embodiment)
|
|
19
|
+
|
|
20
|
+
client.set_observation(frames, observation)
|
|
21
|
+
action = client.get_action()
|
|
22
|
+
client.reset_episode()
|
|
23
|
+
client.close()
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`ABSTRACT_API_KEY` is your key, `frames` maps each camera to JPEG bytes, and `observation`
|
|
27
|
+
holds `prompt` (the task) and `state` (measured alongside the frames). The YAM camera and
|
|
28
|
+
state fields are shown below. The returned `Chunk` contains targets, never hardware motion;
|
|
29
|
+
reset ends the model's episode without repositioning the robot.
|
|
30
|
+
|
|
31
|
+
`abstract.client()` checks the account's unmetered model catalogue before configuring an
|
|
32
|
+
`AtomsClient`. The checkpoint must be available and its `robot` must match `embodiment`.
|
|
33
|
+
It does not adapt models to other robots. Omit `api_key` to use the environment or saved
|
|
34
|
+
CLI credentials; connection options such as `base_url` and `timeout` pass through to the
|
|
35
|
+
existing client. Context managers and the existing `atoms` interface remain supported.
|
|
36
|
+
|
|
37
|
+
Release order: publish the matching 0.2.2 SDK before deploying the new landing snippet and
|
|
38
|
+
quickstart; older wheels do not provide `import abstract`.
|
|
39
|
+
|
|
11
40
|
This is all a robot with its own stack needs. The `abstract` command and the robot station are
|
|
12
41
|
`abstract-robots`, built on it, and `abstract-atoms` installs both (`apps/atoms`).
|
|
13
42
|
|
|
@@ -16,7 +45,7 @@ import atoms
|
|
|
16
45
|
|
|
17
46
|
client = atoms.Client() # the key: api_key=, else ABSTRACT_API_KEY, else `abstract login`'s file
|
|
18
47
|
|
|
19
|
-
with client.connect("
|
|
48
|
+
with client.connect("nvidia/dreamzero", "fold the towel") as policy:
|
|
20
49
|
frames = {"overhead": top_jpeg, "wrist_l": left_jpeg, "wrist_r": right_jpeg}
|
|
21
50
|
while not done:
|
|
22
51
|
state = {
|
|
@@ -47,10 +76,11 @@ These interfaces require `abstract-client` 0.2.0 or later.
|
|
|
47
76
|
`client.get_models()` is the availability source; an SDK adapter does not mean a checkpoint
|
|
48
77
|
is enabled on the account. These native contracts are separate from the YAM example:
|
|
49
78
|
|
|
50
|
-
| Model
|
|
51
|
-
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
79
|
+
| Model | Observation | Returned commands |
|
|
80
|
+
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
81
|
+
| `verne/v0.5` | The YAM example's poses and cameras, one frame per camera and then four; not trained on the YAM | 18 pose rows per arm at 30 Hz |
|
|
82
|
+
| `xiaomi/xiaomi-robotics-1` | RoboDojo ARX X5 world-frame poses, normalized grippers (0 closed, 1 open), and `left_joint_position` / `right_joint_position` with six measured radians each. Cameras retain `overhead`, `wrist_l`, `wrist_r`. | `chunk.left` / `chunk.right`: 30 end-effector targets at 25 Hz, in the same RoboDojo world frame. |
|
|
83
|
+
| `black-forest-labs/flux-3-action` | DROID Franka `joint_position` (seven radians), `gripper_position` (one closed fraction: 0 open, 1 closed), and cameras `exterior_image_0_left`, `exterior_image_1_left`, `wrist_image_left`. | `chunk.joints`: 32 rows of seven absolute joint targets plus gripper at 15 Hz; `chunk.action_space == "joint_position"`. `left` and `right` are empty. |
|
|
54
84
|
|
|
55
85
|
Use `chunk.row_count` for either command format. `elapsed_rows`, sync/async policies, retries
|
|
56
86
|
and the `AtomsClient` observation window work with both. Policies sharing one observation
|
|
@@ -66,7 +96,7 @@ pull a chunk when it says so.
|
|
|
66
96
|
from concurrent.futures import ThreadPoolExecutor
|
|
67
97
|
|
|
68
98
|
robot = atoms.AtomsClient() # the key, as atoms.Client finds it
|
|
69
|
-
robot.policy({"model": "
|
|
99
|
+
robot.policy({"model": "nvidia/dreamzero"})
|
|
70
100
|
with robot, ThreadPoolExecutor(1) as worker: # the request runs while the robot moves
|
|
71
101
|
chunk, row, pending = None, 0, None
|
|
72
102
|
while not done:
|
|
@@ -91,26 +121,24 @@ with its own episode, frames (DreamZero takes four per camera, MolmoAct2 one), p
|
|
|
91
121
|
One drives the arms; the others answer the same observations, to compare them.
|
|
92
122
|
|
|
93
123
|
```python
|
|
94
|
-
robot.policies(
|
|
95
|
-
{"dz": {"model": "abstract/dreamzero-astra"}, "molmo": {"model": "allenai/molmoact2"}}
|
|
96
|
-
)
|
|
124
|
+
robot.policies({"dz": {"model": "nvidia/dreamzero"}, "molmo": {"model": "allenai/molmoact2"}})
|
|
97
125
|
robot.set_observation(frames, observation) # one tick, every model
|
|
98
126
|
answers = robot.get_actions() # every model at once: {name: Chunk, or the error it raised}
|
|
99
127
|
drive = robot["dz"] # one model: get_action(), refill_due(), last, mode, last_timing
|
|
100
128
|
```
|
|
101
129
|
|
|
102
|
-
| DreamClient
|
|
103
|
-
|
|
104
|
-
| `DreamClient(api_key)`
|
|
105
|
-
| `get_models()`
|
|
106
|
-
| `policy({"checkpoint": ...})`
|
|
107
|
-
| `set_observation(frames, observation, timestamp=)`
|
|
108
|
-
| `get_action()` returns joint chunks
|
|
109
|
-
| `reset_episode()`, `refill_due()`, `close()`
|
|
110
|
-
| `mode`, `execution_horizon`, `action_hz`, `last_timing`, `checkpoint`, `session_id` | the same, `model` for `checkpoint`
|
|
111
|
-
| `obs_window`, `obs_fps`
|
|
112
|
-
| `DreamSlowNetworkWarning`
|
|
113
|
-
| one model per client
|
|
130
|
+
| DreamClient | atoms.AtomsClient |
|
|
131
|
+
| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
132
|
+
| `DreamClient(api_key)` | `AtomsClient(api_key)`, or `AtomsClient(client=...)` |
|
|
133
|
+
| `get_models()` | `get_models()`: served models and your fine-tunes, with their rates |
|
|
134
|
+
| `policy({"checkpoint": ...})` | `policy({"model": ...})`; `execution_horizon`, `action_hz`, `sync_above_ms`, `timeout_ms` as in DreamClient |
|
|
135
|
+
| `set_observation(frames, observation, timestamp=)` | the same: `video.<camera>` frames, `prompt` and `state` (a dict or `state.<name>` keys) |
|
|
136
|
+
| `get_action()` returns joint chunks | `get_action()` returns a `Chunk` in the selected model's action space: poses in `left` / `right`, native joint commands in `joints` |
|
|
137
|
+
| `reset_episode()`, `refill_due()`, `close()` | the same |
|
|
138
|
+
| `mode`, `execution_horizon`, `action_hz`, `last_timing`, `checkpoint`, `session_id` | the same, `model` for `checkpoint` |
|
|
139
|
+
| `obs_window`, `obs_fps` | none: each answer says how many frames the next observation carries |
|
|
140
|
+
| `DreamSlowNetworkWarning` | `atoms.SlowNetworkWarning` |
|
|
141
|
+
| one model per client | `policies({name: config})`, `get_actions()`, `robot[name]` |
|
|
114
142
|
|
|
115
143
|
Not here yet: DreamClient's seam smoothing (`commanded`), datasets and fine-tuning. Embodiments,
|
|
116
144
|
`ik` and Live View have no counterpart on this API.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""A configured robot policy: observations in, action chunks out."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from atoms import AbstractError, AtomsClient, Chunk, ConfigError
|
|
8
|
+
|
|
9
|
+
__all__ = ["AbstractError", "Chunk", "ConfigError", "client"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def client(
|
|
13
|
+
api_key: str | None = None,
|
|
14
|
+
checkpoint: str | None = None,
|
|
15
|
+
embodiment: str | None = None,
|
|
16
|
+
**options: Any,
|
|
17
|
+
) -> AtomsClient:
|
|
18
|
+
"""Choose an available checkpoint for this robot, then accept observations.
|
|
19
|
+
|
|
20
|
+
Credentials and connection options are those of atoms.AtomsClient. The unmetered
|
|
21
|
+
catalogue validates the checkpoint/embodiment pair; construction never runs a model.
|
|
22
|
+
Embodiment names match the catalogue's robot field, such as ``yam``. Selecting one
|
|
23
|
+
does not adapt a checkpoint to a different robot or connect physical hardware.
|
|
24
|
+
"""
|
|
25
|
+
if not isinstance(checkpoint, str) or not checkpoint:
|
|
26
|
+
raise ConfigError("Pass checkpoint as an origin/model id.")
|
|
27
|
+
if not isinstance(embodiment, str) or not embodiment:
|
|
28
|
+
raise ConfigError("Pass embodiment as the checkpoint's robot, such as 'yam'.")
|
|
29
|
+
policy = AtomsClient(api_key, **options)
|
|
30
|
+
try:
|
|
31
|
+
model = next((model for model in policy.get_models() if model.id == checkpoint), None)
|
|
32
|
+
if model is None:
|
|
33
|
+
raise ConfigError(f"Checkpoint {checkpoint!r} is not available to this account.")
|
|
34
|
+
if model.robot != embodiment:
|
|
35
|
+
raise ConfigError(
|
|
36
|
+
f"Checkpoint {checkpoint!r} requires embodiment {model.robot!r}, "
|
|
37
|
+
f"not {embodiment!r}."
|
|
38
|
+
)
|
|
39
|
+
policy.policy({"model": model.id})
|
|
40
|
+
except Exception:
|
|
41
|
+
policy.close()
|
|
42
|
+
raise
|
|
43
|
+
return policy
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import atoms
|
|
4
4
|
|
|
5
5
|
client = atoms.Client() # the key: api_key=, else ABSTRACT_API_KEY, else `abstract login`'s
|
|
6
|
-
with client.connect("
|
|
6
|
+
with client.connect("nvidia/dreamzero", "fold the towel") as policy:
|
|
7
7
|
chunk = policy.predict(frames, state)
|
|
8
8
|
|
|
9
9
|
`atoms.AtomsClient` is Dream Labs' DreamClient on this API; `atoms.AsyncClient` is native asyncio.
|
|
@@ -39,7 +39,7 @@ from atoms.errors import (
|
|
|
39
39
|
)
|
|
40
40
|
from atoms.policy import AsyncPolicy, Policy, _trace
|
|
41
41
|
|
|
42
|
-
__version__ = "0.2.
|
|
42
|
+
__version__ = "0.2.2"
|
|
43
43
|
|
|
44
44
|
DEFAULT_BASE_URL = "https://api.abstract.inc/v1"
|
|
45
45
|
API_VERSION = "2026-10-27" # the API this client was built against, pinned in Abstract-Version
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|