NeoteAI commited on
Commit
1537ea1
Β·
verified Β·
1 Parent(s): 1da2f8d

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +39 -59
README.md CHANGED
@@ -12,92 +12,72 @@ tags:
12
  - pi0
13
  ---
14
 
15
- # N<sub>0</sub>-VTLA β€” A Tactile-Native Vision–Language–Action Model
16
 
17
- $N_0$-VTLA is a Vision–Tactile–Language–Action policy built on a Ο€0.5 backbone
18
- (PaliGemma VLM + flow-matching action expert) augmented with a **latent tactile
19
- predictor**: a small module that, from the current observation alone, predicts the
20
- future tactile change and injects it as latent conditioning tokens into the action
21
- expert. Tactile is encoded by a frozen DINOv2 gel encoder; the predictor is trained to
22
- anticipate contact-driven tactile dynamics, so the policy attends to touch when β€” and
23
- only when β€” it matters.
24
 
25
- This repository holds the **pretrained weights** as a single self-contained checkpoint.
26
- The training, inference-server, and post-training **code** lives at
27
- πŸ‘‰ **https://github.com/neoteai/NeoVTLA2.0**
28
 
29
  ## Contents
30
 
31
  ```
32
- .
33
- β”œβ”€β”€ model.safetensors # the full N0-VTLA checkpoint (~8.25 GB): Ο€0.5 VLM +
34
- β”‚ # flow-matching action expert + latent tactile predictor +
35
- β”‚ # frozen DINOv2 tactile encoder β€” all in one state dict
36
- └── metadata.pt # training metadata (step, config fingerprint)
37
  ```
38
 
39
- This checkpoint is the fully-annealed final weights (end of a full multi-platform
40
- visuo-tactile pretraining epoch; training was stable throughout, gradient norm flat).
41
 
42
- ## Usage
43
-
44
- ### 1. Install the code
45
-
46
- ```bash
47
- git clone https://github.com/neoteai/NeoVTLA2.0.git
48
- cd NeoVTLA2.0
49
- pip install -e .
50
- ```
51
-
52
- ### 2. Download this bundle
53
 
54
  ```python
55
  from huggingface_hub import snapshot_download
56
- ckpt = snapshot_download("NeoteAI/n0-vtla-base") # -> dir with model.safetensors
57
- ```
58
-
59
- ### 3. Load
60
-
61
- ```python
62
  import safetensors.torch as st
63
  from openpi.training.config import get_config
64
  from openpi.models_pytorch.vtla_prior_pytorch import Pi0VTLAPrior
65
 
 
66
  cfg = get_config("canonical_e2e_sub72") # the config this ckpt was trained with
67
  model = Pi0VTLAPrior(cfg.model).eval().cuda()
68
  miss, unexp = st.load_model(model, f"{ckpt}/model.safetensors", strict=False, device="cuda")
69
- assert not miss and not unexp # same-arch load -> 0 missing / 0 unexpected
70
  ```
71
 
72
- ## Action representation & de-normalization contract (read before serving)
73
 
74
- The policy outputs **normalized element-wise delta** actions. To recover executable
75
- absolute end-effector actions:
76
 
77
- 1. **De-normalize** with the *per-robot-group* stats in the **element-wise (subtraction)
78
- space** β€” quantile inverse: `x = (x_norm + 1)/2 Β· (q99 βˆ’ q01) + q01`, on the active
79
- dims only (single-arm = first 10, dual-arm = first 20).
80
- 2. **Add back to state** element-wise: `abs = state + delta` on the delta dims; grippers
81
- and padding are absolute already. This is standard `AbsoluteActions` β€” **no
82
- relative-rotation / rotation-matrix math** (the rotation delta here is element-wise).
83
- 3. **Execute the full chunk: `n_execute = 50` (= action horizon).** Executing fewer steps
84
- clips the chunk tail, which drops the grasp-closing motion β†’ gripper appears stuck open.
 
85
 
86
- > The **norm stats are not shipped in this bundle.** Downstream fine-tuning must recompute
87
- > per-group norm on its own task data in the same element-wise-delta space (see
88
- > `scripts/compute_ew_group_norm.py` in the code repo). The checkpoint's embedded
89
- > `assets/canonical_norm_delta` is an **identity placeholder**, not real stats.
90
 
91
- ### 32-dim action/state layout (contiguous EEF)
92
 
93
  ```
94
- left arm [0:10]: xyz [0:3] + rot6d [3:9] + gripper [9]
95
- right arm [10:20]: xyz [10:13] + rot6d [13:19] + gripper [19]
96
  [20:32]: reserved/unused
97
  ```
