› 01 · Tokens › SentencePiece
⚡ Visual Simulator
AI Journey · Understand Language

SentencePiece

Understand SentencePiece as a language-agnostic raw-text tokenization framework — why it eliminates whitespace pre-tokenization, how ▁ encodes word boundaries, and why it powers models across every language.

🟡 GOOD Framework, not a single algorithm Prerequisite: BPE 13 phases
🧙‍♂️ The Wise Scholar's Metaphor Universal Raw Tape
⏮️ 00 · Math & Foundations Hub →

SentencePiece: Reading Unbroken Multilingual Scrolls

Languages like Chinese or Japanese do not separate words with spaces. Instead of demanding a pre-splitter that breaks for non-English texts, SentencePiece treats all human writing as a continuous uninterrupted stream of raw symbols, turning spaces into an explicit symbol (_ or ). The scholar can read any language in the universe without needing an English-centric whitespace cutter first.

01

IntroductionWhat is SentencePiece?

SentencePiece is a tokenizer framework, not a single algorithm. Created by Google (Kudo & Richardson, 2018), it can run BPE or Unigram Language Model as its internal subword algorithm. The key innovation: it treats raw text as a stream of Unicode characters, requiring no language-specific pre-tokenization.

Core insight: SentencePiece takes raw text directly — no whitespace pre-tokenization needed. Spaces become the ▁ (U+2581) character embedded in piece strings, so word boundaries are preserved losslessly without ever splitting on whitespace first.

What SentencePiece is

  • A framework by Google (Kudo & Richardson, 2018)
  • Wraps BPE or Unigram as the internal algorithm
  • Produces .model + .vocab files
  • Handles training and inference end-to-end

What makes it different

  • Treats the entire text as a Unicode character stream
  • No whitespace pre-tokenization step
  • Works identically for any language or script
  • Uses ▁ (U+2581) to encode word boundaries internally
raw text (any language)→ SentencePiece→ subword pieces→ IDs
Memory cue: SentencePiece = "a container that runs BPE or Unigram on raw Unicode, no whitespace assumptions."
02

WhyThe problem SentencePiece solves

Standard BPE and WordPiece rely on pre-tokenization — splitting text on whitespace before learning subwords. This creates fundamental problems:

  • Language coverage: Chinese, Japanese, Thai, and many other languages have no whitespace between words. A whitespace split produces single characters or meaningless units.
  • Reproducibility: different platforms may handle whitespace and Unicode normalization differently. SentencePiece guarantees byte-identical output everywhere given the same .model file.
  • Pipeline complexity: every pre-tokenization choice (split on spaces? on punctuation? strip accents?) is a potential source of inconsistency. SentencePiece removes all those choices.

Whitespace pre-tokenization problem

"hello world" → ["hello", "world"] (fine for English)
"世界" → ["世界"] as one giant token (wrong for subword learning)
Thai / Arabic text → one unsplit chunk — subword learning fails

SentencePiece: language-agnostic solution

Treats everything as a Unicode stream. The ▁ marker is inserted at positions where a space would have been, so word boundary information is preserved without depending on actual whitespace characters.

03

IntuitionStarting from the whole vegetable

Analogy: Standard BPE is like a recipe that says "first, chop the onions" — it assumes you have pre-prepped, whitespace-separated words before it starts. SentencePiece starts from the whole vegetable — raw text — and does all the chopping itself.

The ▁ character (a small underline, U+2581) is the key. SentencePiece replaces every whitespace with ▁ and attaches it to the beginning of the following piece. This way:

  • The raw text can be reconstructed exactly from pieces by replacing ▁ with a space.
  • Word boundaries are encoded within the piece stream, not by the structure of the input.
  • For languages without spaces (Chinese, Thai…), ▁ simply doesn't appear — the algorithm still works identically.
Standard BPE workflow:
  raw text → [SPLIT on whitespace] → words → BPE merge → pieces

SentencePiece workflow:
  raw text → [replace spaces with ▁] → character stream → BPE/Unigram → pieces

"Hello world" (SP):
  spaces become ▁ → "▁Hello▁world" → ["▁Hello", "▁world"]

"世界" (SP, no spaces):
  no ▁ injected → "世界" → ["▁世界"] or ["▁世", "界"] depending on vocab
Key insight: The ▁ prefix is how SentencePiece says "this piece starts a new word." It is a word-start marker embedded in the piece string itself — not a separate token.
04

