AdrianLlopart commited on
Commit
946a7db
·
verified ·
1 Parent(s): f9f41fc

docs: HF model card — best-of-both front-matter derived from manifest

Browse files
Files changed (1) hide show
  1. README.md +198 -162
README.md CHANGED
@@ -1,192 +1,228 @@
1
  ---
2
- library_name: transformers
 
 
 
3
  tags:
4
- - molmoact2
5
- - robotics
6
- - image-text-to-text
7
- - so100
8
- - so101
 
 
 
 
 
 
 
 
 
 
 
 
9
  ---
10
 
11
- <img src="assets/MolmoAct2.svg" alt="MolmoAct Logo" height="50">
12
-
13
- # **MolmoAct2-SO100_101**
14
-
15
- MolmoAct2 is an open vision-language-action model for robot control. It builds on Molmo2-ER and attaches a flow-matching continuous action expert that conditions on the VLM key-value cache through a per-layer connection.
16
-
17
- This checkpoint is fine-tuned on the SO-100/101 mixture with absolute joint-pose control and annotated language instructions. It is intended for both further fine-tuning and SO-100/101 policy inference.
18
-
19
- ## Quick Links
20
-
21
- - 📂 Models: [Models](https://huggingface.co/collections/allenai/molmoact2-models), [Finetuned Models](https://huggingface.co/collections/allenai/molmoact2-finetuned-models)
22
- - 📂 Datasets: [MolmoAct2-BimanualYAM Dataset](https://huggingface.co/collections/allenai/molmoact2-datasets), [MolmoAct2 Datasets](https://huggingface.co/collections/allenai/molmoact2-datasets), [Molmo2-ER Datasets](https://huggingface.co/collections/allenai/molmo2-er-datasets)
23
- - 📄 Paper: [arXiv:2605.02881](https://arxiv.org/abs/2605.02881)
24
- - 💻 Code: [allenai/molmoact2](https://github.com/allenai/molmoact2)
25
- - 🎥 Blog Post: [MolmoAct2](https://allenai.org/blog/molmoact2)
26
-
27
- ## Intended Use
28
-
29
- Use this checkpoint for SO-100/101 inference or for further fine-tuning. Dataset normalization metadata is stored in `norm_stats.json`. pass `norm_tag="so100_so101_molmoact2"` at inference time.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- Continuous action prediction is the intended and recommended inference mode. Discrete action prediction is exposed for parity and debugging, but we use continuous actions by default.
32
 
33
- ## Install
 
 
 
34
 
35
- ```bash
36
- pip install torch transformers pillow numpy huggingface_hub
37
- ```
38
 
39
- ## Sample Input
 
 
 
 
40
 
41
- This sample comes from `Beegbrain/pick_lemon_and_drop_in_bowl`, episode 0, frame 0. Camera order for this checkpoint does not matter. random camera order is acceptable.
42
 
43
- | Realsense Top RGB | Realsense Side RGB |
44
  | --- | --- |
45
- | ![Sample realsense top RGB](assets/sample_realsense_top_rgb.png) | ![Sample realsense side RGB](assets/sample_realsense_side_rgb.png) |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  ```python
48
- from huggingface_hub import hf_hub_download
49
- from PIL import Image
50
- import numpy as np
51
-
52
- repo_id = "allenai/MolmoAct2-SO100_101"
53
-
54
- top_rgb = Image.open(
55
- hf_hub_download(repo_id, "assets/sample_realsense_top_rgb.png")
56
- ).convert("RGB")
57
- side_rgb = Image.open(
58
- hf_hub_download(repo_id, "assets/sample_realsense_side_rgb.png")
59
- ).convert("RGB")
60
-
61
- task = "Move the arm towards the lemon, grasp it, lift it up, and drop it into the red bowl."
62
- robot_state = np.array(
63
- [
64
- -0.52734375,
65
- 189.140625,
66
- 181.40625,
67
- 60.64453125,
68
- -3.603515625,
69
- 1.0971786975860596,
70
- ],
71
- dtype=np.float32,
72
- )
73
- ```
74
-
75
- ## Continuous Actions
76
 
77
- ```python
78
- import numpy as np
79
- import torch
80
- from huggingface_hub import hf_hub_download
81
- from PIL import Image
82
- from transformers import AutoModelForImageTextToText, AutoProcessor
83
-
84
- repo_id = "allenai/MolmoAct2-SO100_101"
85
-
86
- top_rgb = Image.open(
87
- hf_hub_download(repo_id, "assets/sample_realsense_top_rgb.png")
88
- ).convert("RGB")
89
- side_rgb = Image.open(
90
- hf_hub_download(repo_id, "assets/sample_realsense_side_rgb.png")
91
- ).convert("RGB")
92
- task = "Move the arm towards the lemon, grasp it, lift it up, and drop it into the red bowl."
93
- robot_state = np.array(
94
- [
95
- -0.52734375,
96
- 189.140625,
97
- 181.40625,
98
- 60.64453125,
99
- -3.603515625,
100
- 1.0971786975860596,
101
- ],
102
- dtype=np.float32,
103
- )
104
-
105
- processor = AutoProcessor.from_pretrained(repo_id, trust_remote_code=True)
106
- model = AutoModelForImageTextToText.from_pretrained(
107
- repo_id,
108
- trust_remote_code=True,
109
- dtype=torch.float32,
110
- ).to("cuda").eval()
111
-
112
- out = model.predict_action(
113
- processor=processor,
114
- images=[top_rgb, side_rgb],
115
- task=task,
116
- state=robot_state,
117
- norm_tag="so100_so101_molmoact2",
118
- inference_action_mode="continuous",
119
- enable_depth_reasoning=False,
120
- num_steps=10,
121
- normalize_language=True,
122
- enable_cuda_graph=True,
123
- )
124
-
125
- actions = out.actions
126
  ```
127
 
128
- MolmoAct2 was trained with mixed precision. For our reported experiments, we ran inference in `float32`. This path uses the most GPU memory: roughly 26GB with CUDA graph enabled, or around 24GB without CUDA graph.
129
-
130
- If you have a GPU with less memory, you can run inference with `bfloat16` instead:
131
-
132
- ```python
133
- model = AutoModelForImageTextToText.from_pretrained(
134
- repo_id,
135
- trust_remote_code=True,
136
- dtype=torch.bfloat16,
137
- ).to("cuda").eval()
138
-
139
- with torch.inference_mode(), torch.autocast("cuda", dtype=torch.bfloat16):
140
- out = model.predict_action(...)
141
  ```
142
 
143
- Using `bfloat16` is much more memory efficient and can run under 16GB of GPU memory in our tests. It usually does not hurt performance much.
144
 
 
 
 
 
 
 
 
 
145
 
146
- Images may be PIL images or RGB arrays. Camera order does not need to be fixed for this checkpoint. random camera order is acceptable. `state` is the raw robot state, and actions are returned in robot scale.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- `normalize_language=True` is the default. It lowercases the task string and removes trailing sentence punctuation to match training preprocessing. Set it to `False` if you need to preserve the task text exactly.
 
149
 
150
- `enable_cuda_graph=True` is the default. The first few calls can be slow because the model warms up and captures CUDA graphs. run several random warm-up calls before measuring deployment latency. `num_steps` controls the continuous flow solver and defaults to the checkpoint config value, 10.
 
 
 
 
151
 
152
- Depth reasoning is disabled for this checkpoint. Calling `enable_depth_reasoning=True` will raise an error.
 
153
 
154
- ## Discrete Actions
 
 
 
 
 
155
 
156
- Discrete action inference requires a caller-provided action tokenizer. It is not saved in this repository. Discrete mode decodes action tokens directly. the continuous action expert is not used.
157
 
158
- ```python
159
- action_tokenizer = AutoProcessor.from_pretrained(
160
- "allenai/MolmoAct2-FAST-Tokenizer",
161
- trust_remote_code=True,
162
- )
163
-
164
- out = model.predict_action(
165
- processor=processor,
166
- images=[top_rgb, side_rgb],
167
- task=task,
168
- state=robot_state,
169
- norm_tag="so100_so101_molmoact2",
170
- inference_action_mode="discrete",
171
- action_tokenizer=action_tokenizer,
172
- enable_depth_reasoning=False,
173
- )
174
- ```
175
 
176
- ## Model and Hardware Safety
177
 
178
- MolmoAct2 generate robot actions from visual observations and language instructions, but their behavior may vary across embodiments, environments, and hardware configurations. Users should carefully validate model outputs before deployment, especially when operating physical robots or other actuated systems. Where possible, actions should be monitored through interpretable intermediate outputs (adaptive depth map), simulation rollouts, action limits, or other safety checks before execution on hardware. The model’s action space should be bounded by the training data, robot controller limits, and task-specific safety constraints, including limits on speed, workspace, torque, and contact force. Users should follow the hardware manufacturer’s safety guidelines, use appropriate emergency-stop mechanisms, and operate the system only in a safely configured environment with human supervision.
 
 
 
 
179
 
180
- ## Citation
181
 
182
- ```bibtex
183
- @misc{fang2026molmoact2actionreasoningmodels,
184
- title={MolmoAct2: Action Reasoning Models for Real-world Deployment},
185
- author={Haoquan Fang and Jiafei Duan and Donovan Clay and Sam Wang and Shuo Liu and Weikai Huang and Xiang Fan and Wei-Chuan Tsai and Shirui Chen and Yi Ru Wang and Shanli Xing and Jaemin Cho and Jae Sung Park and Ainaz Eftekhar and Peter Sushko and Karen Farley and Angad Wadhwa and Cole Harrison and Winson Han and Ying-Chun Lee and Eli VanderBilt and Rose Hendrix and Suveen Ellawela and Lucas Ngoo and Joyce Chai and Zhongzheng Ren and Ali Farhadi and Dieter Fox and Ranjay Krishna},
186
- year={2026},
187
- eprint={2605.02881},
188
- archivePrefix={arXiv},
189
- primaryClass={cs.RO},
190
- url={https://arxiv.org/abs/2605.02881},
191
- }
192
- ```
 
1
  ---
2
+ language:
3
+ - en
4
+ license: apache-2.0
5
+ pipeline_tag: robotics
6
  tags:
7
+ - OpenRAL
8
+ - rskill
9
+ - molmoact2
10
+ - vision-language-action
11
+ - nf4
12
+ - 4-bit
13
+ - so100_follower
14
+ - so101_follower
15
+ - transformers
16
+ - vla
17
+ - so101
18
+ - so100
19
+ - manipulation
20
+ base_model:
21
+ - allenai/MolmoAct2-SO100_101
22
+ base_model_relation: quantized
23
+ inference: false
24
  ---
25
 
26
+ # rskill-molmoact2-so101-nf4
27
+
28
+ > **OpenRAL rSkill** — MolmoAct2 (Ai2's open action reasoning model: a
29
+ > Molmo2-ER embodied-reasoning VLM backbone with a flow-matching
30
+ > continuous-action expert) finetuned on the
31
+ > [SO-100/SO-101](https://huggingface.co/allenai/MolmoAct2-SO100_101) teleop
32
+ > mixture and NF4-quantized so the ~5.5 B-param model fits an 8 GB GPU.
33
+ > Robots: SO-100 and SO-101 follower arms. **Apache-2.0 weights** — commercial
34
+ > use permitted.
35
+
36
+ This package wraps `hf://OpenRAL/rskill-molmoact2-so101-nf4` (an
37
+ NF4-quantized mirror of `allenai/MolmoAct2-SO100_101`) with a `rskill.yaml`
38
+ manifest that adds capability checking, license surfacing, latency budgets,
39
+ and local registry integration. It does **not** copy model weights — they
40
+ live on the Hub.
41
+
42
+ > **Required sim config knob:** this checkpoint uses normalization statistics
43
+ > tagged `"so100_so101_molmoact2"`. Any `SimEnvironment` config that drives
44
+ > this rSkill must set `vla.extra.norm_tag: "so100_so101_molmoact2"`
45
+ > omitting it silently applies the adapter's default `"libero"` norm stats and
46
+ > produces garbage actions.
47
+
48
+ ## What this skill does
49
+
50
+ Performs tabletop manipulation — picking, placing, grasping, and transporting
51
+ objects — on the SO-100 and SO-101 follower arms. The MolmoAct2 backbone
52
+ reasons about the scene in 3D and the flow-matching action expert emits a
53
+ continuous absolute joint-position action chunk that the adapter replays one
54
+ step at a time.
55
+
56
+ | Field | Value |
57
+ | --- | --- |
58
+ | Actions | pick, place, pick_and_place, grasp |
59
+ | Objects | diverse tabletop objects |
60
+ | Scenes | tabletop |
61
+ | Embodiments | `so100_follower`, `so101_follower` |
62
+
63
+ ## How it works
64
+
65
+ MolmoAct2 grafts a modern DiT-style flow-matching continuous-action expert
66
+ onto the Molmo2-ER discrete-token VLM via per-layer KV-cache conditioning
67
+ (arXiv:2605.02881). It ships as a transformers **custom-code** model
68
+ (`trust_remote_code`, `auto_map` → `MolmoAct2ForConditionalGeneration`), not a
69
+ lerobot policy. The OpenRAL `molmoact2` adapter
70
+ (`python/sim/src/openral_sim/policies/molmoact2.py`) loads it via
71
+ `AutoModelForImageTextToText.from_pretrained` + `AutoProcessor` from the
72
+ manifest's `source_repo`, NF4-quantizes every Linear with ≥4M weight elements
73
+ via bitsandbytes, overlays the prequantized pack from `weights_uri`, then drives
74
+ it through the checkpoint's own `predict_action(...)` continuous-action API. Two
75
+ RGB camera streams plus a 6-D proprio state go in; a `(chunk_size, 6)` absolute
76
+ joint-position chunk comes out, replayed one step at a time and re-inferred
77
+ when the queue empties.
78
+
79
+ The adapter reads `norm_tag` from `vla.extra.norm_tag`; this rSkill requires
80
+ `"so100_so101_molmoact2"` — set it explicitly in every `SimEnvironment` config.
81
+
82
+ ### Observation → action contract
83
+
84
+ | Direction | Key | Shape | Notes |
85
+ | --- | --- | --- | --- |
86
+ | in | `observation.images.camera1` | `(1, 3, H, W) float32 [0,1]` | overhead view (→ model `top`) |
87
+ | in | `observation.images.camera2` | `(1, 3, H, W) float32 [0,1]` | wrist/side view (→ model `side`) |
88
+ | in | `observation.state` | `(1, 6)` float32 | SO-101 6-D joint positions (rad) |
89
+ | out | action chunk | `(10, 6)` float32 | absolute joint-position targets |
90
+
91
+ **Camera aliases (for `so101_box` scene):** `oak_top → top`, `wrist → side`.
92
+ Override per-scene via `vla.extra` if your scene uses different camera names.
93
+
94
+ ## Upstream model / training
95
+
96
+ The wrapped weights come from Ai2's `allenai/MolmoAct2-SO100_101` checkpoint —
97
+ the base `allenai/MolmoAct2` foundation model finetuned on the SO-100/SO-101
98
+ teleop dataset mixture with absolute joint-pose control and annotated language
99
+ instructions. This rSkill repackages an NF4-quantized mirror of those weights;
100
+ it does **not** retrain or copy the full-precision weights.
101
+
102
+ | Field | Value |
103
+ | --- | --- |
104
+ | Source repo | [`allenai/MolmoAct2-SO100_101`](https://huggingface.co/allenai/MolmoAct2-SO100_101) |
105
+ | Base model | [`allenai/MolmoAct2`](https://huggingface.co/allenai/MolmoAct2) |
106
+ | Paper | [arxiv:2605.02881](https://arxiv.org/abs/2605.02881) — *MolmoAct2: Action Reasoning Models for Real-world Deployment* |
107
+ | License | apache-2.0 (code + weights) |
108
+ | Parameters | ~5.5 B |
109
+ | Training data | SO-100/SO-101 teleop mixture (absolute joint-pose, annotated language) |
110
+ | norm_tag | `"so100_so101_molmoact2"` — **required** in `vla.extra.norm_tag` |
111
 
112
+ ## Supported robots
113
 
114
+ | Robot | Embodiment tag | Status | Notes |
115
+ | --- | --- | --- | --- |
116
+ | SO-101 follower | `so101_follower` | ⚡ experimental | Native training embodiment; numbers not yet locally reproduced. |
117
+ | SO-100 follower | `so100_follower` | ⚡ experimental | Shares identical 6-DoF kinematics; covered by training mixture. |
118
 
119
+ ## Sensors required
 
 
120
 
121
+ | Key | Modality | Min resolution | Format |
122
+ | --- | --- | --- | --- |
123
+ | `observation.images.camera1` | RGB | 224 × 224 | `float32` |
124
+ | `observation.images.camera2` | RGB | 224 × 224 | `float32` |
125
+ | `observation.state` | proprioception | (6,) | `float32` |
126
 
127
+ ## Manifest summary
128
 
129
+ | Field | Value |
130
  | --- | --- |
131
+ | `name` | `OpenRAL/rskill-molmoact2-so101-nf4` |
132
+ | `version` | `0.1.0` |
133
+ | `license` | `apache-2.0` |
134
+ | `role` | `s1` |
135
+ | `embodiment_tags` | `["so100_follower", "so101_follower"]` |
136
+ | `runtime` / `quantization.dtype` | `pytorch` / `int4` (NF4) |
137
+ | `weights_uri` | `hf://OpenRAL/rskill-molmoact2-so101-nf4` |
138
+ | `chunk_size` / `n_action_steps` | 10 / 10 (full chunk replay) |
139
+ | `latency_budget.per_chunk_ms` | 1000 ms |
140
+ | `commercial_use_allowed` | `true` (Apache-2.0) |
141
+ | `image_preprocessing.image_max_crops` | `4` (secondary vision lever; processor default is 8 — see Memory note) |
142
+ | **`norm_tag` (vla.extra)** | **`"so100_so101_molmoact2"` — required** |
143
+
144
+ Full schema: [`openral_core.schemas.RSkillManifest`](../../python/core/src/openral_core/schemas.py).
145
+
146
+ ## Quick start
147
 
148
  ```python
149
+ from openral_rskill.loader import rSkill
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
+ pkg = rSkill.from_yaml("rskills/molmoact2-so101-nf4/rskill.yaml")
152
+ print(pkg.manifest.name, pkg.manifest.version)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  ```
154
 
155
+ ```bash
156
+ # CLI:
157
+ uv run openral rskill install OpenRAL/rskill-molmoact2-so101-nf4
158
+ uv run openral rskill check # does this host meet the requirements?
 
 
 
 
 
 
 
 
 
159
  ```
160
 
161
+ ### Sim config snippet
162
 
163
+ ```yaml
164
+ vla:
165
+ id: molmoact2
166
+ weights_uri: rskills/molmoact2-so101-nf4
167
+ extra:
168
+ norm_tag: "so100_so101_molmoact2" # REQUIRED — default "libero" is wrong for this checkpoint
169
+ # image_max_crops: 6 # optional secondary lever; manifest pins 4 (see note)
170
+ ```
171
 
172
+ > **Memory note (measured on an 8 GiB RTX 4070, transformers 5.x).** NF4 makes
173
+ > the model ~6.0 GiB resident (the bf16 vocab embeddings + vision tower
174
+ > dominate; the nf4 Linears are ~3.5 GiB) and it peaks **~7.63 GiB** during a
175
+ > chunk — right at the edge of an 8 GiB card (which exposes only ~7.6 GiB
176
+ > usable). The decisive enabler is the **CUDA expandable-segments allocator**:
177
+ > without it the first forward's ~1.5 GiB embedding `cat` cannot be placed
178
+ > contiguously and OOMs. The molmoact2 adapter turns this on automatically
179
+ > (`PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True`, via
180
+ > `_enable_expandable_segments`) before its first CUDA allocation; export it
181
+ > yourself if other GPU work in the process allocates before the policy loads.
182
+ > `image_max_crops` (pinned to 4 here) is a *secondary* lever — it bounds the
183
+ > vision tile count but does **not** by itself decide the 8 GiB fit on these
184
+ > checkpoints, and transformers 5.x's fast image processor largely ignores it.
185
+ > Leave ~0.4 GiB of headroom: don't run other GPU processes alongside it.
186
+
187
+ ## Reproduction
188
 
189
+ ```bash
190
+ just bootstrap && uv sync --all-packages
191
 
192
+ # Closed-loop rollout against the SO-101 box scene (NF4 weights fit an 8 GB GPU):
193
+ openral sim run --config scenes/sim/so101_tube_insertion.yaml \
194
+ --rskill rskills/molmoact2-so101-nf4 \
195
+ --vla.extra.norm_tag so100_so101_molmoact2
196
+ ```
197
 
198
+ Producing / refreshing the NF4 weights on the Hub (one-shot, needs a CUDA
199
+ host):
200
 
201
+ ```bash
202
+ HF_TOKEN=<write-token> uv run python tools/quantize_rskill.py \
203
+ --source allenai/MolmoAct2-SO100_101 \
204
+ --target OpenRAL/rskill-molmoact2-so101-nf4 \
205
+ --loader transformers --trust-remote-code
206
+ ```
207
 
208
+ ## Evaluation
209
 
210
+ `eval/so101.json::status` is **pending** — no locally-reproduced benchmark
211
+ numbers are available yet. Run the reproduction command in
212
+ `eval/so101.json::source.reproduction_cli` to populate.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
 
214
+ ## License
215
 
216
+ This rSkill package (`rskill.yaml`, `README.md`, `eval/so101.json`) is
217
+ **Apache-2.0**. The wrapped weights at
218
+ `hf://OpenRAL/rskill-molmoact2-so101-nf4` (NF4 mirror of
219
+ `allenai/MolmoAct2-SO100_101`) are also released under **Apache-2.0** by Ai2 —
220
+ commercial use is permitted; review the upstream LICENSE before deployment.
221
 
222
+ ## See also
223
 
224
+ - [`robots/so101_follower/README.md`](../../robots/so101_follower/README.md) — RobotDescription manifest.
225
+ - [`robots/so100_follower/README.md`](../../robots/so100_follower/README.md) — SO-100 variant.
226
+ - [`scenes/sim/so101_tube_insertion.yaml`](../../scenes/sim/so101_tube_insertion.yaml) SO-101 sim scene config.
227
+ - [`rskills/molmoact2-libero-nf4/README.md`](../molmoact2-libero-nf4/README.md) MolmoAct2 LIBERO variant (Franka Panda).
228
+ - [CLAUDE.md §6.4](../../CLAUDE.md) — rSkill packaging contract.