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/routing.py from ZibinDong/ActionCodec2: direct link, hf CLI and curl.
- Browser
- Download file 41 kB
-
https://huggingface.co/ZibinDong/ActionCodec2/resolve/main/runtime/backends/actioncodec2/routing.py
- Command line
-
hf download hf://ZibinDong/ActionCodec2/runtime/backends/actioncodec2/routing.py
-
curl -L -o routing.py https://huggingface.co/ZibinDong/ActionCodec2/resolve/main/runtime/backends/actioncodec2/routing.py
41 kB
| 'Required-preset routing over the two shared ActionCodec2 processors.' | |
| from __future__ import annotations | |
| from .presets import canonical_preset_name | |
| import re | |
| from collections.abc import Mapping, Sequence | |
| from dataclasses import asdict, dataclass | |
| from pathlib import Path | |
| from types import MappingProxyType | |
| from typing import TYPE_CHECKING | |
| import numpy as np | |
| import yaml | |
| from ._validation import optional_finite_array | |
| from .batch_semantics import externalize_batch | |
| from .cache import BoundedCache, cached_prefix_state | |
| from .configuration import ( | |
| ActionCodec2Config, | |
| ConfigError, | |
| _integer, | |
| _mapping, | |
| _reject_unknown, | |
| _required, | |
| _UniqueKeyLoader, | |
| ) | |
| from .hf import ( | |
| ROUTER_ALLOW_PATTERNS, | |
| ROUTER_CONFIG_NAME, | |
| ROUTER_MODEL_TYPE, | |
| resolve_pretrained_directory, | |
| save_huggingface_metadata, | |
| save_model_card, | |
| ) | |
| from .native_backend import native_kernel | |
| from .presets import ( | |
| ComponentSpec, | |
| PresetConfig, | |
| format_action_spaces, | |
| ) | |
| from .processor import ActionCodec2Processor | |
| from .semantic import resampled_horizon | |
| from .trajectory import ActiveTrajectory | |
| if TYPE_CHECKING: | |
| from ...frontend.actioncodec2 import ActionCodec2 | |
| ROUTER_CONFIG_VERSION = 4 | |
| _NAME = re.compile(r"[a-z][a-z0-9_]*\Z") | |
| _PROFILES = {"eef", "joint"} | |
| _PROFILE_WIDTHS = {"eef": 7, "joint": 8} | |
| _ComponentStates = tuple[tuple[int, ...], ...] | |
| _RoutedState = tuple[int, _ComponentStates] | |
| class ProfileSpec: | |
| """Token namespace metadata for one shared physical processor.""" | |
| name: str | |
| token_offset: int | |
| token_budget: int | |
| artifact_fingerprint: str | |
| def __post_init__(self) -> None: | |
| if _NAME.fullmatch(self.name) is None: | |
| raise ConfigError(f"profile.name must match {_NAME.pattern!r}") | |
| _integer(self.token_offset, "profile.token_offset") | |
| _integer(self.token_budget, "profile.token_budget", positive=True) | |
| if re.fullmatch(r"[0-9a-f]{64}", self.artifact_fingerprint) is None: | |
| raise ConfigError("profile.artifact_fingerprint must be a SHA-256 hex digest") | |
| def from_dict(cls, payload: object, *, path: str) -> ProfileSpec: | |
| values = _mapping(payload, path) | |
| allowed = {"name", "token_offset", "token_budget", "artifact_fingerprint"} | |
| _reject_unknown(values, allowed, path) | |
| return cls( | |
| name=str(_required(values, "name", path)), | |
| token_offset=_integer(_required(values, "token_offset", path), f"{path}.token_offset"), | |
| token_budget=_integer( | |
| _required(values, "token_budget", path), | |
| f"{path}.token_budget", | |
| positive=True, | |
| ), | |
| artifact_fingerprint=str(_required(values, "artifact_fingerprint", path)), | |
| ) | |
| def to_dict(self) -> dict[str, object]: | |
| return asdict(self) | |
| def _second_order_dims(config: ActionCodec2Config) -> frozenset[int]: | |
| return frozenset( | |
| dimension | |
| for component in config.physical.components.values() | |
| if component.primitive_order == 2 | |
| for dimension in component.dims | |
| ) | |
| def _second_order_boundaries( | |
| preset: PresetConfig, second_order_dims: Mapping[str, frozenset[int]] | |
| ) -> dict[str, int]: | |
| return { | |
| component.name: len(component.active_dims) | |
| for component in preset.components | |
| if second_order_dims[component.space].intersection(component.active_dims) | |
| } | |
| class _ProfileRuntime: | |
| spec: ProfileSpec | |
| processor: ActionCodec2Processor | |
| class _Segment: | |
| component: ComponentSpec | |
| profile: _ProfileRuntime | |
| def _schedule(fronts: Sequence[int], finished: Sequence[bool], time_major: bool) -> int | None: | |
| open_ = [i for i, done in enumerate(finished) if not done] | |
| if not open_: | |
| return None | |
| return min(open_, key=lambda i: (fronts[i], i)) if time_major else open_[0] | |
| class RoutedActionCodec2Grammar: | |
| 'Coverage grammar over a shared time grid and namespaced physical components.' | |
| def __init__(self, router: ActionCodec2Router, *, preset: str, horizon: int) -> None: | |
| horizon = _integer(horizon, "horizon", positive=True) | |
| self.segments = router._segments(router.preset(preset)) | |
| self.horizon = horizon | |
| self.token_order = router.preset(preset).token_order | |
| self.vocab_size = router.vocab_size | |
| self._grammars = tuple( | |
| segment.profile.processor.grammar(horizon, active_dims=segment.component.active_dims) | |
| for segment in self.segments | |
| ) | |
| self._native_grammars = tuple( | |
| getattr(grammar, "_native", None) for grammar in self._grammars | |
| ) | |
| self._native_offsets = tuple(segment.profile.spec.token_offset for segment in self.segments) | |
| states = tuple(grammar._initial_state() for grammar in self._grammars) | |
| self._initial_state = (self._next_component(states), states) | |
| self._state_cache = BoundedCache(256) | |
| def _compiled_grammars(self): | |
| if native_kernel("route_advance") is None: | |
| return None | |
| if any(g is None for g in self._native_grammars): | |
| self._native_grammars = tuple(g._compiled() for g in self._grammars) | |
| return self._native_grammars if all(g is not None for g in self._native_grammars) else None | |
| def _next_component(self, states: _ComponentStates) -> int: | |
| fronts = [grammar._covered_steps(state) for grammar, state in zip(self._grammars, states, strict=True)] | |
| index = _schedule(fronts, [front >= self.horizon for front in fronts], | |
| self.token_order == "time_major") | |
| return len(fronts) if index is None else index | |
| def _advance_routed_state( | |
| self, | |
| routed_state: _RoutedState, | |
| token: int, | |
| ) -> _RoutedState | None: | |
| segment_index, states = routed_state | |
| kernel = native_kernel("route_advance") | |
| compiled = self._compiled_grammars() | |
| if kernel is not None and compiled is not None: | |
| return kernel( | |
| compiled, | |
| self._native_offsets, | |
| self.token_order == "time_major", | |
| segment_index, | |
| states, | |
| token, | |
| ) | |
| if segment_index == len(self.segments): | |
| return None | |
| segment = self.segments[segment_index] | |
| local_token = token - segment.profile.spec.token_offset | |
| if not 0 <= local_token < segment.profile.processor.vocab_size: | |
| return None | |
| next_state = self._grammars[segment_index]._advance(states[segment_index], local_token) | |
| if next_state is None: | |
| return None | |
| updated = (*states[:segment_index], next_state, *states[segment_index + 1 :]) | |
| return self._next_component(updated), updated | |
| def _consume(self, tokens: Sequence[int]) -> _RoutedState | None: | |
| checked: list[int] = [] | |
| for raw_token in tokens: | |
| if isinstance(raw_token, bool) or not isinstance(raw_token, (int, np.integer)): | |
| return None | |
| checked.append(int(raw_token)) | |
| return cached_prefix_state( | |
| tuple(checked), self._state_cache, self._initial_state, self._advance_routed_state | |
| ) | |
| def reserve_states(self, rows: int) -> None: | |
| 'Size the prefix cache for ``rows`` streams advanced in lockstep.' | |
| self._state_cache.reserve(4 * _integer(rows, "rows", positive=True)) | |
| def next_token_mask(self, tokens: Sequence[int]) -> np.ndarray: | |
| """Return a global namespace mask for the next preset token.""" | |
| state = self._consume(tokens) | |
| if state is None: | |
| raise ValueError("token prefix is not legal for this routed preset") | |
| segment_index, states = state | |
| output = np.zeros(self.vocab_size, dtype=bool) | |
| if segment_index == len(self.segments): | |
| return output | |
| segment = self.segments[segment_index] | |
| mask = self._grammars[segment_index]._next_token_mask_from_state(states[segment_index]) | |
| start = segment.profile.spec.token_offset | |
| output[start : start + len(mask)] = mask | |
| return output | |
| def is_complete(self, tokens: Sequence[int]) -> bool: | |
| """Whether the prefix completes every segment exactly once.""" | |
| state = self._consume(tokens) | |
| return state is not None and state[0] == len(self.segments) | |
| def covered_steps(self, tokens: Sequence[int]) -> int: | |
| """Return the contiguous frame prefix covered by every component.""" | |
| state = self._consume(tokens) | |
| if state is None: | |
| raise ValueError("token prefix is not legal for this routed preset") | |
| return min( | |
| grammar._covered_steps(local) for grammar, local in zip(self._grammars, state[1], strict=True) | |
| ) | |
| def is_prefix_complete(self, tokens: Sequence[int], *, steps: int) -> bool: | |
| """Whether a legal token prefix fully covers the requested action frames.""" | |
| if type(steps) is not int or not 1 <= steps <= self.horizon: | |
| raise ValueError("steps must be an integer within the grammar horizon") | |
| state = self._consume(tokens) | |
| return state is not None and all( | |
| grammar._covered_steps(local) >= steps | |
| for grammar, local in zip(self._grammars, state[1], strict=True) | |
| ) | |
| def interleave(self, streams: Sequence[Sequence[int]]) -> list[int]: | |
| """Route per-component local token streams without changing their tokens.""" | |
| kernel = native_kernel("route_interleave") | |
| compiled = self._compiled_grammars() | |
| if kernel is not None and compiled is not None: | |
| return kernel(compiled, self._native_offsets, self.token_order == "time_major", streams) | |
| if len(streams) != len(self.segments): | |
| raise ValueError("one token stream is required per component") | |
| state = self._initial_state | |
| cursors = [0] * len(streams) | |
| output = [] | |
| while state[0] < len(streams): | |
| index = state[0] | |
| if cursors[index] == len(streams[index]): | |
| raise ValueError("component token stream ends before complete coverage") | |
| token = ( | |
| int(streams[index][cursors[index]]) + self.segments[index].profile.spec.token_offset | |
| ) | |
| state = self._advance_routed_state(state, token) | |
| if state is None: | |
| raise ValueError("component token stream violates the routed grammar") | |
| cursors[index] += 1 | |
| output.append(token) | |
| if any(cursor != len(stream) for cursor, stream in zip(cursors, streams, strict=True)): | |
| raise ValueError("extra component tokens after complete coverage") | |
| return output | |
| def complete_prefix(self, tokens: Sequence[int], *, steps: int) -> list[int]: | |
| 'Fill only unreturned future cells with zero-motion primitive atoms.' | |
| if type(steps) is not int or not 1 <= steps <= self.horizon: | |
| raise ValueError("steps must be an integer within the grammar horizon") | |
| if self.covered_steps(tokens) < steps: | |
| raise ValueError(f"action prefix does not cover the first {steps} frames") | |
| kernel = native_kernel("route_complete") | |
| compiled = self._compiled_grammars() | |
| if kernel is not None and compiled is not None: | |
| zero_atoms = [ | |
| ( | |
| np.r_[0, np.cumsum(segment.profile.processor.bins[:-1])] | |
| + segment.profile.processor._zero_cells | |
| ).tolist() | |
| for segment in self.segments | |
| ] | |
| return kernel( | |
| compiled, | |
| self._native_offsets, | |
| self.token_order == "time_major", | |
| [int(token) for token in tokens], | |
| steps, | |
| zero_atoms, | |
| ) | |
| output = [int(token) for token in tokens] | |
| state = self._consume(output) | |
| while state[0] < len(self.segments): | |
| index, states = state | |
| segment = self.segments[index] | |
| processor = segment.profile.processor | |
| local = states[index] | |
| dims = segment.component.active_dims | |
| if processor.serializer.scheme == "unified_set_bpe": | |
| atom = self._grammars[index].completion_token( | |
| local, processor._zero_cells, processor.bins | |
| ) | |
| token = segment.profile.spec.token_offset + atom | |
| state = self._advance_routed_state(state, token) | |
| if state is None: | |
| raise RuntimeError("zero-motion suffix atom violates the routed grammar") | |
| output.append(token) | |
| continue | |
| if processor.serializer.scheme == "bpe": | |
| dimension = dims[local[0] % len(dims)] | |
| else: | |
| full = sum(1 << d for d in dims) | |
| uncovered = next(full & ~mask for mask in local if mask != full) | |
| dimension = (uncovered & -uncovered).bit_length() - 1 | |
| atom = sum(processor.serializer.bins[:dimension]) + int( | |
| processor._zero_cells[dimension] | |
| ) | |
| token = segment.profile.spec.token_offset + atom | |
| state = self._advance_routed_state(state, token) | |
| if state is None: | |
| raise RuntimeError("zero-motion suffix atom violates the routed grammar") | |
| output.append(token) | |
| return output | |
| class ActionCodec2Router: | |
| 'Route heterogeneous dataset states into physical token namespaces.' | |
| model_type = ROUTER_MODEL_TYPE | |
| def __init__( | |
| self, | |
| profiles: Sequence[tuple[ProfileSpec, ActionCodec2Processor]], | |
| presets: Sequence[PresetConfig], | |
| ) -> None: | |
| runtimes: dict[str, _ProfileRuntime] = {} | |
| expected_offset = 0 | |
| for spec, processor in profiles: | |
| if spec.name in runtimes: | |
| raise ConfigError(f"duplicate physical profile {spec.name!r}") | |
| if spec.token_offset != expected_offset: | |
| raise ConfigError("profile token namespaces must be contiguous and ordered") | |
| if processor.vocab_size > spec.token_budget: | |
| raise ConfigError( | |
| f"profile {spec.name!r} uses {processor.vocab_size} tokens, " | |
| f"exceeding budget {spec.token_budget}" | |
| ) | |
| if processor.artifact_fingerprint != spec.artifact_fingerprint: | |
| raise ConfigError( | |
| f"profile {spec.name!r} artifact fingerprint does not match its processor" | |
| ) | |
| if processor.config.set_bpe.allow_cross_component_merge: | |
| raise ConfigError( | |
| "allow_cross_component_merge=true is not supported by the v1 router; " | |
| "a component-aware Set-BPE serializer and grammar are required" | |
| ) | |
| runtimes[spec.name] = _ProfileRuntime(spec, processor) | |
| expected_offset += spec.token_budget | |
| if not runtimes or set(runtimes) - _PROFILES: | |
| raise ConfigError("router profiles must be a non-empty subset of joint and eef") | |
| for name, runtime in runtimes.items(): | |
| if runtime.processor.action_dim != _PROFILE_WIDTHS[name]: | |
| raise ConfigError( | |
| f"profile {name!r} must have width {_PROFILE_WIDTHS[name]}, " | |
| f"got {runtime.processor.action_dim}" | |
| ) | |
| self.profiles = MappingProxyType(runtimes) | |
| self._second_order_dims = { | |
| name: _second_order_dims(runtime.processor.config) for name, runtime in runtimes.items() | |
| } | |
| self._grammar_cache = BoundedCache(8) | |
| self._action_spaces: dict[str, PresetConfig] = {} | |
| for preset in presets: | |
| self.register_action_space(preset) | |
| self.vocab_size = expected_offset | |
| self._token_cells = np.full(self.vocab_size, -1, dtype=np.int64) | |
| for runtime in runtimes.values(): | |
| start = runtime.spec.token_offset | |
| self._token_cells[start : start + runtime.processor.vocab_size] = ( | |
| runtime.processor.serializer.token_cell_counts | |
| ) | |
| def action_spaces(self) -> Mapping[str, PresetConfig]: | |
| """Read-only registered built-in and user-created action spaces.""" | |
| return MappingProxyType(self._action_spaces) | |
| def __str__(self) -> str: | |
| return self.describe_action_spaces() | |
| def second_order_boundaries(self, preset: str | PresetConfig) -> dict[str, int]: | |
| 'Map each component needing ``previous_first_order`` to its active width.' | |
| if not isinstance(preset, PresetConfig): | |
| preset = self.preset(preset) | |
| return _second_order_boundaries(preset, self._second_order_dims) | |
| def describe_action_spaces( | |
| self, *, selected: str | None = None, action_dim: int | None = None | |
| ) -> str: | |
| """Explain all layouts, or source-width candidates, using this artifact's state requirements.""" | |
| return format_action_spaces( | |
| self.action_spaces, | |
| selected=selected, | |
| action_dim=action_dim, | |
| second_order_boundaries={ | |
| name: self.second_order_boundaries(preset) | |
| for name, preset in self.action_spaces.items() | |
| }, | |
| ) | |
| def from_processors( | |
| cls, | |
| processors: Mapping[str, ActionCodec2Processor], | |
| *, | |
| token_budgets: Mapping[str, int], | |
| presets: Sequence[PresetConfig], | |
| ) -> ActionCodec2Router: | |
| """Assign stable contiguous namespaces in canonical joint/eef order.""" | |
| if set(processors) != set(token_budgets): | |
| raise ConfigError("processors and token_budgets must share keys") | |
| if not processors or set(processors) - _PROFILES: | |
| raise ConfigError("processors must contain a non-empty subset of joint and eef") | |
| offset = 0 | |
| entries = [] | |
| for name in ("joint", "eef"): | |
| if name not in processors: | |
| continue | |
| processor = processors[name] | |
| budget = _integer(token_budgets[name], f"token_budgets.{name}", positive=True) | |
| spec = ProfileSpec( | |
| name, | |
| offset, | |
| budget, | |
| processor.artifact_fingerprint, | |
| ) | |
| entries.append((spec, processor)) | |
| offset += budget | |
| return cls(entries, presets) | |
| def preset(self, name: str) -> PresetConfig: | |
| """Resolve one preset or fail with the available names.""" | |
| try: | |
| return self._action_spaces[canonical_preset_name(name)] | |
| except KeyError as error: | |
| raise KeyError( | |
| f"unknown preset {name!r}; available: {sorted(self._action_spaces)}" | |
| ) from error | |
| def register_action_space( | |
| self, | |
| preset: PresetConfig | Mapping[str, object] | str | Path, | |
| ) -> PresetConfig: | |
| 'Register a validated action-space config, mapping, or YAML file.' | |
| if isinstance(preset, Mapping): | |
| preset = PresetConfig.from_dict(preset) | |
| elif isinstance(preset, (str, Path)): | |
| preset = PresetConfig.from_yaml(preset) | |
| if not isinstance(preset, PresetConfig): | |
| raise TypeError( | |
| "register_action_space expects PresetConfig, a mapping, or a preset YAML path" | |
| ) | |
| missing = {component.space for component in preset.components} - self.profiles.keys() | |
| if missing: | |
| raise ConfigError( | |
| f"action space {preset.name!r} requires missing profiles: {sorted(missing)}" | |
| ) | |
| existing = self._action_spaces.get(preset.name) | |
| if existing is not None and existing != preset: | |
| raise ConfigError( | |
| f"action-space name {preset.name!r} is already registered differently" | |
| ) | |
| self._action_spaces[preset.name] = preset | |
| return preset | |
| def _segments(self, preset: PresetConfig) -> tuple[_Segment, ...]: | |
| return tuple( | |
| _Segment(component, self.profiles[component.space]) for component in preset.components | |
| ) | |
| def configure_encoding( | |
| self, | |
| *, | |
| spatial_search: bool = False, | |
| temporal_search: bool = False, | |
| search_window: int = 32, | |
| search_beam: int = 4, | |
| ) -> ActionCodec2Router: | |
| """Apply runtime packing options to all profiles without changing artifacts.""" | |
| from .packing import EncodingSearch | |
| options = EncodingSearch(spatial_search, temporal_search, search_window, search_beam) | |
| for profile in self.profiles.values(): | |
| serializer = profile.processor.serializer | |
| options.validate_codec(serializer.scheme, serializer.bins) | |
| for profile in self.profiles.values(): | |
| profile.processor.configure_encoding( | |
| spatial_search=spatial_search, | |
| temporal_search=temporal_search, | |
| search_window=search_window, | |
| search_beam=search_beam, | |
| ) | |
| return self | |
| def encode_batch( | |
| self, | |
| inputs: np.ndarray, | |
| *, | |
| preset: str, | |
| fps: float | None = None, | |
| current_state: np.ndarray | None = None, | |
| previous_first_order: Mapping[str, np.ndarray] | None = None, | |
| ) -> list[list[int]]: | |
| 'Encode one regular-rate ``[B,T,D]`` tensor at ``fps``.' | |
| preset_config = self.preset(preset) | |
| self._validate_boundary_keys(previous_first_order, preset_config) | |
| canonical = preset_config._canonicalize_batch( | |
| inputs, source_hz=fps, current_state=current_state | |
| ) | |
| batch = len(next(iter(canonical.values()))) | |
| component_streams = [] | |
| for segment in self._segments(preset_config): | |
| values = canonical[segment.component.name] | |
| streams = segment.profile.processor.encode_batch( | |
| values, | |
| active_dims=segment.component.active_dims, | |
| previous_first_order=None | |
| if previous_first_order is None | |
| else previous_first_order.get(segment.component.name), | |
| ) | |
| component_streams.append(streams) | |
| steps = next(iter(canonical.values())).shape[1] | |
| grammar = self.grammar(preset=preset, horizon=steps) | |
| kernel = native_kernel("route_interleave_batch") | |
| compiled = grammar._compiled_grammars() | |
| if kernel is not None and compiled is not None: | |
| return kernel( | |
| compiled, | |
| grammar._native_offsets, | |
| grammar.token_order == "time_major", | |
| component_streams, | |
| ) | |
| return [ | |
| grammar.interleave([streams[row] for streams in component_streams]) | |
| for row in range(batch) | |
| ] | |
| def route_trajectories( | |
| self, | |
| inputs: np.ndarray, | |
| *, | |
| preset: str, | |
| current_state: np.ndarray | None = None, | |
| fps: float | None = None, | |
| previous_first_order: Mapping[str, np.ndarray] | None = None, | |
| ) -> dict[str, list[ActiveTrajectory]]: | |
| 'Expose canonical complete trajectories grouped by physical profile.' | |
| preset_config = self.preset(preset) | |
| self._validate_boundary_keys(previous_first_order, preset_config) | |
| canonical = preset_config.canonicalize(inputs, current_state=current_state, source_hz=fps) | |
| output: dict[str, list[ActiveTrajectory]] = {} | |
| for component in preset_config.components: | |
| trajectories = canonical[component.name] | |
| processor = self.profiles[component.space].processor | |
| previous = ( | |
| None if previous_first_order is None else previous_first_order.get(component.name) | |
| ) | |
| dense = processor._dense_previous_first_order( | |
| previous, component.active_dims, len(trajectories) | |
| ) | |
| rows = ( | |
| [None] * len(trajectories) | |
| if dense is None | |
| else np.take(dense, component.active_dims, axis=1) | |
| ) | |
| output.setdefault(component.space, []).extend( | |
| ActiveTrajectory(t.values, t.active_dims, previous_first_order=p) | |
| for t, p in zip(trajectories, rows, strict=True) | |
| ) | |
| return output | |
| def _validate_boundary_keys( | |
| self, previous_first_order: Mapping[str, np.ndarray] | None, preset: PresetConfig | |
| ) -> None: | |
| if previous_first_order is None: | |
| previous_first_order = {} | |
| if not isinstance(previous_first_order, Mapping): | |
| raise ValueError( | |
| "previous_first_order must map component names to canonical [B,D_active] boundaries" | |
| ) | |
| unknown = set(previous_first_order) - {c.name for c in preset.components} | |
| if unknown: | |
| raise ValueError(f"unknown previous_first_order component(s): {sorted(unknown)}") | |
| required = { | |
| name: f"(B, {width})" for name, width in self.second_order_boundaries(preset).items() | |
| } | |
| missing = set(required) - previous_first_order.keys() | |
| if missing: | |
| raise ValueError( | |
| "second-order tokenization requires previous_first_order with arrays " | |
| f"{required}; missing {sorted(missing)}. Use canonical {preset.target_hz:g} Hz " | |
| "reconstructed increments. codec.first_order_template(batch_size) explicitly " | |
| "creates zeros; use zeros only if the preceding increment is known to be zero." | |
| ) | |
| def final_first_order( | |
| self, | |
| streams: Sequence[Sequence[int]], | |
| *, | |
| preset: str, | |
| previous_first_order: Mapping[str, np.ndarray], | |
| executed_steps: int | None = None, | |
| ) -> dict[str, np.ndarray]: | |
| 'Return component ``[B,D_active]`` boundaries at the canonical clock.' | |
| preset_config = self.preset(preset) | |
| if previous_first_order is None: | |
| raise ValueError("final_first_order requires previous_first_order") | |
| self._validate_boundary_keys(previous_first_order, preset_config) | |
| segments = self._segments(preset_config) | |
| _, component_streams = self._decode_streams(streams, preset_config, segments) | |
| output = {} | |
| for index, segment in enumerate(segments): | |
| processor = segment.profile.processor | |
| if not processor.requires_previous_first_order: | |
| continue | |
| output[segment.component.name] = processor.final_first_order( | |
| component_streams[index], | |
| previous_first_order=previous_first_order.get(segment.component.name), | |
| active_dims=segment.component.active_dims, | |
| executed_steps=executed_steps, | |
| ) | |
| return output | |
| def _split_stream( | |
| self, tokens: Sequence[int], *, preset: PresetConfig, steps: int | |
| ) -> list[list[int]]: | |
| grammar = self.grammar(preset=preset.name, horizon=steps) | |
| kernel = native_kernel("route_split") | |
| compiled = grammar._compiled_grammars() | |
| if kernel is not None and compiled is not None: | |
| checked = [] | |
| for cursor, token in enumerate(tokens): | |
| if isinstance(token, bool) or not isinstance(token, (int, np.integer)): | |
| raise ValueError(f"tokens[{cursor}] must be an integer") | |
| checked.append(int(token)) | |
| return kernel( | |
| compiled, grammar._native_offsets, grammar.token_order == "time_major", checked | |
| ) | |
| state = grammar._initial_state | |
| output = [[] for _ in grammar.segments] | |
| for cursor, raw_token in enumerate(tokens): | |
| if isinstance(raw_token, bool) or not isinstance(raw_token, (int, np.integer)): | |
| raise ValueError(f"tokens[{cursor}] must be an integer") | |
| index = state[0] | |
| if index == len(grammar.segments): | |
| raise ValueError("Action token stream has extra tokens after complete coverage") | |
| segment = grammar.segments[index] | |
| state = grammar._advance_routed_state(state, int(raw_token)) | |
| if state is None: | |
| raise ValueError( | |
| f"Action token stream has invalid coverage for component {segment.component.name!r}; check the preset token_order and constrain generation with codec.grammar(H, fps=...)." | |
| ) | |
| output[index].append(int(raw_token) - segment.profile.spec.token_offset) | |
| if state[0] != len(grammar.segments): | |
| raise ValueError("Incomplete action token stream; discard or regenerate this row") | |
| return output | |
| def _token_cell_count(self, raw_token: object, *, index: int) -> int: | |
| if isinstance(raw_token, bool) or not isinstance(raw_token, (int, np.integer)): | |
| raise ValueError(f"tokens[{index}] must be an integer") | |
| token = int(raw_token) | |
| if 0 <= token < self.vocab_size and self._token_cells[token] >= 0: | |
| return int(self._token_cells[token]) | |
| raise ValueError(f"tokens[{index}] is outside the routed profile vocabularies") | |
| def _decoded_steps(self, tokens: Sequence[int], segments: Sequence[_Segment]) -> int: | |
| if not tokens: | |
| raise ValueError("token stream must not be empty") | |
| cells_per_step = sum(len(segment.component.active_dims) for segment in segments) | |
| represented_cells = sum( | |
| self._token_cell_count(token, index=index) for index, token in enumerate(tokens) | |
| ) | |
| steps, remainder = divmod(represented_cells, cells_per_step) | |
| if steps < 1 or remainder: | |
| raise ValueError( | |
| "Incomplete action token stream: " | |
| f"{cells_per_step - remainder} more coordinate values are needed to finish a step. " | |
| "Constrain generation with codec.grammar(H, fps=...).next_token_mask(prefix) " | |
| "and check is_complete(tokens) for the intended H before decoding. " | |
| "Use codec.batch_decode(..., errors='return') to isolate invalid rows; " | |
| "do not pad truncated tokens with zeros." | |
| ) | |
| return steps | |
| def _batch_steps( | |
| self, | |
| streams: Sequence[Sequence[int]], | |
| segments: Sequence[_Segment], | |
| ) -> int: | |
| if not streams: | |
| raise ValueError("streams must not be empty") | |
| lengths = [self._decoded_steps(stream, segments) for stream in streams] | |
| if len(set(lengths)) != 1: | |
| raise ValueError( | |
| f"all token streams must decode to the same length, got {lengths}; use codec.batch_decode(...) for independent variable-length outputs" | |
| ) | |
| return lengths[0] | |
| def decode_batch( | |
| self, | |
| streams: Sequence[Sequence[int]], | |
| *, | |
| preset: str, | |
| fps: float | None = None, | |
| current_state: np.ndarray | None = None, | |
| previous_first_order: Mapping[str, np.ndarray] | None = None, | |
| ) -> dict[str, np.ndarray]: | |
| 'Decode rows to deltas, or absolute components with ``current_state``.' | |
| preset_config = self.preset(preset) | |
| self._validate_boundary_keys(previous_first_order, preset_config) | |
| segments = self._segments(preset_config) | |
| internal_steps, component_streams = self._decode_streams(streams, preset_config, segments) | |
| state_array = optional_finite_array( | |
| current_state, shape=(len(streams), preset_config.input_dim) | |
| ) | |
| output_fps = preset_config.source_hz if fps is None else fps | |
| output_steps = resampled_horizon( | |
| internal_steps, | |
| source_hz=preset_config.target_hz, | |
| target_hz=output_fps, | |
| ) | |
| output: dict[str, np.ndarray] = {} | |
| for segment_index, segment in enumerate(segments): | |
| decoded_batch = segment.profile.processor.decode_batch( | |
| component_streams[segment_index], | |
| active_dims=segment.component.active_dims, | |
| previous_first_order=None | |
| if previous_first_order is None | |
| else previous_first_order.get(segment.component.name), | |
| ) | |
| output[segment.component.name] = externalize_batch( | |
| decoded_batch, | |
| segment.component, | |
| source_hz=preset_config.target_hz, | |
| target_hz=output_fps, | |
| target_length=output_steps, | |
| method=preset_config.interpolation, | |
| current_state=state_array, | |
| ) | |
| return output | |
| def _decode_streams(self, streams, preset, segments): | |
| kernel = native_kernel("route_decode_batch") | |
| if kernel is not None: | |
| key = next( | |
| (key for key in reversed(tuple(self._grammar_cache)) if key[0] == preset.name), None | |
| ) | |
| grammar = self._grammar_cache.get(key) | |
| if grammar is None: | |
| grammar = self.grammar(preset=preset.name, horizon=1) | |
| compiled = grammar._compiled_grammars() | |
| if compiled is not None: | |
| width = sum(len(segment.component.active_dims) for segment in segments) | |
| return kernel( | |
| compiled, | |
| grammar._native_offsets, | |
| grammar.token_order == "time_major", | |
| streams, | |
| self._token_cells, | |
| width, | |
| ) | |
| steps = self._batch_steps(streams, segments) | |
| splits = [self._split_stream(row, preset=preset, steps=steps) for row in streams] | |
| return steps, [[row[i] for row in splits] for i in range(len(segments))] | |
| def decode_prefix_batch( | |
| self, | |
| streams, | |
| *, | |
| preset: str, | |
| horizon: int, | |
| steps: int, | |
| fps: float | None = None, | |
| current_state=None, | |
| previous_first_order=None, | |
| ) -> dict[str, np.ndarray]: | |
| 'Decode only fully covered execution frames on the native codec clock.' | |
| config = self.preset(preset) | |
| output_fps = config.source_hz if fps is None else fps | |
| if output_fps != config.target_hz: | |
| raise ValueError("prefix decode requires fps equal to the native codec clock") | |
| grammar = self.grammar(preset=preset, horizon=horizon) | |
| completed = [grammar.complete_prefix(row, steps=steps) for row in streams] | |
| decoded = self.decode_batch( | |
| completed, | |
| preset=preset, | |
| fps=output_fps, | |
| current_state=current_state, | |
| previous_first_order=previous_first_order, | |
| ) | |
| return {name: values[:, :steps] for name, values in decoded.items()} | |
| def grammar(self, *, preset: str, horizon: int) -> RoutedActionCodec2Grammar: | |
| """Build the global constrained grammar for one preset and target horizon.""" | |
| horizon = _integer(horizon, "horizon", positive=True) | |
| self.preset(preset) | |
| key = (preset, horizon) | |
| grammar = self._grammar_cache.get(key) | |
| if grammar is None: | |
| grammar = RoutedActionCodec2Grammar(self, preset=preset, horizon=horizon) | |
| self._grammar_cache[key] = grammar | |
| return grammar | |
| def new_action_tokens(self) -> list[str]: | |
| """Stable physical token names, including reserved profile budget slots.""" | |
| return [ | |
| f"<action_{name}_{index:04d}>" | |
| for name, runtime in self.profiles.items() | |
| for index in range(runtime.spec.token_budget) | |
| ] | |
| def save_pretrained(self, directory: str | Path) -> list[str]: | |
| """Save one manifest plus isolated physical processor subdirectories.""" | |
| root = Path(directory) | |
| files = [] | |
| for runtime in self.profiles.values(): | |
| files.extend(runtime.processor.save_pretrained(root / "profiles" / runtime.spec.name)) | |
| manifest = { | |
| "model_type": self.model_type, | |
| "config_version": ROUTER_CONFIG_VERSION, | |
| "profiles": [runtime.spec.to_dict() for runtime in self.profiles.values()], | |
| "presets": [preset.to_dict() for preset in self.action_spaces.values()], | |
| } | |
| path = root / ROUTER_CONFIG_NAME | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| path.write_text(yaml.safe_dump(manifest, sort_keys=False), encoding="utf-8") | |
| metadata = save_huggingface_metadata( | |
| root, | |
| model_type=self.model_type, | |
| processor_class=type(self).__name__, | |
| ) | |
| card = save_model_card(root, str(self)) | |
| return [str(path), str(card), *map(str, metadata), *files] | |
| def from_pretrained( | |
| cls, | |
| pretrained_model_name_or_path: str | Path, | |
| **kwargs: object, | |
| ) -> ActionCodec2Router | ActionCodec2: | |
| 'Load a router, or bind its public processor when given ``action_space``.' | |
| if "action_space" in kwargs: | |
| from ...frontend.actioncodec2 import ActionCodec2 | |
| return ActionCodec2.from_pretrained(pretrained_model_name_or_path, **kwargs) | |
| root = resolve_pretrained_directory( | |
| pretrained_model_name_or_path, | |
| allow_patterns=ROUTER_ALLOW_PATTERNS, | |
| **kwargs, | |
| ) | |
| specs, presets = cls.read_manifest(root) | |
| profiles = [ | |
| (spec, ActionCodec2Processor.from_pretrained(root / "profiles" / spec.name)) | |
| for spec in specs | |
| ] | |
| return cls(profiles, presets) | |
| def read_manifest( | |
| cls, directory: str | Path | |
| ) -> tuple[tuple[ProfileSpec, ...], tuple[PresetConfig, ...]]: | |
| "Read one artifact's profile specs and action spaces, loading no arrays." | |
| path = Path(directory) / ROUTER_CONFIG_NAME | |
| payload = _mapping( | |
| yaml.load(path.read_text(encoding="utf-8"), Loader=_UniqueKeyLoader), "router" | |
| ) | |
| _reject_unknown(payload, {"model_type", "config_version", "profiles", "presets"}, "router") | |
| if payload.get("model_type") != ROUTER_MODEL_TYPE: | |
| raise ConfigError(f"router.model_type must be {ROUTER_MODEL_TYPE!r}") | |
| version = payload.get("config_version") | |
| if version not in (3, ROUTER_CONFIG_VERSION): | |
| raise ConfigError( | |
| f"unsupported router config_version {payload.get('config_version')!r}" | |
| ) | |
| raw_profiles = payload.get("profiles") | |
| raw_presets = payload.get("presets") | |
| if not isinstance(raw_profiles, list) or not isinstance(raw_presets, list): | |
| raise ConfigError("router.profiles and router.presets must be lists") | |
| if version == 3: | |
| raw_presets = [ | |
| dict(_mapping(raw, "router.preset"), token_order="time_major") | |
| for raw in raw_presets | |
| ] | |
| elif any("token_order" not in _mapping(raw, "router.preset") for raw in raw_presets): | |
| raise ConfigError("router config_version=4 requires explicit preset.token_order") | |
| return ( | |
| tuple( | |
| ProfileSpec.from_dict(raw, path=f"router.profiles[{index}]") | |
| for index, raw in enumerate(raw_profiles) | |
| ), | |
| tuple( | |
| PresetConfig.from_dict(raw, path=f"router.presets[{index}]") | |
| for index, raw in enumerate(raw_presets) | |
| ), | |
| ) | |
| def describe_pretrained( | |
| cls, | |
| directory: str | Path, | |
| *, | |
| selected: str | None = None, | |
| action_dim: int | None = None, | |
| ) -> str: | |
| "Explain a saved artifact's layouts without loading primitives or BPE tables." | |
| root = Path(directory) | |
| specs, presets = cls.read_manifest(root) | |
| second_order_dims = { | |
| spec.name: _second_order_dims( | |
| ActionCodec2Config.from_pretrained(root / "profiles" / spec.name) | |
| ) | |
| for spec in specs | |
| } | |
| return format_action_spaces( | |
| {preset.name: preset for preset in presets}, | |
| selected=selected, | |
| action_dim=action_dim, | |
| second_order_boundaries={ | |
| preset.name: _second_order_boundaries(preset, second_order_dims) | |
| for preset in presets | |
| }, | |
| ) | |
| def eval(self) -> ActionCodec2Router: | |
| """Return ``self`` because all constituent processors are stateless.""" | |
| return self | |
| def to(self, device: object) -> ActionCodec2Router: | |
| """Return ``self`` because routed processors use CPU NumPy arrays.""" | |
| del device | |
| return self | |