ZibinDong commited on
Commit
ce32ca3
·
verified ·
1 Parent(s): 1bfc3f0

Publish audited ActionCodec2 release files

Browse files
README.md CHANGED
@@ -15,6 +15,10 @@ tags:
15
 
16
  All 34 variants use one shared runtime. Precision labels describe translation quantization; rotation and joint limits are in each profile's configuration.
17
 
 
 
 
 
18
  ## Tokenizer usage
19
 
20
  ```bash
@@ -26,7 +30,7 @@ import numpy as np
26
  from transformers import AutoProcessor
27
 
28
  codec = AutoProcessor.from_pretrained(
29
- "ZibinDong/ActionCodec2", variant="paper-1st",
30
  action_space="single_eef_delta", trust_remote_code=True,
31
  )
32
  actions = np.zeros((1, 16, 7), dtype=np.float32)
@@ -34,7 +38,7 @@ tokens = codec.encode(actions, fps=15)
34
  restored = codec.decode(tokens, fps=15)
35
  ```
36
 
37
- Use `variant="sparse-standard-2bin"` or `"sparse-high-dynamic-21bin"` for Sparse;
38
  Sparse decoding requires `horizon=actions.shape[-2]` in source frames.
39
  Each profile has its own token namespace; the budget is per profile, not the total routed vocabulary.
40
 
@@ -67,40 +71,40 @@ Saved cleaning settings do not enable filtering during encode or decode.
67
 
68
  | Variant | Edition | Order | Translation precision | Budget / profile | Profiles |
69
  | --- | --- | --- | --- | --- | --- |
70
- | `paper-1st` | Paper | 1 | 5mm | 4096 | joint, eef |
71
- | `paper-2nd` | Paper | 2 | 5mm | 4096 | joint, eef |
72
- | `extended-1st-1mm-2k` | Extended | 1 | 1mm | 2048 | eef |
73
- | `extended-1st-1mm-4k` | Extended | 1 | 1mm | 4096 | joint, eef |
74
- | `extended-1st-1mm-8k` | Extended | 1 | 1mm | 8192 | joint, eef |
75
- | `extended-1st-1mm-16k` | Extended | 1 | 1mm | 16384 | joint, eef |
76
- | `extended-1st-5mm-1k` | Extended | 1 | 5mm | 1024 | joint, eef |
77
- | `extended-1st-5mm-2k` | Extended | 1 | 5mm | 2048 | joint, eef |
78
- | `extended-1st-5mm-4k` | Extended | 1 | 5mm | 4096 | joint, eef |
79
- | `extended-1st-5mm-8k` | Extended | 1 | 5mm | 8192 | joint, eef |
80
- | `extended-1st-5mm-16k` | Extended | 1 | 5mm | 16384 | joint, eef |
81
- | `extended-1st-10mm-1k` | Extended | 1 | 10mm | 1024 | joint, eef |
82
- | `extended-1st-10mm-2k` | Extended | 1 | 10mm | 2048 | joint, eef |
83
- | `extended-1st-10mm-4k` | Extended | 1 | 10mm | 4096 | joint, eef |
84
- | `extended-1st-10mm-8k` | Extended | 1 | 10mm | 8192 | joint, eef |
85
- | `extended-1st-10mm-16k` | Extended | 1 | 10mm | 16384 | joint, eef |
86
- | `extended-2nd-1mm-2k` | Extended | 2 | 1mm | 2048 | eef |
87
- | `extended-2nd-1mm-4k` | Extended | 2 | 1mm | 4096 | joint, eef |
88
- | `extended-2nd-1mm-8k` | Extended | 2 | 1mm | 8192 | joint, eef |
89
- | `extended-2nd-1mm-16k` | Extended | 2 | 1mm | 16384 | joint, eef |
90
- | `extended-2nd-5mm-1k` | Extended | 2 | 5mm | 1024 | joint, eef |
91
- | `extended-2nd-5mm-2k` | Extended | 2 | 5mm | 2048 | joint, eef |
92
- | `extended-2nd-5mm-4k` | Extended | 2 | 5mm | 4096 | joint, eef |
93
- | `extended-2nd-5mm-8k` | Extended | 2 | 5mm | 8192 | joint, eef |
94
- | `extended-2nd-5mm-16k` | Extended | 2 | 5mm | 16384 | joint, eef |
95
- | `extended-2nd-10mm-1k` | Extended | 2 | 10mm | 1024 | joint, eef |
96
- | `extended-2nd-10mm-2k` | Extended | 2 | 10mm | 2048 | joint, eef |
97
- | `extended-2nd-10mm-4k` | Extended | 2 | 10mm | 4096 | joint, eef |
98
- | `extended-2nd-10mm-8k` | Extended | 2 | 10mm | 8192 | joint, eef |
99
- | `extended-2nd-10mm-16k` | Extended | 2 | 10mm | 16384 | joint, eef |
100
- | `sparse-standard-2bin` | Sparse | 1 | 5mm | 4096 | eef, joint |
101
- | `sparse-standard-21bin` | Sparse | 1 | 5mm | 4096 | eef, joint |
102
- | `sparse-high-dynamic-2bin` | Sparse | 1 | 5mm | 4096 | eef, joint |
103
- | `sparse-high-dynamic-21bin` | Sparse | 1 | 5mm | 4096 | eef, joint |
104
 
