"""Bag-of-words preprocessing for tiny sentiment classifier.""" from __future__ import annotations import json import re from pathlib import Path import numpy as np VOCAB_PATH = Path(__file__).resolve().parent / "vocab.json" TOKEN_PATTERN = re.compile(r"[a-z]+") def tokenize(text: str) -> list[str]: return TOKEN_PATTERN.findall(text.lower()) def build_vocab(texts: list[str]) -> list[str]: words: set[str] = set() for text in texts: words.update(tokenize(text)) return sorted(words) def text_to_bow(text: str, vocab: list[str]) -> np.ndarray: word_to_idx = {word: idx for idx, word in enumerate(vocab)} bow = np.zeros(len(vocab), dtype=np.float32) for token in tokenize(text): idx = word_to_idx.get(token) if idx is not None: bow[idx] = 1.0 return bow def save_vocab(vocab: list[str], labels: list[str]) -> None: VOCAB_PATH.write_text(json.dumps({"vocab": vocab, "labels": labels}, indent=2)) def load_vocab() -> tuple[list[str], list[str]]: data = json.loads(VOCAB_PATH.read_text()) return data["vocab"], data["labels"]