inspect-robots-yam 0.3.0__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.
- inspect_robots_yam-0.3.0/.github/workflows/ci.yml +91 -0
- inspect_robots_yam-0.3.0/.github/workflows/release.yml +23 -0
- inspect_robots_yam-0.3.0/.gitignore +28 -0
- inspect_robots_yam-0.3.0/.pre-commit-config.yaml +52 -0
- inspect_robots_yam-0.3.0/CITATION.cff +9 -0
- inspect_robots_yam-0.3.0/CLAUDE.md +64 -0
- inspect_robots_yam-0.3.0/LICENSE +21 -0
- inspect_robots_yam-0.3.0/PKG-INFO +221 -0
- inspect_robots_yam-0.3.0/README.md +186 -0
- inspect_robots_yam-0.3.0/plans/0001-yam-molmoact2-design.md +328 -0
- inspect_robots_yam-0.3.0/pyproject.toml +110 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/CLAUDE.md +32 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/__init__.py +37 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/config.py +158 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/embodiment.py +246 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/operator.py +66 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/packing.py +74 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/policy.py +120 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/preflight.py +94 -0
- inspect_robots_yam-0.3.0/src/inspect_robots_yam/py.typed +0 -0
- inspect_robots_yam-0.3.0/tests/test_api_snapshot.py +42 -0
- inspect_robots_yam-0.3.0/tests/test_compat.py +99 -0
- inspect_robots_yam-0.3.0/tests/test_config.py +109 -0
- inspect_robots_yam-0.3.0/tests/test_embodiment.py +322 -0
- inspect_robots_yam-0.3.0/tests/test_eval_end_to_end.py +60 -0
- inspect_robots_yam-0.3.0/tests/test_operator.py +54 -0
- inspect_robots_yam-0.3.0/tests/test_packing.py +83 -0
- inspect_robots_yam-0.3.0/tests/test_policy.py +151 -0
- inspect_robots_yam-0.3.0/tests/test_preflight.py +115 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
# Least privilege: every job only reads the repo contents.
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ci-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
# Lint + strict typing, once. mypy targets the 3.10 floor via pyproject; running
|
|
19
|
+
# it on 3.11 avoids NumPy's 3.12-only stub syntax.
|
|
20
|
+
quality:
|
|
21
|
+
name: lint · type
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
timeout-minutes: 10
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v5
|
|
28
|
+
with:
|
|
29
|
+
enable-cache: true
|
|
30
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
31
|
+
- name: Create venv
|
|
32
|
+
run: uv venv --python 3.11
|
|
33
|
+
- name: Install (dev extras; inspect_robots + kitchenbench from git tags)
|
|
34
|
+
run: uv pip install -e ".[dev]"
|
|
35
|
+
- name: Ruff (lint)
|
|
36
|
+
run: uv run ruff check .
|
|
37
|
+
- name: Ruff (format check)
|
|
38
|
+
run: uv run ruff format --check .
|
|
39
|
+
- name: Mypy (strict)
|
|
40
|
+
run: uv run mypy
|
|
41
|
+
|
|
42
|
+
# Blocking test gate across the supported OS x Python matrix (100% coverage).
|
|
43
|
+
test:
|
|
44
|
+
name: test (${{ matrix.os }}, py${{ matrix.python-version }})
|
|
45
|
+
runs-on: ${{ matrix.os }}
|
|
46
|
+
timeout-minutes: 15
|
|
47
|
+
strategy:
|
|
48
|
+
fail-fast: false
|
|
49
|
+
matrix:
|
|
50
|
+
os: [ubuntu-latest, macos-latest]
|
|
51
|
+
python-version: ["3.11", "3.12"]
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
- name: Install uv
|
|
55
|
+
uses: astral-sh/setup-uv@v5
|
|
56
|
+
with:
|
|
57
|
+
enable-cache: true
|
|
58
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
59
|
+
- name: Create venv (py${{ matrix.python-version }})
|
|
60
|
+
run: uv venv --python ${{ matrix.python-version }}
|
|
61
|
+
- name: Install (dev extras)
|
|
62
|
+
run: uv pip install -e ".[dev]"
|
|
63
|
+
- name: Pytest (100% coverage)
|
|
64
|
+
run: uv run pytest --cov --cov-report=term-missing
|
|
65
|
+
|
|
66
|
+
# Dependency hygiene: the package must import with ONLY its runtime deps
|
|
67
|
+
# (inspect_robots + numpy) — no requests, json_numpy, or i2rt (those are lazy extras).
|
|
68
|
+
import-hygiene:
|
|
69
|
+
name: import without client/hardware extras
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
timeout-minutes: 10
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
- name: Install uv
|
|
75
|
+
uses: astral-sh/setup-uv@v5
|
|
76
|
+
with:
|
|
77
|
+
enable-cache: true
|
|
78
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
79
|
+
- name: Create venv
|
|
80
|
+
run: uv venv --python 3.12
|
|
81
|
+
- name: Install runtime only (no extras)
|
|
82
|
+
run: uv pip install -e .
|
|
83
|
+
- name: Assert optional deps absent, then import
|
|
84
|
+
run: |
|
|
85
|
+
uv run python - <<'PY'
|
|
86
|
+
import importlib.util
|
|
87
|
+
for mod in ("requests", "json_numpy", "i2rt"):
|
|
88
|
+
assert importlib.util.find_spec(mod) is None, f"{mod} unexpectedly installed"
|
|
89
|
+
import inspect_robots_yam
|
|
90
|
+
print("inspect_robots_yam", inspect_robots_yam.__version__, "imported with runtime deps only")
|
|
91
|
+
PY
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI via trusted publishing (OIDC) — no API tokens.
|
|
4
|
+
# Authenticates against the PyPI trusted-publisher entry for this repo
|
|
5
|
+
# (workflow: release.yml, environment: pypi).
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [published]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write # OIDC token for PyPI trusted publishing
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v5
|
|
20
|
+
- name: Build sdist + wheel
|
|
21
|
+
run: uv build
|
|
22
|
+
- name: Publish to PyPI
|
|
23
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Virtualenvs
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
|
|
13
|
+
# Test / coverage
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
coverage.xml
|
|
17
|
+
htmlcov/
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
|
|
21
|
+
# Secrets / env
|
|
22
|
+
.env
|
|
23
|
+
.env.*
|
|
24
|
+
|
|
25
|
+
# OS / editor
|
|
26
|
+
.DS_Store
|
|
27
|
+
.idea/
|
|
28
|
+
.vscode/
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Pre-commit hooks for inspect-robots-yam. Install once per clone:
|
|
2
|
+
#
|
|
3
|
+
# uv run pre-commit install # sets up both pre-commit and pre-push hooks
|
|
4
|
+
#
|
|
5
|
+
# On commit: file hygiene + ruff (lint & format) + mypy (strict).
|
|
6
|
+
# On push: pytest with the 100% coverage gate.
|
|
7
|
+
#
|
|
8
|
+
# Local hooks run through `uv run` so they use this project's dev environment
|
|
9
|
+
# (matching CI) regardless of whether a virtualenv is activated. Requires uv.
|
|
10
|
+
default_install_hook_types: [pre-commit, pre-push]
|
|
11
|
+
|
|
12
|
+
repos:
|
|
13
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
14
|
+
rev: v5.0.0
|
|
15
|
+
hooks:
|
|
16
|
+
- id: trailing-whitespace
|
|
17
|
+
- id: end-of-file-fixer
|
|
18
|
+
- id: check-yaml
|
|
19
|
+
- id: check-toml
|
|
20
|
+
- id: check-merge-conflict
|
|
21
|
+
- id: check-added-large-files
|
|
22
|
+
|
|
23
|
+
- repo: local
|
|
24
|
+
hooks:
|
|
25
|
+
- id: ruff-check
|
|
26
|
+
name: ruff (lint, autofix)
|
|
27
|
+
entry: uv run ruff check --fix
|
|
28
|
+
language: system
|
|
29
|
+
types_or: [python, pyi]
|
|
30
|
+
require_serial: true
|
|
31
|
+
|
|
32
|
+
- id: ruff-format
|
|
33
|
+
name: ruff (format)
|
|
34
|
+
entry: uv run ruff format
|
|
35
|
+
language: system
|
|
36
|
+
types_or: [python, pyi]
|
|
37
|
+
require_serial: true
|
|
38
|
+
|
|
39
|
+
- id: mypy
|
|
40
|
+
name: mypy (strict)
|
|
41
|
+
entry: uv run mypy
|
|
42
|
+
language: system
|
|
43
|
+
types: [python]
|
|
44
|
+
pass_filenames: false
|
|
45
|
+
|
|
46
|
+
- id: pytest-coverage
|
|
47
|
+
name: pytest (100% coverage gate)
|
|
48
|
+
entry: uv run pytest --cov --cov-report=term-missing
|
|
49
|
+
language: system
|
|
50
|
+
always_run: true
|
|
51
|
+
pass_filenames: false
|
|
52
|
+
stages: [pre-push]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below."
|
|
3
|
+
title: "Inspect Robots YAM: Adapters for I2RT YAM bimanual arms"
|
|
4
|
+
authors:
|
|
5
|
+
- name: "Robocurve"
|
|
6
|
+
type: software
|
|
7
|
+
license: MIT
|
|
8
|
+
repository-code: "https://github.com/robocurve/inspect-robots-yam"
|
|
9
|
+
version: "0.3.0"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# inspect-robots-yam — agent guide
|
|
2
|
+
|
|
3
|
+
Inspect Robots adapters that let evals (e.g. [KitchenBench](https://github.com/robocurve/kitchenbench))
|
|
4
|
+
run on real **I2RT YAM bimanual arms** driven by **MolmoAct2**. This is a
|
|
5
|
+
**plugin package** in the Inspect Robots ecosystem — the framework lives in
|
|
6
|
+
[inspect-robots](https://github.com/robocurve/inspect-robots); benchmarks are separate repos
|
|
7
|
+
indexed by [WorldEvals](https://github.com/robocurve/worldevals).
|
|
8
|
+
|
|
9
|
+
## The one big idea
|
|
10
|
+
|
|
11
|
+
Inspect Robots evals swap two inputs: a `Policy` (VLA brain) and an `Embodiment` (robot
|
|
12
|
+
body + world). We ship both for one real stack:
|
|
13
|
+
|
|
14
|
+
- **`molmoact2` policy** — a thin HTTP client for MolmoAct2's first-party
|
|
15
|
+
bimanual-YAM `/act` server. The model runs in its own process (GPU + weights);
|
|
16
|
+
we never import torch here.
|
|
17
|
+
- **`yam_arms` embodiment** — the i2rt joint-position driver.
|
|
18
|
+
|
|
19
|
+
Both declare the **same 14-D `joint_pos` contract** (2 arms × [6 joints +
|
|
20
|
+
gripper], cameras `top/left/right`, packed `joint_pos` state). That makes
|
|
21
|
+
`inspect_robots.compat.check_compatibility` pass with zero errors **and** zero warnings
|
|
22
|
+
— the property `tests/test_compat.py` locks down.
|
|
23
|
+
|
|
24
|
+
## Layout
|
|
25
|
+
|
|
26
|
+
- `src/inspect_robots_yam/` — the package (see `src/inspect_robots_yam/CLAUDE.md`).
|
|
27
|
+
- `tests/` — pytest; everything (driver, cameras, `/act`, clock, operator stdin)
|
|
28
|
+
is injected, so the suite needs **no hardware, no server, no stdin**.
|
|
29
|
+
- `plans/0001-yam-molmoact2-design.md` — the design + plan (approved after two
|
|
30
|
+
adversarial subagent critique rounds). Read it before changing the contract.
|
|
31
|
+
|
|
32
|
+
## Working here
|
|
33
|
+
|
|
34
|
+
- Dev loop: `uv venv && uv pip install -e ".[dev]"`, `uv run pre-commit install`,
|
|
35
|
+
then `uv run pytest --cov`.
|
|
36
|
+
- **Local install gotcha:** `uv pip install -e ".[dev]"` resolves inspect-robots +
|
|
37
|
+
kitchenbench from git tags. To work against sibling checkouts instead:
|
|
38
|
+
`uv pip install -e ../inspect-robots && uv pip install --no-deps -e ../kitchenbench`
|
|
39
|
+
(the `--no-deps` avoids an inspect-robots URL conflict with kitchenbench's own
|
|
40
|
+
`tool.uv.sources`).
|
|
41
|
+
- Gates (all blocking in CI): `ruff check .`, `ruff format --check .`,
|
|
42
|
+
`mypy` (strict), `pytest --cov` at **100%**.
|
|
43
|
+
- **mypy + numpy:** numpy 2.5's stubs use 3.12-only syntax that mypy (py3.10
|
|
44
|
+
target) rejects; the dev extra pins `numpy<2.5` and CI runs mypy on 3.11.
|
|
45
|
+
- **No torch.** The model lives in the MolmoAct2 server. Hardware/client deps
|
|
46
|
+
(`requests`, `json_numpy`, `i2rt`) are optional extras, lazily imported behind
|
|
47
|
+
`# pragma: no cover` seams; the `import-hygiene` CI job enforces that
|
|
48
|
+
`import inspect_robots_yam` works with only inspect_robots + numpy.
|
|
49
|
+
|
|
50
|
+
## Safety invariants (do not weaken)
|
|
51
|
+
|
|
52
|
+
- `YAMEmbodiment.step()` **always clamps** to `YamConfig.joint_low/high` before
|
|
53
|
+
commanding, independent of any `Approver`. This is the last line of defense.
|
|
54
|
+
- The declared `control_mode` is `joint_pos` (absolute). Delta checkpoints are
|
|
55
|
+
converted to absolute *inside* `step()` (`joints_are_delta=True`) so the
|
|
56
|
+
declared semantics stay honest. There is no `joint_delta` control mode in
|
|
57
|
+
Inspect Robots, so compat cannot verify abs-vs-delta — that's a hardware check.
|
|
58
|
+
- Success reaches the scorer **only** via `StepResult.termination_reason="success"`
|
|
59
|
+
(stock `rollout` never sets `operator_judgement`).
|
|
60
|
+
|
|
61
|
+
## Out of scope
|
|
62
|
+
|
|
63
|
+
Launching/serving MolmoAct2 (that's the `allenai/molmoact2` repo), single-arm or
|
|
64
|
+
non-YAM I2RT robots, and model fine-tuning.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RoboCurve
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: inspect-robots-yam
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Inspect Robots adapters for I2RT YAM bimanual arms driven by MolmoAct2.
|
|
5
|
+
Project-URL: Homepage, https://github.com/robocurve/inspect-robots-yam
|
|
6
|
+
Project-URL: Framework, https://github.com/robocurve/inspect-robots
|
|
7
|
+
Project-URL: Collection, https://github.com/robocurve/worldevals
|
|
8
|
+
Author: RoboCurve
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: bimanual,inspect-robots,molmoact,robotics,vla,yam
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: inspect-robots>=0.3
|
|
20
|
+
Requires-Dist: numpy>=1.24
|
|
21
|
+
Provides-Extra: client
|
|
22
|
+
Requires-Dist: json-numpy>=2.1; extra == 'client'
|
|
23
|
+
Requires-Dist: requests>=2.31; extra == 'client'
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: kitchenbench; extra == 'dev'
|
|
26
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
27
|
+
Requires-Dist: numpy<2.5; extra == 'dev'
|
|
28
|
+
Requires-Dist: pre-commit>=3.5; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
32
|
+
Provides-Extra: yam
|
|
33
|
+
Requires-Dist: i2rt; extra == 'yam'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
<div align="center">
|
|
37
|
+
|
|
38
|
+
# 🦾 inspect-robots-yam
|
|
39
|
+
|
|
40
|
+
**Run [Inspect Robots](https://github.com/robocurve/inspect-robots) evals on real
|
|
41
|
+
[I2RT YAM](https://i2rt.com/products/yam-6-dof-arm) bimanual arms driven by
|
|
42
|
+
[MolmoAct2](https://github.com/allenai/molmoact2).**
|
|
43
|
+
|
|
44
|
+
[](https://github.com/robocurve/inspect-robots-yam/actions/workflows/ci.yml)
|
|
45
|
+
[](LICENSE)
|
|
46
|
+
[](https://github.com/robocurve/inspect-robots-yam/actions/workflows/ci.yml)
|
|
47
|
+
[](https://github.com/robocurve/inspect-robots)
|
|
48
|
+
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
Inspect Robots has **two** swappable inputs: a `Policy` (the VLA brain) and an
|
|
52
|
+
`Embodiment` (the robot body + world). This package provides both for the
|
|
53
|
+
YAM + MolmoAct2 stack, so any embodiment-agnostic Inspect Robots task — e.g. all of
|
|
54
|
+
[KitchenBench](https://github.com/robocurve/kitchenbench) — runs on real arms:
|
|
55
|
+
|
|
56
|
+
- **`molmoact2` policy** — a thin client for MolmoAct2's first-party bimanual-YAM
|
|
57
|
+
`/act` server (the model owns the GPU + weights in its own process).
|
|
58
|
+
- **`yam_arms` embodiment** — the I2RT joint-position driver, with a hard safety
|
|
59
|
+
clamp, operator-in-the-loop success, and self-paced control.
|
|
60
|
+
|
|
61
|
+
Both declare the **same 14-D joint-position contract** (2 arms × [6 joints +
|
|
62
|
+
gripper], cameras `top/left/right`, packed `joint_pos` state), so Inspect Robots's
|
|
63
|
+
compatibility check passes with **zero errors and zero warnings** — verifiable
|
|
64
|
+
before any motion.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
inspect-robots run --task kitchenbench/pour_pasta --policy molmoact2 --embodiment yam_arms
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> **Note:** the CLI forwards scalar `key=value` knobs only — it cannot inject a
|
|
71
|
+
> `camera_reader`, which hardware runs require. Launch from Python (see *Run on
|
|
72
|
+
> hardware*) or register your own entry-point factory that bundles the cameras;
|
|
73
|
+
> otherwise `yam_arms` fails fast with a `ConfigError` at `reset()`, before any
|
|
74
|
+
> driver connect or motion.
|
|
75
|
+
|
|
76
|
+
## Install (on the robot/GPU machine)
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Inspect Robots isn't on PyPI yet; uv resolves it (and the optional i2rt driver) from git.
|
|
80
|
+
uv pip install "inspect-robots-yam[client,yam] @ git+https://github.com/robocurve/inspect-robots-yam"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- `client` → `requests` + `json-numpy` (the `/act` transport).
|
|
84
|
+
- `yam` → the I2RT `i2rt` driver (GitHub-only).
|
|
85
|
+
|
|
86
|
+
Then download the model weights (needs a Hugging Face token) and start the server,
|
|
87
|
+
from the [MolmoAct2 repo](https://github.com/allenai/molmoact2):
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
huggingface-cli download allenai/MolmoAct2-BimanualYAM
|
|
91
|
+
python examples/yam/host_server_yam.py # serves /act on :8202
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Preflight — *prove compatibility before any motion*
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
inspect-robots-yam-preflight # dims/semantics/cameras/state
|
|
98
|
+
inspect-robots-yam-preflight --task kitchenbench/pour_pasta # + scene realizability
|
|
99
|
+
inspect-robots-yam-preflight --dry-run # affirm no motion
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
A green preflight means action dim (14), control mode (`joint_pos`), cameras, and
|
|
103
|
+
state keys all line up. **It does not prove the joint values are interpreted the
|
|
104
|
+
same way** — see *Safety* below.
|
|
105
|
+
|
|
106
|
+
## Run on hardware
|
|
107
|
+
|
|
108
|
+
You must provide a `camera_reader` (there is no universal camera API) returning
|
|
109
|
+
`{"top_cam", "left_cam", "right_cam": HxWx3 uint8}`. From Python:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from inspect_robots import eval
|
|
113
|
+
from inspect_robots.approver import ClampApprover
|
|
114
|
+
from inspect_robots_yam import MolmoAct2Policy, YAMEmbodiment, YamConfig
|
|
115
|
+
|
|
116
|
+
emb = YAMEmbodiment(YamConfig(left_channel="can0", right_channel="can1"),
|
|
117
|
+
camera_reader=my_camera_reader)
|
|
118
|
+
pol = MolmoAct2Policy(server_url="http://127.0.0.1:8202")
|
|
119
|
+
|
|
120
|
+
(log,) = eval("kitchenbench/pour_pasta", pol, emb,
|
|
121
|
+
approver=ClampApprover(emb.info.action_space)) # defense in depth
|
|
122
|
+
print(log.status, log.results.metrics)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
At each episode end the embodiment asks the operator (y/N); a `yes` records
|
|
126
|
+
`termination_reason="success"`, which KitchenBench's `task_success` scorer reads.
|
|
127
|
+
The operator prompts need an interactive terminal — a dead stdin raises
|
|
128
|
+
`EmbodimentFault` (the framework's always-halt path). For runs with no operator,
|
|
129
|
+
set `YamConfig(unattended=True)` (CLI: `-E unattended=true`): all operator
|
|
130
|
+
prompts are skipped and every episode runs to `max_steps`, scoring as a failure.
|
|
131
|
+
|
|
132
|
+
## Safety
|
|
133
|
+
|
|
134
|
+
- **Hard clamp backstop.** Every command is clipped to `YamConfig.joint_low/high`
|
|
135
|
+
*inside* `step()`, independent of any Inspect Robots `Approver` — unclamped model
|
|
136
|
+
outputs can never reach the motors. **Set the arm slots to your real YAM joint
|
|
137
|
+
limits** (the defaults are conservative placeholders: joints ±π, gripper 0–1) —
|
|
138
|
+
but note the limits are in *policy units* per the table below: gripper slots 6
|
|
139
|
+
and 13 stay normalized 0–1, only slots 0–5 and 7–12 are radians.
|
|
140
|
+
- **Use `ClampApprover`** on hardware for a second layer.
|
|
141
|
+
- **Zero-gravity handoff jump.** The arms connect in zero-gravity mode by default
|
|
142
|
+
(`YamConfig(zero_gravity_mode=True)`, passed through to the i2rt driver), so the
|
|
143
|
+
first stiff PD command — homing or the first action — can jump from wherever the
|
|
144
|
+
arm was idling. Nothing bounds the per-step joint delta yet (tracked as a known
|
|
145
|
+
issue); stand clear at `reset()` and prefer a `home_pose` near the resting pose.
|
|
146
|
+
- **Absolute vs. delta joints — verify first.** MolmoAct2's YAM `actions` are
|
|
147
|
+
treated as **absolute** joint targets by default. If your checkpoint emits
|
|
148
|
+
deltas, set `YamConfig(joints_are_delta=True)` (the embodiment converts to
|
|
149
|
+
absolute internally so the declared `joint_pos` stays honest). Inspect Robots's
|
|
150
|
+
compat check *cannot* tell these apart — confirm with `--dry-run` and a single
|
|
151
|
+
slow jog before running a task.
|
|
152
|
+
- **Gripper polarity/trim.** The i2rt driver already exposes the YAM gripper as
|
|
153
|
+
normalized 0–1 in both directions, so the defaults (`gripper_open=0.0`,
|
|
154
|
+
`gripper_closed=1.0`) are an identity map and correct for standard grippers.
|
|
155
|
+
`YamConfig(gripper_open=..., gripper_closed=...)` is a polarity/trim remap over
|
|
156
|
+
that already-normalized range — its main use is a gripper wired with inverted
|
|
157
|
+
polarity (`gripper_open=1.0, gripper_closed=0.0`). The remap is a bijection:
|
|
158
|
+
commands are de-normalized on the way out and observations are re-normalized on
|
|
159
|
+
the way back, so the model always sees 0–1. **Warning:** values outside [0, 1]
|
|
160
|
+
are forwarded on a path i2rt does *not* clip — avoid them unless you have
|
|
161
|
+
verified your firmware's behavior.
|
|
162
|
+
|
|
163
|
+
## Configuration
|
|
164
|
+
|
|
165
|
+
### Units — every 14-D vector uses the same layout
|
|
166
|
+
|
|
167
|
+
`joint_low`/`joint_high`, `home_pose`, actions, and the observed `joint_pos`
|
|
168
|
+
state all use *policy units*:
|
|
169
|
+
|
|
170
|
+
| Slots | Meaning | Unit |
|
|
171
|
+
|-------|---------|------|
|
|
172
|
+
| 0–5, 7–12 | left / right arm revolute joints | radians |
|
|
173
|
+
| 6, 13 | left / right gripper | normalized 0–1 (0 = open, 1 = closed) |
|
|
174
|
+
|
|
175
|
+
Hardware gripper units (via `gripper_open`/`gripper_closed`) exist only at the
|
|
176
|
+
driver boundary; nothing you configure here is in hardware gripper units.
|
|
177
|
+
|
|
178
|
+
`YamConfig`: `left_channel`, `right_channel`, `gripper_type` (i2rt `GripperType`
|
|
179
|
+
enum *name*, e.g. `LINEAR_4310`; grippers only — `NO_GRIPPER`/`YAM_TEACHING_HANDLE`
|
|
180
|
+
would break the 14-D packing and are rejected), `control_hz`, `cam_height/width`,
|
|
181
|
+
`joint_low/high`, `home_pose`, `gripper_open/closed`, `joints_are_delta`,
|
|
182
|
+
`zero_gravity_mode` (default `True`; see *Safety*), `unattended` (default `False`;
|
|
183
|
+
skip operator prompts).
|
|
184
|
+
`MolmoActConfig`: `server_url`, `endpoint`, `num_steps`, `timeout_s`,
|
|
185
|
+
`camera_order`, `state_key`, `cam_height/width`.
|
|
186
|
+
|
|
187
|
+
Scalar knobs are settable from the CLI:
|
|
188
|
+
`inspect-robots run -P server_url=http://gpu:8202 -E left_channel=can0 ...`.
|
|
189
|
+
|
|
190
|
+
## Development
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
uv venv && uv pip install -e ".[dev]" # inspect_robots + kitchenbench from git tags
|
|
194
|
+
uv run pre-commit install
|
|
195
|
+
uv run pytest --cov # 100% coverage required
|
|
196
|
+
uv run ruff check . && uv run mypy
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The whole suite runs with **no hardware, no server, and no stdin** — the i2rt
|
|
200
|
+
driver, cameras, the `/act` transport, the clock, and operator I/O are all
|
|
201
|
+
injected. The default hardware seams are excluded from coverage (`# pragma: no
|
|
202
|
+
cover`).
|
|
203
|
+
|
|
204
|
+
## Citation
|
|
205
|
+
|
|
206
|
+
If you use Inspect Robots YAM in your research, please cite it:
|
|
207
|
+
|
|
208
|
+
```bibtex
|
|
209
|
+
@software{inspect-robots-yam,
|
|
210
|
+
author = {Robocurve},
|
|
211
|
+
title = {Inspect Robots YAM: Adapters for I2RT YAM bimanual arms},
|
|
212
|
+
year = {2026},
|
|
213
|
+
url = {https://github.com/robocurve/inspect-robots-yam},
|
|
214
|
+
version = {0.3.0},
|
|
215
|
+
license = {MIT}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## License
|
|
220
|
+
|
|
221
|
+
[MIT](LICENSE)
|