105
  Pin `revision` for reproducibility. `variants.json` records asset hashes; a selected
106
  `save_pretrained()` directory contains its assets and the shared portable runtime.
 
15
 
16
  All 34 variants use one shared runtime. Precision labels describe translation quantization; rotation and joint limits are in each profile's configuration.
17
 
18
+ Names encode edition, order (`o1`/`o2`), translation precision, vocabulary budget,
19
+ gripper levels, and EEF speed per translation axis: `1p2ms` = 1.2 m/s, `2ms` = 2 m/s.
20
+ Previous names remain compatibility aliases in `variants.json`; token IDs are unchanged.
21
+
22
  ## Tokenizer usage
23
 
24
  ```bash
 
30
  from transformers import AutoProcessor
31
 
32
  codec = AutoProcessor.from_pretrained(
33
+ "ZibinDong/ActionCodec2", variant="paper-o1-5mm-4k-2bin-1p2ms",
34
  action_space="single_eef_delta", trust_remote_code=True,
35
  )
36
  actions = np.zeros((1, 16, 7), dtype=np.float32)
 
38
  restored = codec.decode(tokens, fps=15)
39
  ```
40
 
41
+ Use `variant="sparse-o1-5mm-4k-2bin-1p2ms"` or `"sparse-o1-5mm-4k-21bin-2ms"` for Sparse;
42
  Sparse decoding requires `horizon=actions.shape[-2]` in source frames.
43
  Each profile has its own token namespace; the budget is per profile, not the total routed vocabulary.
44
 
 
71
 
72
  | Variant | Edition | Order | Translation precision | Budget / profile | Profiles |
73
  | --- | --- | --- | --- | --- | --- |
