Skill Tracer
Skills › Scientific Agent Skills › transformers › tokenizers.md

tokenizers.md

444 lines · skills/transformers/references/tokenizers.md at 5f2bc03

Open on GitHub
1# Tokenizers
2
3Targets Transformers 5.18.0. Tokenizer behavior was exercised with a local BERT vocabulary and a local chat template; Hub examples remain illustrative. See [review evidence](review.md).
4

Tokenizers

Targets Transformers 5.18.0. Tokenizer behavior was exercised with a local BERT vocabulary and a local chat template; Hub examples remain illustrative. See review evidence.

Raw lines 1 to 4
5## Overview
6
7Tokenizers convert text into numerical representations (tokens) that models can process. They handle special tokens, padding, truncation, and attention masks.
8

Overview

Tokenizers convert text into numerical representations (tokens) that models can process. They handle special tokens, padding, truncation, and attention masks.

Raw lines 5 to 8
9## Loading Tokenizers

Loading Tokenizers

Raw lines 9 to 10
11### AutoTokenizer
13Automatically load the correct tokenizer for a model:
15```python
16from transformers import AutoTokenizer
18tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
19```
21Load from local path:
22```python
23tokenizer = AutoTokenizer.from_pretrained("./local/tokenizer/path")
24```

AutoTokenizer

Automatically load the correct tokenizer for a model:

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")

Load from local path:

tokenizer = AutoTokenizer.from_pretrained("./local/tokenizer/path")
Raw lines 11 to 25
26## Basic Tokenization

Basic Tokenization

Raw lines 26 to 27
28### Encode Text
30```python
31# Simple encoding
32text = "Hello, how are you?"
33tokens = tokenizer.encode(text)
34print(tokens) # [101, 7592, 1010, 2129, 2024, 2017, 1029, 102]
36# With text tokenization
37tokens = tokenizer.tokenize(text)
38print(tokens) # ['hello', ',', 'how', 'are', 'you', '?']
39```

Encode Text

# Simple encoding
text = "Hello, how are you?"
tokens = tokenizer.encode(text)
print(tokens)  # [101, 7592, 1010, 2129, 2024, 2017, 1029, 102]

# With text tokenization
tokens = tokenizer.tokenize(text)
print(tokens)  # ['hello', ',', 'how', 'are', 'you', '?']
Raw lines 28 to 40
41### Decode Tokens
43```python
44token_ids = [101, 7592, 1010, 2129, 2024, 2017, 1029, 102]
45text = tokenizer.decode(token_ids)
46print(text) # Includes [CLS]/[SEP] unless skip_special_tokens=True
48# Skip special tokens
49text = tokenizer.decode(token_ids, skip_special_tokens=True)
50print(text) # "hello, how are you?"
51```

Decode Tokens

token_ids = [101, 7592, 1010, 2129, 2024, 2017, 1029, 102]
text = tokenizer.decode(token_ids)
print(text)  # Includes [CLS]/[SEP] unless skip_special_tokens=True

# Skip special tokens
text = tokenizer.decode(token_ids, skip_special_tokens=True)
print(text)  # "hello, how are you?"
Raw lines 41 to 52
53## The `__call__` Method
55Primary tokenization interface:
57```python
58# Single text
59inputs = tokenizer("Hello, how are you?")
61# Returns BatchEncoding: input_ids, attention_mask, and tokenizer-dependent fields
62# (BERT also emits token_type_ids).
63print(inputs)
64# {
65# 'input_ids': [101, 7592, 1010, 2129, 2024, 2017, 1029, 102],
66# 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1]
67# }
68```
70Multiple texts:
71```python
72texts = ["Hello", "How are you?"]
73inputs = tokenizer(texts, padding=True, truncation=True)
74```

The __call__ Method

Primary tokenization interface:

# Single text
inputs = tokenizer("Hello, how are you?")

# Returns BatchEncoding: input_ids, attention_mask, and tokenizer-dependent fields
# (BERT also emits token_type_ids).
print(inputs)
# {
#   'input_ids': [101, 7592, 1010, 2129, 2024, 2017, 1029, 102],
#   'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1]
# }

