ZibinDong's picture
Publish audited ActionCodec2 release files
1bfc3f0 verified
Raw History Blame
5.24 kB
"""Package-owned configuration templates for fresh ActionCodec2 instances."""
from __future__ import annotations
from collections.abc import Mapping
from functools import lru_cache
from pathlib import Path
from types import MappingProxyType
from .bpe import BPESerializer, SetBPESerializer
from .configuration import ActionCodec2Config
from .presets import PresetConfig
from .processor import ActionCodec2Processor
from .routing import ActionCodec2Router
from .training import build_primitives
class CodecBuilder:
'Build unfitted physical profiles from packaged defaults or explicit configs.'
def __init__(self, *, primitive_order=1, bpe_scheme=None, profile_configs=None):
if type(primitive_order) is not int or primitive_order not in (1, 2):
raise ValueError("primitive_order must be 1 or 2")
if bpe_scheme not in (None, "set_bpe", "unified_set_bpe", "bpe"):
raise ValueError("bpe_scheme must be 'set_bpe', 'unified_set_bpe' or 'bpe'")
if profile_configs is not None and not isinstance(profile_configs, Mapping):
raise TypeError("profile_configs must map 'joint'/'eef' to physical configurations")
self.profile_configs = dict(profile_configs or {})
if set(self.profile_configs) - {"joint", "eef"}:
raise ValueError("profile_configs keys must be 'joint' or 'eef'")
self.primitive_order = primitive_order
self.bpe_scheme = bpe_scheme
self.assets = Path(__file__).with_name("assets")
def _config(self, name: str) -> ActionCodec2Config:
suffix = "" if self.primitive_order == 1 else "_second_order"
raw = self.profile_configs.get(name, self.assets / "profiles" / f"{name}{suffix}.yaml")
if isinstance(raw, ActionCodec2Config):
config = raw
elif isinstance(raw, Mapping):
config = ActionCodec2Config.from_dict(raw)
else:
config = ActionCodec2Config.from_yaml(raw)
if config.train is None:
raise ValueError(f"{name} profile config requires a train section")
if self.bpe_scheme is not None:
payload = config.to_dict()
payload["set_bpe"]["scheme"] = self.bpe_scheme
if self.bpe_scheme == "bpe":
payload["train"]["bpe"]["spatial_vocab_size"] = payload["train"]["bpe"][
"vocab_size"
]
config = ActionCodec2Config.from_dict(payload)
return config
def build(self) -> ActionCodec2Router:
"""Create primitive-only profiles; the public facade tracks fitted state."""
processors = {}
budgets = {}
for name in ("joint", "eef"):
config = self._config(name)
primitives = build_primitives(config)
if config.set_bpe.scheme == "bpe":
serializer = BPESerializer(
bins=primitives.bins, lookahead=config.set_bpe.lookahead, merges=()
)
elif config.set_bpe.scheme == "unified_set_bpe":
from .unified_set_bpe import UnifiedSetBPESerializer
serializer = UnifiedSetBPESerializer(
bins=primitives.bins, lookahead=config.set_bpe.lookahead, merges=()
)
else:
serializer = SetBPESerializer(
bins=primitives.bins,
lookahead=config.set_bpe.lookahead,
spatial_merges=(),
temporal_merges=(),
)
processors[name] = ActionCodec2Processor(config, primitives, serializer)
budgets[name] = config.train.bpe.vocab_size
presets = list(builtin_action_spaces().values())
return ActionCodec2Router.from_processors(
processors, token_budgets=budgets, presets=presets
)
@lru_cache(maxsize=1)
def builtin_action_spaces():
'Return a read-only name-to-preset mapping shipped in the installed package.'
presets = [
PresetConfig.from_yaml(path)
for path in sorted(Path(__file__).with_name("assets").joinpath("presets").glob("*.yaml"))
]
return MappingProxyType({preset.name: preset for preset in presets})
class ProfileBundleBuilder:
'Assemble two existing physical artifacts using their recorded vocabulary budgets.'
def __init__(self, joint, eef, *, token_budgets=None):
self.paths = {"joint": joint, "eef": eef}
self.budgets = dict(token_budgets or {})
if self.budgets.keys() - self.paths.keys():
raise ValueError("token_budgets accepts only 'joint' and 'eef'")
def build(self):
processors = {
name: ActionCodec2Processor.from_pretrained(path) for name, path in self.paths.items()
}
budgets = {
name: self.budgets.get(
name,
processor.config.train.bpe.vocab_size
if processor.config.train is not None
else processor.vocab_size,
)
for name, processor in processors.items()
}
return ActionCodec2Router.from_processors(
processors, token_budgets=budgets, presets=list(builtin_action_spaces().values())
)