98
- Rotation is **rot6d** (not quaternion/euler). On-disk `action` is **absolute** EEF; the
99
- delta target is formed by the data transforms at train time (`action[t+k] βˆ’ state[t]`).
100
-
101
- ## Citation
102
 
103
- If you use these weights, please cite NeoteAI / N0-VTLA (see the code repository).
 
 
12
  - pi0
13
  ---
14
 
15
+ # N<sub>0</sub>-VTLA (base)
16
 
17
+ $N_0$-VTLA is a Vision-Tactile-Language-Action policy. It uses a Ο€0.5 backbone
18
+ (PaliGemma VLM plus a flow-matching action expert) and adds a latent tactile predictor.
19
+ From the current observation alone, the predictor anticipates how the tactile signal will
20
+ change over the next chunk and injects that as a few latent tokens into the action expert.
21
+ Tactile frames are encoded by a frozen DINOv2 gel encoder. Because the predictor is trained
22
+ to anticipate contact-driven tactile dynamics, the policy leans on touch when it matters and
23
+ stays quiet in free space.
24
 
25
+ This repository is the pretrained base checkpoint. Training, serving, and post-training code
26
+ is at https://github.com/neoteai/NeoVTLA2.0.
 
27
 
28
  ## Contents
29
 
30
  ```
31
+ model.safetensors # the full checkpoint (~8.25 GB): Ο€0.5 VLM, flow-matching action
32
+ # expert, latent tactile predictor, and frozen DINOv2, in one state dict
33
+ config.json # architecture summary + the config name this ckpt was trained with
34
+ metadata.pt # training metadata (step, config fingerprint)
 
35
  ```
36
 
37
+ These are the final, fully-annealed weights from a full multi-platform visuo-tactile
38
+ pretraining epoch. Training was stable end to end (gradient norm flat throughout).
39
 
40
+ ## Load
 
 
 
 
 
 
 
 
 
 
41
 
42
  ```python
43
  from huggingface_hub import snapshot_download
 
 
 
 
 
 
44
  import safetensors.torch as st
45
  from openpi.training.config import get_config
46
  from openpi.models_pytorch.vtla_prior_pytorch import Pi0VTLAPrior
47
 
48
+ ckpt = snapshot_download("NeoteAI/n0-vtla-base")
49
  cfg = get_config("canonical_e2e_sub72") # the config this ckpt was trained with
50
  model = Pi0VTLAPrior(cfg.model).eval().cuda()
51
  miss, unexp = st.load_model(model, f"{ckpt}/model.safetensors", strict=False, device="cuda")
52
+ assert not miss and not unexp # same arch, so nothing is missing
53
  ```
54
 
55
+ ## Action format and de-normalization
56
 
57
+ The policy outputs normalized element-wise delta actions. To run them on a robot:
 
58
 
59
+ 1. De-normalize with the per-robot-group stats in the same element-wise (subtraction)
60
+ space the model was trained in. Quantile inverse is `x = (x_norm + 1)/2 * (q99 - q01) + q01`,
61
+ applied to the active dims only (10 for single-arm, 20 for dual-arm).
62
+ 2. Add back to the current state element-wise, `abs = state + delta`, on the delta dims.
63
+ Grippers and padding are already absolute. This is the standard `AbsoluteActions` step,
64
+ with no relative-rotation or rotation-matrix math, since the rotation delta is element-wise.
65
+ 3. Execute the full chunk. Set `n_execute = 50` (the action horizon). If you execute fewer
66
+ steps you clip the tail of the chunk, which drops the grasp-closing motion, and the gripper
67
+ looks stuck open.
68
 
69
+ Norm stats are not included in this bundle. For post-training you recompute per-group norm on
70
+ your own task data in the same element-wise-delta space (see `scripts/compute_ew_group_norm.py`
71
+ in the code repo). The `assets/canonical_norm_delta` embedded in the checkpoint is an identity
72
+ placeholder, not real stats.
73
 
74
+ ### 32-dim action/state layout
75
 
76
  ```
77
+ left arm [0:10]: xyz [0:3], rot6d [3:9], gripper [9]
78
+ right arm [10:20]: xyz [10:13], rot6d [13:19], gripper [19]
79
  [20:32]: reserved/unused
80
  ```
 
 
 
 
81
 
82
+ Rotation is rot6d, not quaternion or euler. On disk the `action` field is absolute end-effector
83
+ pose; the training transforms form the delta target as `action[t+k] - state[t]`.