ActionCodec2 / runtime /backends /actioncodec2 /native_serialization.py
ZibinDong's picture
Publish audited ActionCodec2 release files
1bfc3f0 verified
Raw History Blame
2.93 kB
"""Cached C++ serializers shared by scalar and batched inference paths."""
from __future__ import annotations
import numpy as np
from .native_backend import native_kernel
class NativeCacheMixin:
"""Serialize numerical state while rebuilding process-local C++ caches."""
def __getstate__(self):
state = vars(self).copy()
for key in ("_compiled_serializer", "_compiled_spatial", "_coverage_metadata"):
state.pop(key, None)
return state
def __setstate__(self, state):
vars(self).update(state)
def compiled_serializer(owner):
"""Return a codec for a serializer/vocabulary, or the Python override."""
spatial = getattr(owner, "spatial", None)
temporal = getattr(owner, "temporal_merges", getattr(owner, "merges", ()))
scheme = getattr(owner, "scheme", "set_bpe" if spatial is not None else "bpe")
constructor = native_kernel("SetBPE" if scheme == "set_bpe" else "PlainBPE")
if constructor is None:
return None
cached = getattr(owner, "_compiled_serializer", None)
if cached is None:
bins = getattr(owner, "bins", spatial.bins if spatial is not None else ())
if scheme == "set_bpe":
merges = getattr(owner, "spatial_merges", spatial.merges)
cached = constructor(bins, owner.lookahead, merges, temporal)
else:
cached = constructor(bins, owner.merges)
owner._compiled_serializer = cached
return cached
def encode_native(owner, dense: np.ndarray):
codec = compiled_serializer(owner)
options = getattr(owner, "encoding_search", None)
if options is not None and options.enabled:
if codec is None or not hasattr(codec, "encode_search_batch"):
raise RuntimeError(
"packing search requires the rebuilt actioncodec2 native extension; "
"run 'python setup.py build_ext --inplace'"
)
return codec.encode_search_batch(
np.asarray(dense, dtype=np.int64),
options.spatial_search,
options.temporal_search,
options.search_window,
options.search_beam,
)
return None if codec is None else codec.encode_batch(np.asarray(dense, dtype=np.int64))
def decode_native(owner, rows, dims, *, validate=False):
codec = compiled_serializer(owner)
if codec is None:
return None
bins = getattr(owner, "bins", owner.spatial.bins if hasattr(owner, "spatial") else ())
if validate:
if not hasattr(codec, "decode_checked_batch"):
return None
support = dims if hasattr(codec, "decode_active_batch") else sum(1 << d for d in dims)
return codec.decode_checked_batch(rows, len(bins), support)
if hasattr(codec, "decode_active_batch"):
return codec.decode_active_batch(rows, len(bins), dims)
return codec.decode_batch(rows, len(bins), sum(1 << d for d in dims))