74
+ | `paper-o1-5mm-4k-2bin-1p2ms` | Paper | 1 | 5mm | 4096 | joint, eef |
75
+ | `paper-o2-5mm-4k-2bin-1p2ms` | Paper | 2 | 5mm | 4096 | joint, eef |
76
+ | `extended-o1-1mm-2k-2bin-1p2ms` | Extended | 1 | 1mm | 2048 | eef |
77
+ | `extended-o1-1mm-4k-2bin-1p2ms` | Extended | 1 | 1mm | 4096 | joint, eef |
78
+ | `extended-o1-1mm-8k-2bin-1p2ms` | Extended | 1 | 1mm | 8192 | joint, eef |
79
+ | `extended-o1-1mm-16k-2bin-1p2ms` | Extended | 1 | 1mm | 16384 | joint, eef |
80
+ | `extended-o1-5mm-1k-2bin-1p2ms` | Extended | 1 | 5mm | 1024 | joint, eef |
81
+ | `extended-o1-5mm-2k-2bin-1p2ms` | Extended | 1 | 5mm | 2048 | joint, eef |
82
+ | `extended-o1-5mm-4k-2bin-1p2ms` | Extended | 1 | 5mm | 4096 | joint, eef |
83
+ | `extended-o1-5mm-8k-2bin-1p2ms` | Extended | 1 | 5mm | 8192 | joint, eef |
84
+ | `extended-o1-5mm-16k-2bin-1p2ms` | Extended | 1 | 5mm | 16384 | joint, eef |
85
+ | `extended-o1-10mm-1k-2bin-1p2ms` | Extended | 1 | 10mm | 1024 | joint, eef |
86
+ | `extended-o1-10mm-2k-2bin-1p2ms` | Extended | 1 | 10mm | 2048 | joint, eef |
87
+ | `extended-o1-10mm-4k-2bin-1p2ms` | Extended | 1 | 10mm | 4096 | joint, eef |
88
+ | `extended-o1-10mm-8k-2bin-1p2ms` | Extended | 1 | 10mm | 8192 | joint, eef |
89
+ | `extended-o1-10mm-16k-2bin-1p2ms` | Extended | 1 | 10mm | 16384 | joint, eef |
90
+ | `extended-o2-1mm-2k-2bin-1p2ms` | Extended | 2 | 1mm | 2048 | eef |
91
+ | `extended-o2-1mm-4k-2bin-1p2ms` | Extended | 2 | 1mm | 4096 | joint, eef |
92
+ | `extended-o2-1mm-8k-2bin-1p2ms` | Extended | 2 | 1mm | 8192 | joint, eef |
93
+ | `extended-o2-1mm-16k-2bin-1p2ms` | Extended | 2 | 1mm | 16384 | joint, eef |
94
+ | `extended-o2-5mm-1k-2bin-1p2ms` | Extended | 2 | 5mm | 1024 | joint, eef |
95
+ | `extended-o2-5mm-2k-2bin-1p2ms` | Extended | 2 | 5mm | 2048 | joint, eef |
96
+ | `extended-o2-5mm-4k-2bin-1p2ms` | Extended | 2 | 5mm | 4096 | joint, eef |
97
+ | `extended-o2-5mm-8k-2bin-1p2ms` | Extended | 2 | 5mm | 8192 | joint, eef |
98
+ | `extended-o2-5mm-16k-2bin-1p2ms` | Extended | 2 | 5mm | 16384 | joint, eef |
99
+ | `extended-o2-10mm-1k-2bin-1p2ms` | Extended | 2 | 10mm | 1024 | joint, eef |
100
+ | `extended-o2-10mm-2k-2bin-1p2ms` | Extended | 2 | 10mm | 2048 | joint, eef |
101
+ | `extended-o2-10mm-4k-2bin-1p2ms` | Extended | 2 | 10mm | 4096 | joint, eef |
102
+ | `extended-o2-10mm-8k-2bin-1p2ms` | Extended | 2 | 10mm | 8192 | joint, eef |
103
+ | `extended-o2-10mm-16k-2bin-1p2ms` | Extended | 2 | 10mm | 16384 | joint, eef |
104
+ | `sparse-o1-5mm-4k-2bin-1p2ms` | Sparse | 1 | 5mm | 4096 | eef, joint |
105
+ | `sparse-o1-5mm-4k-21bin-1p2ms` | Sparse | 1 | 5mm | 4096 | eef, joint |
106
+ | `sparse-o1-5mm-4k-2bin-2ms` | Sparse | 1 | 5mm | 4096 | eef, joint |
107
+ | `sparse-o1-5mm-4k-21bin-2ms` | Sparse | 1 | 5mm | 4096 | eef, joint |
108
 
109
  Pin `revision` for reproducibility. `variants.json` records asset hashes; a selected
110
  `save_pretrained()` directory contains its assets and the shared portable runtime.