Multiple texts:

texts = ["Hello", "How are you?"]
inputs = tokenizer(texts, padding=True, truncation=True)
Raw lines 53 to 75
76## Key Parameters

Key Parameters

Raw lines 76 to 77
78### Return Tensors
80**return_tensors**: Output format (`"pt"` for PyTorch, `"np"` for NumPy)
81```python
82# PyTorch tensors (without return_tensors, the default output is Python lists)
83inputs = tokenizer("text", return_tensors="pt")
85# NumPy arrays
86inputs = tokenizer("text", return_tensors="np")
87```

Return Tensors

return_tensors: Output format ("pt" for PyTorch, "np" for NumPy)

# PyTorch tensors (without return_tensors, the default output is Python lists)
inputs = tokenizer("text", return_tensors="pt")

# NumPy arrays
inputs = tokenizer("text", return_tensors="np")
Raw lines 78 to 88
89### Padding
91**padding**: Pad sequences to same length
92```python
93# Pad to longest sequence in batch
94inputs = tokenizer(texts, padding=True)
96# Pad to specific length
97inputs = tokenizer(texts, padding="max_length", max_length=128)
99# No padding
100inputs = tokenizer(texts, padding=False)
101```
103**pad_to_multiple_of**: Pad to multiple of specified value
104```python
105inputs = tokenizer(texts, padding=True, pad_to_multiple_of=8)
106```

Padding

padding: Pad sequences to same length

# Pad to longest sequence in batch
inputs = tokenizer(texts, padding=True)

# Pad to specific length
inputs = tokenizer(texts, padding="max_length", max_length=128)

# No padding
inputs = tokenizer(texts, padding=False)

pad_to_multiple_of: Pad to multiple of specified value

inputs = tokenizer(texts, padding=True, pad_to_multiple_of=8)
Raw lines 89 to 107
108### Truncation
110**truncation**: Limit sequence length
111```python
112# Truncate to max_length
113inputs = tokenizer(text, truncation=True, max_length=512)
115# Truncate first sequence in pairs
116inputs = tokenizer(text1, text2, truncation="only_first")
118# Truncate second sequence
119inputs = tokenizer(text1, text2, truncation="only_second")
121# Truncate longest first (default for pairs)
122inputs = tokenizer(text1, text2, truncation="longest_first", max_length=512)
123```

Truncation

truncation: Limit sequence length

# Truncate to max_length
inputs = tokenizer(text, truncation=True, max_length=512)

# Truncate first sequence in pairs
inputs = tokenizer(text1, text2, truncation="only_first")

# Truncate second sequence
inputs = tokenizer(text1, text2, truncation="only_second")

# Truncate longest first (default for pairs)
inputs = tokenizer(text1, text2, truncation="longest_first", max_length=512)
Raw lines 108 to 124
125### Max Length
127**max_length**: Maximum sequence length
128```python
129inputs = tokenizer(text, max_length=512, truncation=True)
130```

Max Length

max_length: Maximum sequence length

inputs = tokenizer(text, max_length=512, truncation=True)
Raw lines 125 to 131
132### Additional Outputs
134**return_attention_mask**: Include attention mask (default True)
135```python
136inputs = tokenizer(text, return_attention_mask=True)
137```
139**return_token_type_ids**: Segment IDs for sentence pairs
140```python
141inputs = tokenizer(text1, text2, return_token_type_ids=True)
142```
144**return_offsets_mapping**: Character position mapping (Fast tokenizers only)
145```python
146inputs = tokenizer(text, return_offsets_mapping=True)
147```
149**return_length**: Include sequence lengths
150```python
151inputs = tokenizer(texts, padding=True, return_length=True)
152```

Additional Outputs

return_attention_mask: Include attention mask (default True)

inputs = tokenizer(text, return_attention_mask=True)

return_token_type_ids: Segment IDs for sentence pairs

inputs = tokenizer(text1, text2, return_token_type_ids=True)

return_offsets_mapping: Character position mapping (Fast tokenizers only)

inputs = tokenizer(text, return_offsets_mapping=True)

