Open_Mind / tests /test_tokenizer.py
Rachit17-12's picture
Initial commit
4a6405d
Raw
History Blame Contribute Delete
4.73 kB
"""
Unit tests for the BPE Tokenizer.
"""
import os
import sys
import tempfile
import pytest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
from data.tokenizer import BPETokenizer
class TestBPETokenizer:
"""Test suite for BPETokenizer."""
def setup_method(self):
"""Create a small tokenizer for testing."""
self.tokenizer = BPETokenizer(vocab_size=300)
def test_initialization(self):
"""Test tokenizer initializes with correct vocab size."""
tok = BPETokenizer(vocab_size=32000)
assert tok.vocab_size == 32000
assert len(tok.SPECIAL_TOKENS) == 6
assert tok.eos_token_id == 0
assert tok.pad_token_id == 1
assert tok.unk_token_id == 2
def test_byte_level_encoding(self):
"""Test encoding without training (byte-level fallback)."""
tok = BPETokenizer()
text = "hi"
ids = tok.encode(text)
decoded = tok.decode(ids)
assert decoded == text
def test_encode_decode_roundtrip_ascii(self):
"""Test encode->decode preserves ASCII text."""
tok = BPETokenizer()
texts = [
"Hello, world!",
"The quick brown fox",
"Testing 123",
"Special chars: @#$%",
]
for text in texts:
ids = tok.encode(text)
decoded = tok.decode(ids)
assert decoded == text, f"Roundtrip failed for: {text}"
def test_encode_decode_roundtrip_unicode(self):
"""Test encode->decode preserves Unicode text."""
tok = BPETokenizer()
texts = [
"café résumé",
"日本語テスト",
"emoji 🎉🚀",
"über straße",
]
for text in texts:
ids = tok.encode(text)
decoded = tok.decode(ids)
assert decoded == text, f"Unicode roundtrip failed for: {text}"
def test_special_tokens(self):
"""Test special token encoding/decoding."""
tok = BPETokenizer()
text = "Hello<|endoftext|>World"
# Without allowing special tokens
ids_no_special = tok.encode(text)
# The special token should be encoded as regular bytes
assert tok.eos_token_id not in ids_no_special
# With allowing special tokens
ids_with_special = tok.encode(text, allowed_special={"<|endoftext|>"})
assert tok.eos_token_id in ids_with_special
def test_special_tokens_all(self):
"""Test allowing all special tokens."""
tok = BPETokenizer()
text = "<|system|>Hello<|endoftext|>"
ids = tok.encode(text, allowed_special={"all"})
assert 3 in ids # system token
assert 0 in ids # endoftext token
def test_training(self):
"""Test tokenizer training on a small corpus."""
tok = BPETokenizer(vocab_size=300)
corpus = "the cat sat on the mat. the cat sat on the hat. " * 100
tok.train(corpus, verbose=False)
# Should have learned some merges
assert len(tok.merge_list) > 0
assert len(tok.vocab) > 262 # 6 special + 256 bytes + merges
# Encoding should produce fewer tokens than byte-level
text = "the cat sat"
ids = tok.encode(text)
assert len(ids) < len(text.encode("utf-8"))
def test_save_and_load(self):
"""Test saving and loading tokenizer."""
tok = BPETokenizer(vocab_size=300)
corpus = "hello world " * 100
tok.train(corpus, verbose=False)
with tempfile.TemporaryDirectory() as tmpdir:
tok.save(tmpdir, "test_tok")
# Check files exist
assert os.path.exists(os.path.join(tmpdir, "test_tok_vocab.json"))
assert os.path.exists(os.path.join(tmpdir, "test_tok_merges.txt"))
assert os.path.exists(os.path.join(tmpdir, "tokenizer.json"))
# Load and verify
loaded = BPETokenizer.load(tmpdir, "test_tok")
assert len(loaded.vocab) == len(tok.vocab)
assert len(loaded.merge_list) == len(tok.merge_list)
# Verify encoding consistency
test_text = "hello world"
assert tok.encode(test_text) == loaded.encode(test_text)
def test_empty_input(self):
"""Test handling of empty input."""
tok = BPETokenizer()
assert tok.encode("") == []
assert tok.decode([]) == ""
def test_repr(self):
"""Test string representation."""
tok = BPETokenizer(vocab_size=32000)
repr_str = repr(tok)
assert "BPETokenizer" in repr_str
assert "vocab_size" in repr_str
if __name__ == "__main__":
pytest.main([__file__, "-v"])