Nexus-Erebus-3M / tokenization_nexus.py
MaliosDark's picture
Nexus-Erebus-3M (avg 32.50)
4d848c2 verified
Raw
History Blame Contribute Delete
1.81 kB
"""Nexus-Erebus digit-atomic, least-significant-digit-first tokenizer.
Digits are never merged by BPE, and every maximal run of digits is reversed at
encode time so the model reads and writes numbers least-significant-digit first.
This aligns carry propagation with the left-to-right direction the model reads,
which is what lets a tiny model do integer arithmetic.
The transform is an involution, so decoding simply applies it again to restore
ordinary left-to-right numbers. Callers see normal text in and normal text out.
Load with:
AutoTokenizer.from_pretrained(repo, trust_remote_code=True)
"""
import re
from transformers import PreTrainedTokenizerFast
_DIGIT_RUN = re.compile(r"\d+")
def rev_digits(text: str) -> str:
"""Reverse each maximal run of digits. Involution: rev(rev(x)) == x."""
return _DIGIT_RUN.sub(lambda m: m.group(0)[::-1], text)
class NexusLSDTokenizer(PreTrainedTokenizerFast):
"""PreTrainedTokenizerFast that applies the LSD-first digit transform."""
def _t(self, x):
if x is None:
return None
if isinstance(x, str):
return rev_digits(x)
if isinstance(x, (list, tuple)):
return type(x)(self._t(i) for i in x)
return x
def _batch_encode_plus(self, batch_text_or_text_pairs, *args, **kwargs):
return super()._batch_encode_plus(self._t(batch_text_or_text_pairs), *args, **kwargs)
def _encode_plus(self, text, text_pair=None, *args, **kwargs):
return super()._encode_plus(self._t(text), self._t(text_pair), *args, **kwargs)
# NOTE: do not override tokenize(); it routes through _encode_plus, so the
# transform would be applied twice and cancel out.
def _decode(self, *args, **kwargs):
return rev_digits(super()._decode(*args, **kwargs))