return_length: Include sequence lengths

inputs = tokenizer(texts, padding=True, return_length=True)
Raw lines 132 to 153
154## Special Tokens

Special Tokens

Raw lines 154 to 155
156### Predefined Special Tokens
158Access special tokens:
159```python
160print(tokenizer.cls_token) # [CLS] or <s>
161print(tokenizer.sep_token) # [SEP] or </s>
162print(tokenizer.pad_token) # [PAD]
163print(tokenizer.unk_token) # [UNK]
164print(tokenizer.mask_token) # [MASK]
165print(tokenizer.eos_token) # End of sequence
166print(tokenizer.bos_token) # Beginning of sequence
168# Get IDs
169print(tokenizer.cls_token_id)
170print(tokenizer.sep_token_id)
171```

Predefined Special Tokens

Access special tokens:

print(tokenizer.cls_token)      # [CLS] or <s>
print(tokenizer.sep_token)      # [SEP] or </s>
print(tokenizer.pad_token)      # [PAD]
print(tokenizer.unk_token)      # [UNK]
print(tokenizer.mask_token)     # [MASK]
print(tokenizer.eos_token)      # End of sequence
print(tokenizer.bos_token)      # Beginning of sequence

# Get IDs
print(tokenizer.cls_token_id)
print(tokenizer.sep_token_id)
Raw lines 156 to 172
173### Add Special Tokens
175Manual control:
176```python
177# Automatically add special tokens (default True)
178inputs = tokenizer(text, add_special_tokens=True)
180# Skip special tokens
181inputs = tokenizer(text, add_special_tokens=False)
182```

Add Special Tokens

Manual control:

# Automatically add special tokens (default True)
inputs = tokenizer(text, add_special_tokens=True)

# Skip special tokens
inputs = tokenizer(text, add_special_tokens=False)
Raw lines 173 to 183
184### Custom Special Tokens
186```python
187special_tokens_dict = {
188 "extra_special_tokens": ["<CUSTOM>", "<SPECIAL>"]
191num_added = tokenizer.add_special_tokens(special_tokens_dict)
192print(f"Added {num_added} tokens")
194# Resize model embeddings after adding tokens
195model.resize_token_embeddings(len(tokenizer))
196```

Custom Special Tokens

special_tokens_dict = {
    "extra_special_tokens": ["<CUSTOM>", "<SPECIAL>"]
}

num_added = tokenizer.add_special_tokens(special_tokens_dict)
print(f"Added {num_added} tokens")

# Resize model embeddings after adding tokens
model.resize_token_embeddings(len(tokenizer))
Raw lines 184 to 197
198## Sentence Pairs
200Tokenize text pairs:
202```python
203text1 = "What is the capital of France?"
204text2 = "Paris is the capital of France."
206# Automatically handles separation
207inputs = tokenizer(text1, text2, padding=True, truncation=True)
209# Results in: [CLS] text1 [SEP] text2 [SEP]
210```

Sentence Pairs

Tokenize text pairs:

text1 = "What is the capital of France?"
text2 = "Paris is the capital of France."

# Automatically handles separation
inputs = tokenizer(text1, text2, padding=True, truncation=True)

# Results in: [CLS] text1 [SEP] text2 [SEP]
Raw lines 198 to 211
212## Batch Encoding
214Process multiple texts:
216```python
217texts = ["First text", "Second text", "Third text"]
219# Basic batch encoding
220batch = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")
222# Access individual encodings
223for i in range(len(texts)):
224 input_ids = batch["input_ids"][i]
225 attention_mask = batch["attention_mask"][i]
226```

Batch Encoding

Process multiple texts:

texts = ["First text", "Second text", "Third text"]

# Basic batch encoding
batch = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Access individual encodings
for i in range(len(texts)):
    input_ids = batch["input_ids"][i]
    attention_mask = batch["attention_mask"][i]
