import json PAD, BOS, EOS, UNK = 0, 1, 2, 3 SPECIALS = ["", "", "", ""] class CharTokenizer: def __init__(self, vocab=None): self.vocab = vocab or {} self.inv = {i: c for c, i in self.vocab.items()} @classmethod def build(cls, texts, min_freq=20): from collections import Counter cnt = Counter() for t in texts: cnt.update(t) vocab = {s: i for i, s in enumerate(SPECIALS)} for ch, freq in sorted(cnt.items()): if freq >= min_freq: vocab[ch] = len(vocab) return cls(vocab) def encode(self, text, add_special=True): ids = [self.vocab.get(c, UNK) for c in text] return [BOS] + ids + [EOS] if add_special else ids def decode(self, ids): return "".join(self.inv.get(i, "") for i in ids if i not in (PAD, BOS, EOS, UNK)) def save(self, path): with open(path, "w", encoding="utf-8") as f: json.dump(self.vocab, f, ensure_ascii=False) @classmethod def load(cls, path): with open(path, encoding="utf-8") as f: return cls(json.load(f)) def __len__(self): return len(self.vocab)