actioncodec2-0.1.0.tar.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6e3dc31a8a8af57e780870af4f83b84116fec02316265101808a549d9339e613
3
+ size 510658
processing_actioncodec2.py CHANGED
@@ -19,6 +19,33 @@ SHARED_PATTERNS = (
19
  )
20
 
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  def asset_inventory(directory: Path) -> dict[str, str]:
23
  """Hash the complete configuration and fitted assets for one variant."""
24
  sparse = (directory / "sparse_router_config.yaml").is_file()
@@ -151,8 +178,7 @@ class ActionCodec2:
151
  not isinstance(catalog.get("variants"), dict)):
152
  raise ValueError("unsupported ActionCodec2 variant catalog")
153
  variants = catalog["variants"]
154
- if variant not in variants:
155
- raise ValueError(f"select variant= from: {', '.join(sorted(variants))}")
156
  record = variants[variant]
157
  if not isinstance(record, dict):
158
  raise ValueError("invalid ActionCodec2 variant record")
@@ -183,7 +209,7 @@ class ActionCodec2:
183
  raise ValueError("unsupported ActionCodec2 saved artifact manifest")
184
  _check_inventory(directory, record)
185
  origin = record["origin"]
186
- if variant is not None and variant != origin.get("name"):
187
  raise ValueError("saved processor contains a different variant; load the catalog to switch")
188
  if variant_fingerprint is not None and variant_fingerprint != origin.get("fingerprint"):
189
  raise ValueError("variant fingerprint differs from the tokenizer bound to this policy")
 
19
  )
20
 
21
 
22
+ VARIANT_ALIASES = {
23
+ **{f"paper-{order}": f"paper-o{index}-5mm-4k-2bin-1p2ms"
24
+ for index, order in enumerate(("1st", "2nd"), 1)},
25
+ **{f"extended-{order}-{precision}-{size}k":
26
+ f"extended-o{index}-{precision}-{size}k-2bin-1p2ms"
27
+ for index, order in enumerate(("1st", "2nd"), 1)
28
+ for precision in ("1mm", "5mm", "10mm") for size in (1, 2, 4, 8, 16)
29
+ if precision != "1mm" or size != 1},
30
+ **{f"sparse-{dynamics}-{mode}": f"sparse-o1-5mm-4k-{mode}-{speed}"
31
+ for dynamics, speed in (("standard", "1p2ms"), ("high-dynamic", "2ms"))
32
+ for mode in ("2bin", "21bin")},
33
+ }
34
+
35
+
36
+ def resolve_variant_name(variant, variants):
37
+ """Resolve either published spelling against an old or new catalog."""
38
+ if variant in variants:
39
+ return variant
40
+ canonical = VARIANT_ALIASES.get(variant, variant)
41
+ if canonical in variants:
42
+ return canonical
43
+ for legacy, name in VARIANT_ALIASES.items():
44
+ if name == canonical and legacy in variants:
45
+ return legacy
46
+ raise ValueError(f"select variant= from: {', '.join(sorted(variants))}")
47
+
48
+
49
  def asset_inventory(directory: Path) -> dict[str, str]:
50
  """Hash the complete configuration and fitted assets for one variant."""
51
  sparse = (directory / "sparse_router_config.yaml").is_file()
 
178
  not isinstance(catalog.get("variants"), dict)):
179
  raise ValueError("unsupported ActionCodec2 variant catalog")
180
  variants = catalog["variants"]
181
+ variant = resolve_variant_name(variant, variants)
 
182
  record = variants[variant]
183
  if not isinstance(record, dict):
184
  raise ValueError("invalid ActionCodec2 variant record")
 
209
  raise ValueError("unsupported ActionCodec2 saved artifact manifest")
210
  _check_inventory(directory, record)
211
  origin = record["origin"]
212
+ if variant is not None and VARIANT_ALIASES.get(variant, variant) != VARIANT_ALIASES.get(origin.get("name"), origin.get("name")):
213
  raise ValueError("saved processor contains a different variant; load the catalog to switch")
