Instructions to use ZibinDong/ActionCodec2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ZibinDong/ActionCodec2 with Transformers:
# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("ZibinDong/ActionCodec2", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download runtime/backends/actioncodec2/sparse/processor.py from ZibinDong/ActionCodec2: direct link, hf CLI and curl.
- Browser
- Download file 9.87 kB
-
https://huggingface.co/ZibinDong/ActionCodec2/resolve/main/runtime/backends/actioncodec2/sparse/processor.py
- Command line
-
hf download hf://ZibinDong/ActionCodec2/runtime/backends/actioncodec2/sparse/processor.py
-
curl -L -o processor.py https://huggingface.co/ZibinDong/ActionCodec2/resolve/main/runtime/backends/actioncodec2/sparse/processor.py
9.87 kB
| """One ActionCodec2Sparse physical profile: unchanged physical stage plus sparse token layer.""" | |
| from __future__ import annotations | |
| import hashlib | |
| import json | |
| from collections.abc import Sequence | |
| from numbers import Integral | |
| from pathlib import Path | |
| import numpy as np | |
| from .._validation import active_dimensions | |
| from ..cache import BoundedCache | |
| from ..configuration import CONFIG_NAME, ActionCodec2Config, ConfigError | |
| from ..hf import save_huggingface_metadata | |
| from ..physical_codec import PhysicalCodec | |
| from ..primitives import PRIMITIVES_NAME, PrimitiveStore | |
| from .grammar import SparseGrammar | |
| from .layout import SparseLayout | |
| from .vocabulary import SparseVocabulary | |
| PROFILE_PROCESSOR_CLASS = "ActionCodec2SparseProcessor" | |
| class ActionCodec2SparseProcessor: | |
| """Fitted sparse profile over canonical first- or second-order profile actions.""" | |
| def __init__( | |
| self, | |
| config: ActionCodec2Config, | |
| primitives: PrimitiveStore, | |
| vocabulary: SparseVocabulary, | |
| ) -> None: | |
| if config.set_bpe.scheme != "sparse_set_bpe": | |
| raise ConfigError("ActionCodec2Sparse profiles require set_bpe.scheme=sparse_set_bpe") | |
| if vocabulary.layout != SparseLayout.from_config(config, primitives): | |
| raise ValueError("sparse layout does not match the physical primitives") | |
| if vocabulary.lookahead != config.set_bpe.lookahead: | |
| raise ValueError("sparse vocabulary lookahead does not match config.yaml") | |
| self.config, self.primitives, self.vocabulary = config, primitives, vocabulary | |
| self.physical = PhysicalCodec(config, primitives) | |
| self.requires_previous_first_order = self.physical.requires_previous_first_order | |
| self.action_dim = config.physical.input_dim | |
| self.bins = primitives.bins | |
| self._grammar_cache = BoundedCache(8) | |
| def vocab_size(self) -> int: | |
| return self.vocabulary.vocab_size | |
| def layout(self) -> SparseLayout: | |
| return self.vocabulary.layout | |
| def from_pretrained(cls, directory: str | Path) -> ActionCodec2SparseProcessor: | |
| """Load ``config.yaml``, ``primitives.npz`` and ``sparse_bpe.json``.""" | |
| root = Path(directory) | |
| config = ActionCodec2Config.from_pretrained(root) | |
| primitives = PrimitiveStore.from_pretrained(root, input_dim=config.physical.input_dim) | |
| return cls(config, primitives, SparseVocabulary.from_pretrained(root)) | |
| def save_pretrained(self, directory: str | Path) -> list[str]: | |
| root = Path(directory) | |
| self.config.save_pretrained(root) | |
| self.primitives.save_pretrained(root) | |
| files = [root / CONFIG_NAME, root / PRIMITIVES_NAME, self.vocabulary.save_pretrained(root)] | |
| files.extend( | |
| save_huggingface_metadata( | |
| root, processor_class=PROFILE_PROCESSOR_CLASS, vocab_size=self.vocab_size | |
| ) | |
| ) | |
| return [str(path) for path in files] | |
| def artifact_fingerprint(self) -> str: | |
| """Content hash over config, primitive axes and the ordered sparse rules.""" | |
| digest = hashlib.sha256() | |
| digest.update( | |
| json.dumps(self.config.to_dict(), sort_keys=True, separators=(",", ":")).encode() | |
| ) | |
| for axis in self.primitives.values: | |
| values = np.ascontiguousarray(axis) | |
| digest.update(str(values.dtype).encode()) | |
| digest.update(np.asarray(values.shape, dtype=np.int64).tobytes()) | |
| digest.update(values.tobytes()) | |
| digest.update( | |
| json.dumps(self.vocabulary.to_dict(), sort_keys=True, separators=(",", ":")).encode() | |
| ) | |
| return digest.hexdigest() | |
| def _active(self, dims: tuple[int, ...]) -> np.ndarray: | |
| flags = np.zeros(self.action_dim, dtype=bool) | |
| flags[list(dims)] = True | |
| return flags | |
| def _dense_previous_first_order( | |
| self, previous_first_order: np.ndarray | None, dims: tuple[int, ...], batch: int | |
| ) -> np.ndarray | None: | |
| active = set(dims) | |
| for component in self.config.physical.components.values(): | |
| present = active.intersection(component.dims) | |
| if ( | |
| component.primitive_order == 2 | |
| and component.space == "so3" | |
| and present | |
| and present != set(component.dims) | |
| ): | |
| raise ValueError( | |
| "second-order SO(3) requires all three active component dimensions" | |
| ) | |
| if previous_first_order is None: | |
| if any( | |
| c.primitive_order == 2 and active.intersection(c.dims) | |
| for c in self.config.physical.components.values() | |
| ): | |
| raise ValueError( | |
| f"second-order tokenization requires previous_first_order with shape {(batch, len(dims))} in canonical input units" | |
| ) | |
| return ( | |
| np.zeros((batch, self.action_dim), dtype=np.float32) | |
| if self.requires_previous_first_order | |
| else None | |
| ) | |
| values = np.asarray(previous_first_order, dtype=np.float32) | |
| if values.shape != (batch, len(dims)) or not np.all(np.isfinite(values)): | |
| raise ValueError(f"previous_first_order must be finite with shape {(batch, len(dims))}") | |
| dense = np.zeros((batch, self.action_dim), dtype=np.float32) | |
| dense[:, dims] = values | |
| return dense | |
| def quantize_batch( | |
| self, actions: np.ndarray, *, active_dims=None, previous_first_order=None | |
| ) -> np.ndarray: | |
| """Compact ``(B,T,D_active)`` actions to dense cells ``(B,T,D)``, ``-1`` inactive.""" | |
| values = np.asarray(actions, dtype=np.float32) | |
| if values.ndim != 3 or len(values) < 1 or values.shape[1] < 1: | |
| raise ValueError("actions must have non-empty shape [B, T, D_active]") | |
| dims = active_dimensions(active_dims, self.action_dim) | |
| if len(dims) != values.shape[2]: | |
| raise ValueError("active_dims must have one entry per action coordinate") | |
| dense = np.zeros((len(values), values.shape[1], self.action_dim), dtype=np.float32) | |
| dense[:, :, dims] = values | |
| previous = self._dense_previous_first_order(previous_first_order, dims, len(values)) | |
| cells = np.asarray( | |
| self.physical.encode_batch(dense, previous_first_order=previous), dtype=np.int64 | |
| ) | |
| cells[:, :, ~self._active(dims)] = -1 | |
| return cells | |
| def encode_batch( | |
| self, | |
| actions: np.ndarray, | |
| *, | |
| active_dims: Sequence[int] | None = None, | |
| previous_first_order: np.ndarray | None = None, | |
| threads: int = 0, | |
| ) -> list[list[int]]: | |
| """Encode independent ``(B,T,D_active)`` chunks into ragged local token rows.""" | |
| cells = self.quantize_batch( | |
| actions, active_dims=active_dims, previous_first_order=previous_first_order | |
| ) | |
| return self.vocabulary.encode_batch(cells, threads=threads) | |
| def cells_from_tokens( | |
| self, rows: Sequence[Sequence[int]], *, horizon: int, active_dims=None | |
| ) -> np.ndarray: | |
| """Losslessly recover dense cells ``(B,horizon,D)`` with ``-1`` for inactive slots.""" | |
| dims = active_dimensions(active_dims, self.action_dim) | |
| return self.vocabulary.decode_batch(rows, horizon, self._active(dims)) | |
| def _filled(self, cells: np.ndarray) -> np.ndarray: | |
| zero = [0 if z is None else z for z in self.layout.zero] | |
| return np.where(cells >= 0, cells, np.asarray(zero, dtype=np.int64)) | |
| def decode_batch( | |
| self, | |
| rows: Sequence[Sequence[int]], | |
| *, | |
| horizon: int, | |
| active_dims=None, | |
| previous_first_order: np.ndarray | None = None, | |
| ) -> np.ndarray: | |
| """Decode rows to ``(B,horizon,D_active)`` reconstructed profile actions.""" | |
| dims = active_dimensions(active_dims, self.action_dim) | |
| cells = self.cells_from_tokens(rows, horizon=horizon, active_dims=dims) | |
| previous = self._dense_previous_first_order(previous_first_order, dims, len(cells)) | |
| decoded = self.physical.decode_batch(self._filled(cells), previous_first_order=previous) | |
| return np.take(decoded, dims, axis=2) | |
| def final_first_order( | |
| self, | |
| rows: Sequence[Sequence[int]], | |
| *, | |
| horizon: int, | |
| previous_first_order: np.ndarray, | |
| active_dims=None, | |
| executed_steps: int | None = None, | |
| ) -> np.ndarray: | |
| """Next compact ``(B,D_active)`` boundary after ``executed_steps`` codec frames.""" | |
| dims = active_dimensions(active_dims, self.action_dim) | |
| cells = self.cells_from_tokens(rows, horizon=horizon, active_dims=dims) | |
| if executed_steps is not None: | |
| if ( | |
| isinstance(executed_steps, bool) | |
| or not isinstance(executed_steps, Integral) | |
| or not 1 <= executed_steps <= cells.shape[1] | |
| ): | |
| raise ValueError("executed_steps must be within the chunk horizon") | |
| cells = cells[:, :executed_steps] | |
| previous = self._dense_previous_first_order(previous_first_order, dims, len(cells)) | |
| result = self.physical.final_first_order(self._filled(cells), previous_first_order=previous) | |
| return np.take(result, dims, axis=1) | |
| def grammar(self, horizon: int, *, active_dims=None) -> SparseGrammar: | |
| """Prefix grammar of one ``horizon``-frame chunk over the active slots.""" | |
| dims = active_dimensions(active_dims, self.action_dim) | |
| key = (int(horizon), dims) | |
| grammar = self._grammar_cache.get(key) | |
| if grammar is None: | |
| grammar = SparseGrammar(self.vocabulary, horizon, self._active(dims)) | |
| self._grammar_cache[key] = grammar | |
| return grammar | |