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.
It ships as a Rust library, a command-line tool, a Python package and a
WebAssembly (WASM) module for the browser.
- Compatible — reads and writes
tokenizer.json; files trained with morpheme load in Pythontokenizersand encode identically, and vice versa. - Verified — CI checks every code change 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; the default build has no C/C++ dependencies
(the optional
hubfeature uses rustls, whoseringbackend includes C and assembly). - Fast — faster than Python
tokenizersin our encode and training benchmarks (see benchmarks).
Status: v0.5.0. The library API may still change before 1.0; see the changelog.
Install
| Channel | Install |
|---|---|
| Rust library | cargo add morpheme (add --features hub to download from the Hugging Face Hub) |
| CLI | cargo install morpheme-cli, or a prebuilt binary (below) |
| Python (≥ 3.9) | pip install morpheme |
| WASM | build from source with wasm-pack (bindings/wasm); not published to npm |
Prebuilt CLI binaries (macOS on Apple silicon, Linux, Windows; Intel
Macs: cargo install morpheme-cli), via the installer scripts attached
to each GitHub Release:
# macOS on Apple silicon, and Linux
|
# Windows
powershell -ExecutionPolicy Bypass -c "irm https://github.com/sourceblender/morpheme/releases/latest/download/morpheme-cli-installer.ps1 | iex"
Supported platforms
| Channel | Prebuilt artifacts | Elsewhere |
|---|---|---|
| Rust library | — (source crate on crates.io) | any target with Rust 1.85+, including wasm32-unknown-unknown |
| CLI | Linux x86-64 (glibc and musl) and arm64 (glibc); macOS arm64; Windows x86-64 | cargo install morpheme-cli (Intel macOS included) |
| Python | abi3 wheels for CPython ≥ 3.9: Linux x86-64 and aarch64 (manylinux), macOS arm64, Windows x64 | the sdist builds with a Rust toolchain (Intel macOS included) |
| WASM | — | wasm-pack build in bindings/wasm |
Quick start
Rust
Load a 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!;
encode returns byte offsets; encode_char_offsets returns char
offsets like the Python API. encode_batch applies the file's
padding/truncation settings and runs in parallel with the default
parallel feature.
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?;
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!;
Runtime-only model settings — Unigram subword-regularization sampling
and BPE dropout — are changed in place through Tokenizer::model_mut;
see Unigram
and BPE.
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.
Python
=
# or: morpheme.Tokenizer.from_file("tokenizer.json")
=
# ['[CLS]', 'hello', ',', 'world', '!', '[SEP]']
# character spans, like Python `tokenizers`
# hello, world!
The Python API is deliberately small (load, encode, decode, count,
vocabulary lookups, save); see bindings/python.
WebAssembly
bindings/wasm wraps the library for the
browser with wasm-bindgen. After wasm-pack build --target web:
import init from "./pkg/morpheme_wasm.js";
await ;
const json = await .;
const tok = ;
tok.; // 6 with bert-base-uncased
Cargo features
| Feature | Default | Enables |
|---|---|---|
progressbar |
yes | Trainer progress bars on stderr (indicatif) |
parallel |
yes | rayon for encode_batch, decode_batch, batch padding and the trainers; without it they run sequentially |
hub |
no | Tokenizer::from_pretrained (native targets only; a no-op on wasm32) |
The CLI enables hub by default. The library compiles for
wasm32-unknown-unknown with any feature set; Tokenizer::save is
compiled out there (use to_json).
What's supported
| Component | Types (Hugging Face type names) |
|---|---|
| Models | BPE (incl. byte_fallback, dropout, prefixes/suffixes), WordPiece, WordLevel, Unigram (incl. subword-regularization sampling) |
| 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 Hugging Face), WordPieceTrainer, WordLevelTrainer, UnigramTrainer |
| Tokenizer | added/special tokens, pairs, pre-tokenized input, truncation (with stride/overflow), padding, batch encode/decode, streaming decode |
Legacy tokenizer.json forms written by older tokenizers versions
load too. Known differences from Hugging Face are listed in
docs/interop.md.
How it's tested
crates/morpheme/tests/hf_golden.rs— 11 real tokenizers pinned by revision (scripts/hf-fixtures.txt); ids, tokens, offsets, masks, word ids, decoding, streaming decode, 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, regression tests for past bugs,
cargo-fuzztargets, and tests for the Python and WASM bindings.
The full local gate, including the Python and WASM bindings, is in
docs/contributing.md.
Performance
Encoding is 1.2–1.7× faster than Python tokenizers 0.23.2 on the same
files and inputs, and training 1.5–1.8× faster; see
docs/benchmarks.md for the numbers, caveats and
methodology. Regressions are tracked daily on a dedicated benchmark host.
Project layout
morpheme/
├── crates/morpheme/ # the library
├── apps/morpheme-cli/ # the `morpheme` binary
├── bindings/python/ # the `morpheme` Python package (PyO3 + maturin)
├── bindings/wasm/ # `morpheme-wasm` browser bindings (wasm-bindgen)
├── fuzz/ # cargo-fuzz targets (separate nightly workspace)
├── docs/ # design, module and operations documentation
├── examples/ # sample corpus and trained tokenizers
└── scripts/ # fixtures, golden generation, interop, benchmarks, release smoke
Documentation
- API reference on docs.rs.
docs/architecture.md— design, crate layout and pipeline.docs/modules/— per-component reference.docs/interop.md— format compatibility and known differences.docs/cli.md— CLI automation: counting, JSONL batches, inspection.docs/document-workflow.md— executable dataset preparation with exact budgets and atomic publication.docs/benchmarks.md— performance and methodology.docs/decisions/— architecture decision records.docs/roadmap.md— what's done and what's next.CONTRIBUTING.md,CHANGELOG.md,SECURITY.md,SUPPORT.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.