Raw lines 212 to 227
228## Tokenizer Backends
230v5 uses one implementation per model backed by `TokenizersBackend`, `SentencePieceBackend`, `PythonBackend`, or `MistralCommonBackend`. `AutoTokenizer` selects based on files/dependencies. In 5.18.0 its old `use_fast` argument is ignored; `use_fast=False` does not force the former Python tokenizer. Inspect `tokenizer.is_fast` before using offset/word alignment, and use the checkpoint's actual backend rather than substituting a tokenizer.
232```python
233print(type(tokenizer).__name__, tokenizer.is_fast)
234```

Tokenizer Backends

v5 uses one implementation per model backed by TokenizersBackend, SentencePieceBackend, PythonBackend, or MistralCommonBackend. AutoTokenizer selects based on files/dependencies. In 5.18.0 its old use_fast argument is ignored; use_fast=False does not force the former Python tokenizer. Inspect tokenizer.is_fast before using offset/word alignment, and use the checkpoint's actual backend rather than substituting a tokenizer.

print(type(tokenizer).__name__, tokenizer.is_fast)
Raw lines 228 to 235
236### Fast Tokenizer Features
238**Offset mapping** (character positions):
239```python
240inputs = tokenizer("Hello world", return_offsets_mapping=True)
241print(inputs["offset_mapping"])
242# [(0, 0), (0, 5), (6, 11), (0, 0)] # [CLS], "Hello", "world", [SEP]
243```
245**Token to word mapping**:
246```python
247encoding = tokenizer("Hello world")
248word_ids = encoding.word_ids()
249print(word_ids) # [None, 0, 1, None] # [CLS]=None, "Hello"=0, "world"=1, [SEP]=None
250```

Fast Tokenizer Features

Offset mapping (character positions):

inputs = tokenizer("Hello world", return_offsets_mapping=True)
print(inputs["offset_mapping"])
# [(0, 0), (0, 5), (6, 11), (0, 0)]  # [CLS], "Hello", "world", [SEP]

Token to word mapping:

encoding = tokenizer("Hello world")
word_ids = encoding.word_ids()
print(word_ids)  # [None, 0, 1, None]  # [CLS]=None, "Hello"=0, "world"=1, [SEP]=None
Raw lines 236 to 251
252## Saving Tokenizers
254Save locally:
255```python
256tokenizer.save_pretrained("./my_tokenizer")
257```
259Push to Hub:
260```python
261tokenizer.push_to_hub("username/my-tokenizer")
262```

Saving Tokenizers

Save locally:

tokenizer.save_pretrained("./my_tokenizer")

Push to Hub:

tokenizer.push_to_hub("username/my-tokenizer")
Raw lines 252 to 263
264## Advanced Usage

Advanced Usage

Raw lines 264 to 265
266### Vocabulary
268Access vocabulary:
269```python
270vocab = tokenizer.get_vocab()
271vocab_size = len(vocab)
273# Get token for ID
274token = tokenizer.convert_ids_to_tokens(100)
276# Get ID for token
277token_id = tokenizer.convert_tokens_to_ids("hello")
278```

Vocabulary

Access vocabulary:

vocab = tokenizer.get_vocab()
vocab_size = len(vocab)

# Get token for ID
token = tokenizer.convert_ids_to_tokens(100)

# Get ID for token
token_id = tokenizer.convert_tokens_to_ids("hello")
Raw lines 266 to 279
280### Encoding Details
282Get detailed encoding information:
284```python
285encoding = tokenizer("Hello world", return_tensors="pt")
287# Original methods still available
288tokens = encoding.tokens()
289word_ids = encoding.word_ids()
290sequence_ids = encoding.sequence_ids()
291```

Encoding Details

Get detailed encoding information:

encoding = tokenizer("Hello world", return_tensors="pt")

# Original methods still available
tokens = encoding.tokens()
word_ids = encoding.word_ids()
sequence_ids = encoding.sequence_ids()
Raw lines 280 to 292
293### Custom Preprocessing
295`AutoTokenizer` is a factory, not an instantiable tokenizer base class. Apply preprocessing explicitly and consistently instead of subclassing it. Lowercasing is appropriate only when the checkpoint/training protocol expects it:
297```python
298def tokenize_normalized(texts, tokenizer):
299 normalized = [text.strip() for text in texts]
300 return tokenizer(normalized, truncation=True, max_length=128)
301```
303Preserve the original text if you need original-coordinate spans: normalization changes offset meaning.