214
  if variant_fingerprint is not None and variant_fingerprint != origin.get("fingerprint"):
215
  raise ValueError("variant fingerprint differs from the tokenizer bound to this policy")
runtime/catalog.py CHANGED
@@ -19,6 +19,33 @@ SHARED_PATTERNS = (
19
  )
20
 
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  def asset_inventory(directory: Path) -> dict[str, str]:
23
  """Hash the complete configuration and fitted assets for one variant."""
24
  sparse = (directory / "sparse_router_config.yaml").is_file()
@@ -151,8 +178,7 @@ class ActionCodec2:
151
  not isinstance(catalog.get("variants"), dict)):
152
  raise ValueError("unsupported ActionCodec2 variant catalog")
153
  variants = catalog["variants"]
154
- if variant not in variants:
155
- raise ValueError(f"select variant= from: {', '.join(sorted(variants))}")
156
  record = variants[variant]
157
  if not isinstance(record, dict):
158
  raise ValueError("invalid ActionCodec2 variant record")
@@ -183,7 +209,7 @@ class ActionCodec2:
183
  raise ValueError("unsupported ActionCodec2 saved artifact manifest")
184
  _check_inventory(directory, record)
185
  origin = record["origin"]
186
- if variant is not None and variant != origin.get("name"):
187
  raise ValueError("saved processor contains a different variant; load the catalog to switch")
188
  if variant_fingerprint is not None and variant_fingerprint != origin.get("fingerprint"):
189
  raise ValueError("variant fingerprint differs from the tokenizer bound to this policy")
 
19
  )
20
 
21
 
22
+ VARIANT_ALIASES = {
23
+ **{f"paper-{order}": f"paper-o{index}-5mm-4k-2bin-1p2ms"
24
+ for index, order in enumerate(("1st", "2nd"), 1)},
25
+ **{f"extended-{order}-{precision}-{size}k":
26
+ f"extended-o{index}-{precision}-{size}k-2bin-1p2ms"
27
+ for index, order in enumerate(("1st", "2nd"), 1)
28
+ for precision in ("1mm", "5mm", "10mm") for size in (1, 2, 4, 8, 16)
29
+ if precision != "1mm" or size != 1},
30
+ **{f"sparse-{dynamics}-{mode}": f"sparse-o1-5mm-4k-{mode}-{speed}"
31
+ for dynamics, speed in (("standard", "1p2ms"), ("high-dynamic", "2ms"))
32
+ for mode in ("2bin", "21bin")},
33
+ }
34
+
35
+
36
+ def resolve_variant_name(variant, variants):
37
+ """Resolve either published spelling against an old or new catalog."""
38
+ if variant in variants:
39
+ return variant
40
+ canonical = VARIANT_ALIASES.get(variant, variant)
41
+ if canonical in variants:
42
+ return canonical
43
+ for legacy, name in VARIANT_ALIASES.items():
44
+ if name == canonical and legacy in variants:
45
+ return legacy
46
+ raise ValueError(f"select variant= from: {', '.join(sorted(variants))}")
47
+
48
+
49
  def asset_inventory(directory: Path) -> dict[str, str]:
50
  """Hash the complete configuration and fitted assets for one variant."""
51
  sparse = (directory / "sparse_router_config.yaml").is_file()
 
178
  not isinstance(catalog.get("variants"), dict)):
179
  raise ValueError("unsupported ActionCodec2 variant catalog")
180
  variants = catalog["variants"]
181
+ variant = resolve_variant_name(variant, variants)
 
182
  record = variants[variant]
183
  if not isinstance(record, dict):
184
  raise ValueError("invalid ActionCodec2 variant record")
 
209
  raise ValueError("unsupported ActionCodec2 saved artifact manifest")
210
  _check_inventory(directory, record)
211
  origin = record["origin"]