TheoryBPE mode vs Unigram mode

A. SentencePiece + BPE mode

  • Same merge-based vocabulary learning as standard BPE, but applied to the raw Unicode character stream (with ▁ inserted for spaces).
  • Deterministic: given the same corpus and settings, training always produces the same vocabulary and the same tokenization.
  • Used by: LLaMA (v1/v2), mBART.

B. SentencePiece + Unigram Language Model mode

  • Instead of greedily merging pairs, Unigram starts with a large vocabulary and prunes it by removing pieces whose removal decreases corpus log-likelihood the least (top-down).
  • Assigns a probability to each tokenization; picks the most likely one at inference via Viterbi search.
  • Can sample multiple tokenizations during training as a regularization technique (subword regularization).
  • Used by: T5, mT5, ALBERT.
Input "Hello world"
SP internal representation: "▁Hello▁world"
Pieces: ["▁Hello", "▁world"]
Input "It's a test."
SP representation: "▁It's▁a▁test."
Pieces: ["▁It", "'", "s", "▁a", "▁test", "."]
Decode Join pieces → replace ▁ with space → strip leading space → "It's a test." ✓
Important: The ▁ is part of the piece string, not a special separate token. "▁Hello" is a single vocabulary entry — one ID — just like "hello" would be.
05

How It WorksTraining and inference pipeline

SentencePiece manages the full pipeline internally. You provide a raw text corpus and a config; it handles everything from space encoding to vocabulary output.

Training

Config (CLI / Python API)
# Training config (SentencePiece CLI or Python API)
model_type         = "bpe"     # or "unigram"
vocab_size         = 32000     # target vocabulary size
character_coverage = 0.9995   # fraction of unique chars to cover
                               # lower → more byte-fallback for rare chars
input              = "corpus.txt"   # raw text, any language
model_prefix       = "mymodel"     # produces mymodel.model + mymodel.vocab

# Output files:
#   mymodel.model  — binary protobuf (portable, platform-independent)
#   mymodel.vocab  — human-readable vocabulary with log-probabilities

Inference (single-pass)

raw_text→ load .model→ replace spaces → ▁→ BPE / Unigram→ pieces + IDs
Portability: The .model file is a binary Protocol Buffer. Load it in Python, C++, Java, or any other language — output is always byte-identical regardless of platform.
06

ExampleTokenizing mixed and cross-script text

Concrete piece outputs across three example inputs, with ▁ markers highlighted:

SentencePiece output
Example 1 — basic English
  Input:  "hello world"
  Pieces: ["▁hello", "▁world"]   ← ▁ on every word-start piece
  IDs:    [12345,    6789]        ← example IDs only

Example 2 — mixed script (no failure, no [UNK])
  Input:  "hello世界"
  Pieces: ["▁hello", "世界"]

Example 3 — punctuation and contractions
  Input:  "It's a test."
  Pieces: ["▁It", "'", "s", "▁a", "▁test", "."]
  # ▁ only on pieces that start a new word

Example 4 — reconstructing original text
  Pieces: ["▁It", "'", "s", "▁a", "▁test", "."]
  → join:          "▁It's▁a▁test."
  → replace ▁→' ': " It's a test."
  → strip leading: "It's a test."  ✓
Watch out: The ▁ prefix means pieces cannot be naively concatenated with "".join(pieces). You must replace ▁ with a space (and strip the leading space) to reconstruct the original text correctly.
07

Visualize + InteractiveBPE pipeline vs SentencePiece pipeline

Standard BPE has an extra pre-tokenization step that SentencePiece eliminates entirely:

StepStandard BPESentencePiece
1Pre-tokenize: split on whitespace / punctuationReplace spaces with ▁ inline — no split
2Apply BPE merges to each pre-tokenized word independentlyApply BPE or Unigram to the full character stream
3Mark continuation pieces (e.g. ## prefix or suffix marker)Word-start pieces carry ▁ prefix — rest have none
4Map pieces to IDsMap pieces to IDs
Language agnostic?❌ — pre-tokenizer is language-specific✅ — same logic for every Unicode script
graph LR
    A["Raw text: 'Hello world'"] -->|replace spaces with ▁| B["▁Hello▁world"]
    B -->|BPE or Unigram| C["Pieces: ['▁Hello','▁world']"]
    C -->|join + ▁→space| D["Decoded: 'Hello world' ✓"]

    style A fill:#3b82f6,stroke:#1d4ed8,color:#fff
    style B fill:#f59e0b,stroke:#b45309,color:#fff
    style C fill:#8b5cf6,stroke:#6d28d9,color:#fff
    style D fill:#34d399,stroke:#047857,color:#fff
        
Fig 1. SentencePiece lossless round-trip: ▁ is a physical, reversible U+2581 character embedded in pieces.

Try the live SentencePiece-style simulation. Type any text and see how spaces become ▁ markers on the first piece of each word:

Simulation rules: spaces become ▁ on the first piece of each word; words longer than 8 chars are split into two pieces (▁ only on the first). The ▁ symbol is highlighted in amber.
08

Hands-onUsing SentencePiece via HuggingFace

T5 (and mT5, ALBERT) use SentencePiece under the hood. Load the tokenizer and observe the ▁ marker directly:

Python
from transformers import T5Tokenizer

tok = T5Tokenizer.from_pretrained("t5-small")

# Basic English
print(tok.tokenize("Hello world"))
# ['▁Hello', '▁world']

# Mixed script — no failure, no [UNK]
print(tok.tokenize("hello世界"))
# ['▁hello', '世', '界']

# Punctuation and contractions
print(tok.tokenize("It's a test."))
# ['▁It', "'", 's', '▁a', '▁test', '.']
#   ↑ only word-start pieces carry ▁

# Reconstruction — always use the tokenizer, never "".join()
pieces = tok.tokenize("Hello world")
print(tok.convert_tokens_to_string(pieces))
# 'Hello world'  ← ▁ → space, leading space stripped

Understanding the output

  • '▁Hello' — starts a new word (space before "Hello")
  • '▁world' — starts a new word (space before "world")
  • 's' after "'" — no ▁, it continues within a word segment

To decode back

Use tok.decode(ids) or tok.convert_tokens_to_string(pieces). Never do "".join(pieces) — you'll get raw ▁ characters embedded in the output string.

09

CompareBPE vs WordPiece vs SentencePiece

AspectBPEWordPieceSentencePiece
Algorithm type Merge-based (frequency) Merge-based (likelihood) Framework — BPE or Unigram inside
Pre-tokenization needed ✅ Yes — split on spaces first ✅ Yes — split on spaces first ❌ No — works on raw text directly
Whitespace handling Spaces discarded before BPE; continuation pieces marked implicitly (Ġ or nothing) Continuation pieces get ## prefix Spaces replaced by ▁ on word-start pieces
Language agnostic ❌ — pre-tokenizer is language-specific ❌ — pre-tokenizer is language-specific ✅ — same algorithm for any Unicode
▁ marker No (uses Ġ or nothing) No (uses ## on non-start pieces) Yes — ▁ on word-start pieces
Used by GPT-2, GPT-4, Falcon BERT, DistilBERT, ELECTRA T5, mT5, ALBERT, LLaMA (v1/v2), mBART
Note: LLaMA-3 switched from SentencePiece to tiktoken (BPE). Earlier LLaMA versions used SentencePiece. Always check the specific model card.
10

ApplyWhere SentencePiece is used and why

  • T5 and mT5: Google's text-to-text transfer transformer family. mT5 is trained on 101 languages — SentencePiece's language-agnostic tokenization is essential here.
  • ALBERT: Uses SentencePiece + Unigram with 30,000 vocabulary. The Unigram mode's probabilistic sampling is used for subword regularization during training.
  • LLaMA (v1 and v2): Meta's LLaMA uses SentencePiece + BPE with 32,000 vocabulary. The ▁ markers are visible if you inspect its tokenizer output.
  • mBART: Multilingual sequence-to-sequence model — SentencePiece ensures consistent tokenization across all 25 languages without 25 language-specific pre-tokenization rules.

Multilingual models

SentencePiece's language-agnostic approach is not just convenient — it is required for models that must handle dozens of languages uniformly.

Low-resource languages & character_coverage

The character_coverage parameter controls how many rare characters to include vs fall back to UTF-8 byte pieces. Set lower (e.g. 0.995) for more coverage of rare scripts via byte fallback.

Raw multilingual corpus→ SP trainer→ .model file→ Shared vocabulary→ Multilingual model
11

LimitationsWhat SentencePiece does not solve

Most common mistake: "This model uses SentencePiece, so it uses BPE." — SentencePiece is a framework. Always check the model card for model_type: bpe or model_type: unigram.
  • SentencePiece is NOT an algorithm. Saying "model X uses SentencePiece" doesn't tell you what subword algorithm it uses. You need to check BPE vs Unigram mode explicitly.
  • ▁ means non-trivial reconstruction. Pieces cannot be concatenated with "".join(). Code that assumes simple joining will silently produce garbage output with ▁ characters embedded.
  • Byte-fallback surprises. When character_coverage < 1.0, rare characters are encoded as UTF-8 byte pieces (e.g. <0xE4>). These look like HTML entities but are byte fallbacks — they will confuse users who haven't encountered them.
  • Unigram mode is non-deterministic at training time. The pruning algorithm involves randomness. Two training runs on the same corpus may produce slightly different vocabularies. Fix the random seed for reproducibility.
  • Not interchangeable. A SentencePiece model trained for T5 cannot be used with BERT. Vocabularies, IDs, and normalization schemes are all different.

Wrong mental model

"SentencePiece uses BPE."

"Just join the pieces with ''.join()."

Correct understanding

SentencePiece is a framework. Check model_type for the actual algorithm. Always decode through the tokenizer API, not string joining.

12

ExplainFeynman Challenge

Whole Vegetable vs Pre-Chopped

Standard BPE is like a recipe that says "first, chop the onions" — it assumes you have pre-prepped, whitespace-separated words before it starts. If the ingredient is a whole, un-labelled vegetable (Chinese text with no spaces), the recipe fails immediately.

SentencePiece starts from the whole vegetable. It stamps every position where a space would be with a tiny ▁ mark, then reads the continuous raw stream and decides where to slice — entirely statistically, with no pre-chopping required.

Common misconceptions to test yourself on:

  • ❌ "SentencePiece is just BPE with a different name." — Wrong: it's a framework that can also run Unigram LM.
  • ❌ "The ▁ is a separate special token." — Wrong: ▁ is a character prefix inside the piece string. "▁Hello" is one vocabulary entry.
  • ❌ "You can ignore ▁ when decoding." — Wrong: ignoring it will silently fuse words together or embed ▁ characters in output.
  • ✅ "SentencePiece eliminates the pre-tokenization step by encoding whitespace as ▁ within pieces." — Correct.
10-second Feynman explanation: SentencePiece is a tokenization framework (not a new algorithm) that wraps BPE or Unigram and removes the whitespace pre-tokenization step entirely — replacing spaces with the ▁ marker inside the piece stream. This makes it work identically for any language, including those with no spaces at all.
13

BuildMini-Project + Summary

🔨 Mini-Project: SP Model Inspection & ▁ Decoder

  1. SP model inspection: Load any SentencePiece .model file with the sentencepiece Python library. Print the first 20 vocabulary entries and note which ones carry ▁.
  2. ▁ decoder: Write a function decode_sp_pieces(pieces) that joins pieces, replaces ▁ with a space, and strips any leading space. Validate it round-trips correctly on at least three inputs.
  3. Language-agnostic test: Run the T5 tokenizer on English, Chinese ("世界你好"), and Arabic ("مرحبا") text. Confirm ▁ appears only on word-start pieces (or not at all for scripts with no spaces). Confirm no [UNK] is produced.
  4. Byte-fallback bonus: Feed an emoji (e.g. 🐾) into the T5 tokenizer with character_coverage < 1.0. Inspect the resulting <0xXX> tokens and write code to decode them back to the original character.

📌 Summary — five things to remember

  • Framework, not algorithm: SentencePiece wraps BPE or Unigram — it is not a new tokenization algorithm in itself.
  • No pre-tokenization: treats raw Unicode text as a stream; no language-specific whitespace splitting required.
  • ▁ replaces whitespace: spaces become the ▁ (U+2581) prefix on word-start pieces, encoding word boundaries without splitting the input first.
  • BPE or Unigram inside: BPE mode is merge-based and deterministic; Unigram mode is probabilistic and supports subword regularization during training.
  • Used by multilingual models: T5, mT5, ALBERT, LLaMA (v1/v2), mBART — whenever cross-language consistency matters, SentencePiece is the standard choice.
This page 0:00
This session 0:00
Total (all pages) 0:00
Today 0:00
▶ Running
📊 View all study stats →
0:00 studying