Custom Preprocessing

AutoTokenizer is a factory, not an instantiable tokenizer base class. Apply preprocessing explicitly and consistently instead of subclassing it. Lowercasing is appropriate only when the checkpoint/training protocol expects it:

def tokenize_normalized(texts, tokenizer):
    normalized = [text.strip() for text in texts]
    return tokenizer(normalized, truncation=True, max_length=128)

Preserve the original text if you need original-coordinate spans: normalization changes offset meaning.

Raw lines 293 to 304
305## Chat Templates
307Use a chat checkpoint with a saved `chat_template`; BERT/GPT-2 examples above are not chat templates. `tokenize=True` returns a `BatchEncoding` dictionary in v5. Pass `**inputs` to generation. For training use `add_generation_prompt=False`; preserve labels/loss masks appropriate to the training objective. Do not combine `add_generation_prompt=True` with `continue_final_message=True`.
309```python
310messages = [
311 {"role": "system", "content": "You are helpful."},
312 {"role": "user", "content": "Hello!"},
313 {"role": "assistant", "content": "Hi there!"},
314 {"role": "user", "content": "How are you?"}
317# Format for display or preprocessing
318text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
319print(text)
320# If tokenizing this formatted string later, use add_special_tokens=False.
322# Tokenize directly for generation
323inputs = tokenizer.apply_chat_template(
324 messages,
325 tokenize=True,
326 add_generation_prompt=True,
327 return_tensors="pt"
329```

Chat Templates

Use a chat checkpoint with a saved chat_template; BERT/GPT-2 examples above are not chat templates. tokenize=True returns a BatchEncoding dictionary in v5. Pass **inputs to generation. For training use add_generation_prompt=False; preserve labels/loss masks appropriate to the training objective. Do not combine add_generation_prompt=True with continue_final_message=True.

messages = [
    {"role": "system", "content": "You are helpful."},
    {"role": "user", "content": "Hello!"},
    {"role": "assistant", "content": "Hi there!"},
    {"role": "user", "content": "How are you?"}
]

# Format for display or preprocessing
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
print(text)
# If tokenizing this formatted string later, use add_special_tokens=False.

# Tokenize directly for generation
inputs = tokenizer.apply_chat_template(
    messages,
    tokenize=True,
    add_generation_prompt=True,
    return_tensors="pt"
)
Raw lines 305 to 330
331## Common Patterns

Common Patterns

Raw lines 331 to 332
333### Pattern 1: Simple Text Classification
335```python
336import torch
338texts = ["I love this!", "I hate this!"]
339labels = [1, 0]
341inputs = tokenizer(
342 texts,
343 padding=True,
344 truncation=True,
345 max_length=512,
346 return_tensors="pt"
349# Use with model
350inputs = inputs.to(model.device)
351outputs = model(**inputs, labels=torch.tensor(labels, device=model.device))
352```

Pattern 1: Simple Text Classification

import torch

texts = ["I love this!", "I hate this!"]
labels = [1, 0]

inputs = tokenizer(
    texts,
    padding=True,
    truncation=True,
    max_length=512,
    return_tensors="pt"
)

# Use with model
inputs = inputs.to(model.device)
outputs = model(**inputs, labels=torch.tensor(labels, device=model.device))
Raw lines 333 to 353
354### Pattern 2: Question Answering
356```python
357question = "What is the capital?"
358context = "Paris is the capital of France."
360inputs = tokenizer(
361 question,
362 context,
363 padding=True,
364 truncation="only_second",
365 max_length=384,
366 return_tensors="pt"
368```

Pattern 2: Question Answering

question = "What is the capital?"
context = "Paris is the capital of France."

