morpheme
Fast, pure-Rust subword tokenization, compatible with Hugging Face tokenizers.
morpheme loads, runs, trains and saves tokenizers in the Hugging Face
tokenizer.json format — BPE, WordPiece, WordLevel and Unigram — and
matches the reference implementation on the supported configurations and
pinned real-model tests. Deliberate edge-case corrections and unsupported
forms are documented in the compatibility guide.
- Compatible — reads and writes
tokenizer.json; files trained with morpheme load in Pythontokenizersand encode identically, and vice versa. - Verified — every release is checked against 11 real, pinned tokenizers (BERT, GPT-2, RoBERTa, GPT-NeoX, Qwen2.5, Llama, T5, ALBERT, XLM-R, …) across tricky Unicode inputs.
- Pure Rust — no FFI, no C/C++ dependencies.
- Fast — faster than Python
tokenizersin our encode and training benchmarks (see benchmarks).
Status
v0.3.0 — correctness fixes from a full code review (no panics on loadable files, complete truncation overflow, hardened Hub cache), legacy JSON forms, and faster encoding. The library API may still change before 1.0.
The morpheme CLI:
# or a prebuilt binary (macOS, Linux, Windows):
|
On Windows: powershell -ExecutionPolicy Bypass -c "irm https://github.com/sourceblender/morpheme/releases/latest/download/morpheme-cli-installer.ps1 | iex".
Library
Load a supported tokenizer.json and encode:
use Tokenizer;
let tokenizer = from_file?;
let encoding = tokenizer.encode?;
assert_eq!;
assert_eq!;
assert_eq!; // byte offsets into the input
let pair = tokenizer.encode?;
println!; // [0, 0, 0, 0, 0, 0, 1, 1, 1]
let text = tokenizer.decode?;
assert_eq!;
With the hub feature, load straight from the Hugging Face Hub. Files
go to the standard Hugging Face cache (shared with Python) and
HF_TOKEN, HF_HOME, HF_ENDPOINT and HF_HUB_OFFLINE work as usual:
use ;
let tokenizer = from_pretrained?;
let pinned = from_pretrained?;
encode returns byte offsets; encode_char_offsets returns char
offsets like the Python API. encode_batch encodes in parallel and
applies the file's padding/truncation settings.
Train a GPT-2-style byte-level BPE tokenizer:
use Bpe;
use ByteLevel;
use BpeTrainer;
use ;
let mut tokenizer = new
.with_pre_tokenizer
.with_decoder;
let trainer = builder
.vocab_size
.initial_alphabet
.special_tokens
.build?;
tokenizer.train_from_files?;
tokenizer.save?;
let ids = tokenizer.encode?.ids.to_vec;
assert_eq!;
CLI
# Train (presets: byte-level for bpe, bert for wordpiece,
# sentencepiece for unigram, whitespace for wordlevel)
# Budget raw text without configured padding or truncation
# Process bounded JSONL batches with one tokenizer load
# Any Hugging Face Hub model id works in place of a path (cached locally)
Every command uses the full pipeline stored in the file; --help on
any command lists its options.
See CLI automation for JSONL schemas, counting semantics,
size limits, and streaming error behavior.
What's supported
| Component | Types (Hugging Face type names) |
|---|---|
| Models | BPE (incl. byte_fallback, dropout, prefixes/suffixes), WordPiece, WordLevel, Unigram |
| Normalizers | BertNormalizer, NFC, NFD, NFKC, NFKD, Lowercase, Strip, StripAccents, Replace, Prepend, Precompiled (SentencePiece), Nmt, ByteLevel, Sequence |
| Pre-tokenizers | ByteLevel, BertPreTokenizer, Whitespace, WhitespaceSplit, Metaspace, Split (regex, incl. look-around), Punctuation, Digits, CharDelimiterSplit, UnicodeScripts, FixedLength, Sequence |
| Post-processors | TemplateProcessing, BertProcessing, RobertaProcessing, ByteLevel, Sequence |
| Decoders | ByteLevel, WordPiece, Metaspace, BPEDecoder, ByteFallback, Fuse, Strip, Replace, CTC, Sequence |
| Trainers | BpeTrainer (output identical to HF), WordPieceTrainer, WordLevelTrainer, UnigramTrainer |
| Tokenizer | added/special tokens, pairs, pre-tokenized input, truncation (with stride/overflow), padding, batch encode/decode, streaming decode |
Known differences from Hugging Face are listed in
docs/interop.md.
How it's tested
tests/hf_golden.rs— 11 real tokenizers pinned by revision (scripts/hf-fixtures.txt); ids, tokens, offsets, masks, word ids, decoding, pairs, batches and the serialized JSON must match outputs recorded fromtokenizers0.23.2 (scripts/gen_golden.py).scripts/check_python_interop.py— the reverse direction: morpheme-trained files loaded by Python.- Property tests (lossless byte-level round-trips, valid offsets), per-component ground-truth tests, and regression tests for past bugs.
Project layout
morpheme/
├── crates/morpheme/ # the library
├── apps/morpheme-cli/ # the `morpheme` binary
├── docs/ # design and module documentation
├── examples/ # sample corpus and trained tokenizers
└── scripts/ # fixture download, golden generation, interop check
Documentation
docs/architecture.md— design and pipeline.docs/modules/— per-component reference.docs/interop.md— format compatibility and known differences.docs/benchmarks.md— performance and methodology.docs/document-workflow.md— executable dataset preparation with exact budgets and atomic publication.docs/roadmap.md— what's next.CONTRIBUTING.md,CHANGELOG.md.
Acknowledgements
morpheme's file format and component semantics follow Hugging Face
tokenizers (Apache-2.0),
which served as the behavioral reference.
License
MIT © 2026 The morpheme authors.