dynamo-tokenizers
Efficient, versatile tokenization for LLM inference. Wraps HuggingFace and TikToken tokenizers (plus a FastTokenizer hybrid mode) behind a small encode/decode/sequence API designed for streaming detokenization.
Features
- Multiple backends. HuggingFace
tokenizers, OpenAItiktoken, and a FastTokenizer hybrid behind one trait. - Streaming-friendly.
Sequencetracks incremental token-id appends and emits text deltas without re-decoding the full prefix. - Prefix caching.
CachedTokenizerrecords prefix tokenizations at special-token boundaries; repeated prompts that share a system prefix re-encode only the trailing suffix, turning O(N) work into O(suffix_len). - Hash verification. Detect tokenizer drift across model versions.
Quick start
use HuggingFaceTokenizer;
use ;
// tokenizer.json downloaded from any HuggingFace model repo
let tokenizer = from_file
.expect;
let encoding = tokenizer.encode
.expect;
println!;
let decoded = tokenizer.decode
.expect;
assert_eq!;
Streaming detokenization with Sequence
use ;
use Arc;
let tokenizer = from;
let mut sequence = new;
sequence.append_text
.expect;
// As each new token id is produced by the engine, append it
// and get back just the incremental text delta:
let delta = sequence.append_token_id
.expect;
Prefix caching with CachedTokenizer
Multi-turn chat workloads re-tokenize a large shared prefix (system prompt +
prior turns) on every request. CachedTokenizer wraps any tokenizer and caches
prefix tokenizations at special-token boundaries (e.g. <|im_start|>,
<|im_end|>, <s>, </s>). On a hit it merges the cached prefix tokens with a
fresh encode of the trailing suffix only.
Boundaries are taken only immediately after a registered special token —
those are atomic in BPE, so the merge is exact:
encode(prefix) + encode(suffix) == encode(prefix + suffix). There is no
whitespace/punctuation fallback; the cache prefers a miss over a corrupt split.
use ;
use ;
use Arc;
let hf = from_file
.expect;
let inner: = new;
// The atomic special tokens the model uses as turn delimiters.
// An empty list disables caching: encode/encode_batch pass straight through.
let specials = vec!;
let cached = new; // 256 MiB budget
let encoding = cached.encode
.expect;
let stats = cached.cache_stats;
println!;
TikToken models expose the exact special-token strings registered with their BPE, so the same cache can be constructed without duplicating model metadata:
use ;
use Tokenizer;
use Arc;
let tiktoken = from_file_auto
.expect;
let specials = tiktoken.special_tokens.to_vec;
let inner: = new;
let cached = new;
Entries are evicted by approximate LRU once max_memory_bytes is exceeded. The
cache lives as long as the CachedTokenizer instance. Use .with_observer(...)
to push request-level hit/miss events into your metrics. Use
.with_token_observer(...) to receive exact cached and uncached token counts
after each successful encode while L1 is active. Partial hits report both
categories, so consumers can increment cached_tokens_total and
uncached_tokens_total counters and derive a token-level reuse ratio.