inputs = tokenizer(
    question,
    context,
    padding=True,
    truncation="only_second",
    max_length=384,
    return_tensors="pt"
)
Raw lines 354 to 369
370### Pattern 3: Text Generation
372```python
373prompt = "Once upon a time"
375inputs = tokenizer(prompt, return_tensors="pt")
377# Generate
378outputs = model.generate(
379 **inputs.to(model.device),
380 max_new_tokens=50,
381 pad_token_id=tokenizer.eos_token_id
384# Decode
385text = tokenizer.decode(outputs[0], skip_special_tokens=True)
386```

Pattern 3: Text Generation

prompt = "Once upon a time"

inputs = tokenizer(prompt, return_tensors="pt")

# Generate
outputs = model.generate(
    **inputs.to(model.device),
    max_new_tokens=50,
    pad_token_id=tokenizer.eos_token_id
)

# Decode
text = tokenizer.decode(outputs[0], skip_special_tokens=True)
Raw lines 370 to 387
388### Pattern 4: Dataset Tokenization
390```python
391def tokenize_function(examples):
392 return tokenizer(
393 examples["text"],
394 padding="max_length",
395 truncation=True,
396 max_length=512
397 )
399# Apply to dataset
400tokenized_dataset = dataset.map(tokenize_function, batched=True)
401```

Pattern 4: Dataset Tokenization

def tokenize_function(examples):
    return tokenizer(
        examples["text"],
        padding="max_length",
        truncation=True,
        max_length=512
    )

# Apply to dataset
tokenized_dataset = dataset.map(tokenize_function, batched=True)
Raw lines 388 to 402
403## Best Practices
4051. **Always specify return_tensors**: For model input
4062. **Use padding and truncation**: For batch processing
4073. **Set max_length explicitly**: Prevent memory issues
4084. **Use Fast tokenizers**: When available for speed
4095. **Handle pad_token**: For compatible causal-LM inference, use EOS if needed and retain attention_mask; do not mask genuine EOS training labels just because PAD shares its ID
4106. **Add special tokens once**: Chat templates already contain them; do not duplicate them
4117. **Resize embeddings**: After adding custom tokens
4128. **Decode with skip_special_tokens**: For cleaner output
4139. **Use batched processing**: For efficiency with datasets
41410. **Save tokenizer with model**: Ensure compatibility

Best Practices

  1. Always specify return_tensors: For model input
  2. Use padding and truncation: For batch processing
  3. Set max_length explicitly: Prevent memory issues
  4. Use Fast tokenizers: When available for speed
  5. Handle pad_token: For compatible causal-LM inference, use EOS if needed and retain attention_mask; do not mask genuine EOS training labels just because PAD shares its ID
  6. Add special tokens once: Chat templates already contain them; do not duplicate them
  7. Resize embeddings: After adding custom tokens
  8. Decode with skip_special_tokens: For cleaner output
  9. Use batched processing: For efficiency with datasets
  10. Save tokenizer with model: Ensure compatibility
Raw lines 403 to 415
416## Common Issues
418**Padding token not set:**
419```python
420if tokenizer.pad_token is None:
421 tokenizer.pad_token = tokenizer.eos_token
422```
424**Sequence too long:**
425```python
426# Enable truncation
427inputs = tokenizer(text, truncation=True, max_length=512)
428```
430**Mismatched vocabulary:**
431```python
432# Always load tokenizer and model from same checkpoint
433tokenizer = AutoTokenizer.from_pretrained("model-id")
434model = AutoModel.from_pretrained("model-id")
435```
437**Attention mask issues:**
438```python
439# Ensure attention_mask is passed
440outputs = model(
441 input_ids=inputs["input_ids"],
442 attention_mask=inputs["attention_mask"]
444```

Common Issues

Padding token not set:

if tokenizer.pad_token is None:
    tokenizer.pad_token = tokenizer.eos_token

Sequence too long:

# Enable truncation
inputs = tokenizer(text, truncation=True, max_length=512)

Mismatched vocabulary:

# Always load tokenizer and model from same checkpoint
tokenizer = AutoTokenizer.from_pretrained("model-id")
model = AutoModel.from_pretrained("model-id")

Attention mask issues:

# Ensure attention_mask is passed
outputs = model(
    input_ids=inputs["input_ids"],
    attention_mask=inputs["attention_mask"]
)
Raw lines 416 to 444