212
+ if variant is not None and VARIANT_ALIASES.get(variant, variant) != VARIANT_ALIASES.get(origin.get("name"), origin.get("name")):
213
  raise ValueError("saved processor contains a different variant; load the catalog to switch")
214
  if variant_fingerprint is not None and variant_fingerprint != origin.get("fingerprint"):
215
  raise ValueError("variant fingerprint differs from the tokenizer bound to this policy")
runtime/exporting.py CHANGED
@@ -38,7 +38,7 @@ from pybind11.setup_helpers import Pybind11Extension, build_ext
38
  from pathlib import Path
39
  native = 'actioncodec2_kernels'
40
  openmp = ['-fopenmp'] if sys.platform.startswith('linux') else []
41
- setup(name='actioncodec2-kernels', version='0.3.0', packages=['actioncodec2_kernels'],
42
  ext_modules=[Pybind11Extension('actioncodec2_kernels._native',
43
  sources=sorted(str(p) for p in Path(native).glob('*.cpp')),
44
  include_dirs=[native], cxx_std=17,
 
38
  from pathlib import Path
39
  native = 'actioncodec2_kernels'
40
  openmp = ['-fopenmp'] if sys.platform.startswith('linux') else []
41
+ setup(name='actioncodec2-kernels', version='0.1.0', packages=['actioncodec2_kernels'],
42
  ext_modules=[Pybind11Extension('actioncodec2_kernels._native',
43
  sources=sorted(str(p) for p in Path(native).glob('*.cpp')),
44
  include_dirs=[native], cxx_std=17,
runtime/frontend/actioncodec2_sparse/processor.py CHANGED
@@ -600,7 +600,7 @@ def _save_model_card(directory: Path, codec: ActionCodec2Sparse) -> Path:
600
  path.write_text(
601
  "---\nlibrary_name: actioncodec2\nlicense: apache-2.0\ntags:\n- robotics\n- action-tokenizer\n---\n\n"
602
  f"{GENERATED_CARD_MARKER}\n\n# ActionCodec2Sparse\n\n"
603
- "Install actioncodec2 >= 0.3.0 before loading this artifact.\n\n"
604
  "```python\nfrom actioncodec2 import ActionCodec2Sparse\n\n"
605
  "codec = ActionCodec2Sparse.from_pretrained('./my_codec')\n"
606
  + context
 
600
  path.write_text(
601
  "---\nlibrary_name: actioncodec2\nlicense: apache-2.0\ntags:\n- robotics\n- action-tokenizer\n---\n\n"
602
  f"{GENERATED_CARD_MARKER}\n\n# ActionCodec2Sparse\n\n"
603
+ "Install actioncodec2 >= 0.1.0 before loading this artifact.\n\n"
604
  "```python\nfrom actioncodec2 import ActionCodec2Sparse\n\n"
605
  "codec = ActionCodec2Sparse.from_pretrained('./my_codec')\n"
606
  + context
setup.py CHANGED
@@ -4,7 +4,7 @@ from pybind11.setup_helpers import Pybind11Extension, build_ext
4
  from pathlib import Path
5
  native = 'actioncodec2_kernels'
6
  openmp = ['-fopenmp'] if sys.platform.startswith('linux') else []
7
- setup(name='actioncodec2-kernels', version='0.3.0', packages=['actioncodec2_kernels'],
8
  ext_modules=[Pybind11Extension('actioncodec2_kernels._native',
9
  sources=sorted(str(p) for p in Path(native).glob('*.cpp')),
10
  include_dirs=[native], cxx_std=17,
 
4
  from pathlib import Path
5
  native = 'actioncodec2_kernels'
6
  openmp = ['-fopenmp'] if sys.platform.startswith('linux') else []
7
+ setup(name='actioncodec2-kernels', version='0.1.0', packages=['actioncodec2_kernels'],
8
  ext_modules=[Pybind11Extension('actioncodec2_kernels._native',
9
  sources=sorted(str(p) for p in Path(native).glob('*.cpp')),
10
  include_dirs=[native], cxx_std=17,