Skip to content

feat(bindings): Python bindings rework, plugging PipelineTokenizer#2229

Draft
SBrandeis wants to merge 19 commits into
feat/train_encode_splitfrom
feat/pipeline-python-api
Draft

feat(bindings): Python bindings rework, plugging PipelineTokenizer#2229
SBrandeis wants to merge 19 commits into
feat/train_encode_splitfrom
feat/pipeline-python-api

Conversation

@SBrandeis

@SBrandeis SBrandeis commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

TL;DR

Rewrite the Python bindings on PipelineTokenizer (tokenizers v1.0)

This is a big diff because it swaps one implementation for another: ~26k lines of the
old bindings go, ~6k come in.

Intent

  • Smaller and faster binding surface / code
  • Best-effort feature parity
  • Python wrapper should not impair performance

What changed

  • New encode path. Encoding runs in Rust with the GIL released, batches run
    multi-threaded, inputs are borrowed (not copied), and ids come back as
    numpy.uint32 with no copy.
  • encode / encode_batchEncoding / EncodingBatch for compatibility with the ecosystem (with the transformers lib, notably). Misses a lot of features atm
  • encode_ids / encode_batch_ids -> numpy.ndarray: fast path when you just want the id array. Same encode work either way.
  • Training kept: BPE / WordPiece / WordLevel / Unigram trainers, plus parity-aware
    BPE. Components (normalizer/pre-tokenizer/model) are plain values you assign.
  • async and free-threaded Python (3.14t)
  • Tooling:
    • type stubs generated (+ CI validated)
    • add a benchmark to compare released vs new bindings perf
  • Anything we can't do yet raises a clear error: word_ids, offsets, decode, and post-processing (special-token insertion)...

TODO

  • Padding & truncation — makes attention_mask.
  • word_ids — small core change to track each token's source word.
  • Post-processing[CLS]/[SEP]/<s> inserype_ids` and pair inputs.
  • decode — ids back to text.
  • offsets — character span per token (deliberat).
  • golden tests to assert drop-in compatibility with transformers

PipelineTokenizer benchmark

7 / 8 models supported — PipelineTokenizer vs tokenizers v0.23.1 (latest release) · ~10 kB inputs · single thread + 1/2/4/8/max-thread sweep

d546c7d52 · 2026-07-22 10:49 UTC · Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz · 48 cores

Per-model encode throughput vs latest release

vs base branch (575582072) — per-model geomean ×speedup of this PR's PipelineTokenizer against the base branch's; regressions in red.

Per-model encode throughput vs base branch

Per-model memory footprint

Minimal encode binary size

bert-base-uncased — normalizer-heavy WordPiece · ×4.90 vs v0.23.1 · ×1.00 vs base bert-base-uncased speedup bert-base-uncased stage decomposition bert-base-uncased thread scaling

Memory (RSS MB, load+encode): v0.23.1 12+1 (peak 12) · Pipeline 8+0 (peak 17)

Fixture Group v0.23.1 MB/s Pipeline MB/s Speedup Δ base added-token normalize pre-tokenize model Ids
amh_Ethi lang 7.9 27.5 ×3.48 ×1.00 3% (1.2) 76% (27.6) 13% (4.7) 7% (2.6) match
arb_Arab lang 4.2 24.9 ×5.88 ×1.00 3% (1.2) 69% (27.5) 9% (3.4) 20% (7.8) match
ben_Beng lang 5.9 34.8 ×5.87 ×1.00 4% (1.2) 68% (19.4) 9% (2.6) 18% (5.3) match
cmn_Hani lang 3.9 18.6 ×4.79 ×0.99 2% (1.3) 71% (37.7) 10% (5.3) 16% (8.6) match
ell_Grek lang 3.8 23.5 ×6.17 ×0.99 3% (1.2) 68% (28.6) 8% (3.4) 21% (8.6) match
eng_Latn lang 4.5 18.2 ×4.07 ×1.00 5% (2.7) 71% (38.8) 8% (4.4) 16% (8.6) match
heb_Hebr lang 4.2 19.9 ×4.70 ×1.00 2% (1.2) 75% (37.7) 7% (3.6) 15% (7.6) match
hin_Deva lang 6.5 27.6 ×4.27 ×1.01 3% (1.2) 75% (27.3) 8% (3.0) 13% (4.8) match
jpn_Jpan lang 4.3 27.3 ×6.36 ×1.00 3% (1.2) 64% (23.4) 13% (4.7) 20% (7.4) match
kat_Geor lang 6.1 28.0 ×4.58 ×0.99 3% (1.2) 76% (26.6) 9% (3.2) 12% (4.2) match
kor_Hang lang 2.5 17.7 ×7.22 ×1.01 2% (1.2) 63% (35.3) 12% (7.0) 23% (12.9) match
rus_Cyrl lang 3.7 23.7 ×6.44 ×1.01 3% (1.2) 65% (27.4) 8% (3.2) 24% (10.1) match
tam_Taml lang 7.0 38.4 ×5.47 ×1.01 4% (1.2) 73% (18.8) 9% (2.2) 14% (3.6) match
tha_Thai lang 8.4 33.2 ×3.95 ×0.99 4% (1.2) 84% (25.1) 7% (2.2) 5% (1.5) match
added_normalized_dense modalities 6.7 19.7 ×2.93 ×1.00 3% (1.3) 82% (40.8) 13% (6.7) 2% (1.0) match
added_normalized_sparse modalities 5.3 18.3 ×3.45 ×1.00 4% (1.9) 75% (40.0) 13% (7.0) 9% (4.7) match
added_special_dense modalities 5.3 38.6 ×7.25 ×0.99 20% (5.1) 37% (9.1) 35% (8.8) 8% (1.9) match
added_special_sparse modalities 4.0 21.4 ×5.37 ×1.01 8% (3.8) 60% (27.6) 19% (8.8) 13% (5.8) match
agentic-traces modalities 3.9 18.0 ×4.64 ×1.01 5% (2.5) 70% (38.6) 9% (5.0) 17% (9.1) match
agentic_swe modalities 4.1 19.4 ×4.71 ×1.00 4% (2.0) 76% (38.7) 7% (3.7) 13% (6.9) match
code_mixed modalities 3.9 18.8 ×4.75 ×1.00 4% (2.3) 73% (38.5) 8% (4.3) 15% (7.7) match
math_latex modalities 4.1 18.0 ×4.42 ×1.00 5% (2.6) 70% (38.7) 9% (4.9) 16% (8.9) match
deepseek-v4 — deepseek 3-regex split-heavy byte-level BPE · ×4.02 vs v0.23.1 · ×1.03 vs base deepseek-v4 speedup deepseek-v4 stage decomposition deepseek-v4 thread scaling

Memory (RSS MB, load+encode): v0.23.1 62+0 (peak 67) · Pipeline 96+0 (peak 96)

Fixture Group v0.23.1 MB/s Pipeline MB/s Speedup Δ base added-token normalize pre-tokenize model Ids
amh_Ethi lang 4.4 33.9 ×7.68 ×1.01 2% (0.7) 0% (0.0) 17% (4.8) 81% (22.9) match
arb_Arab lang 4.3 16.9 ×3.91 ×1.00 1% (0.6) 0% (0.0) 6% (3.4) 93% (54.2) match
ben_Beng lang 6.6 18.5 ×2.82 ×1.01 1% (0.6) 0% (0.0) 6% (3.1) 93% (50.1) match
cmn_Hani lang 3.9 17.6 ×4.49 ×1.12 1% (0.8) 0% (0.0) 6% (3.2) 93% (53.2) match
ell_Grek lang 4.8 18.4 ×3.83 ×1.05 1% (0.6) 0% (0.0) 6% (3.4) 92% (49.2) match
eng_Latn lang 3.4 13.3 ×3.93 ×1.08 3% (2.1) 0% (0.0) 7% (5.2) 90% (67.0) match
heb_Hebr lang 4.2 13.0 ×3.12 ×1.02 1% (0.6) 0% (0.0) 5% (3.5) 95% (71.6) match
hin_Deva lang 6.2 22.0 ×3.55 ×1.02 1% (0.6) 0% (0.0) 7% (3.3) 91% (41.2) match
jpn_Jpan lang 4.5 18.5 ×4.13 ×1.02 1% (0.7) 0% (0.0) 6% (3.0) 93% (49.7) match
kat_Geor lang 6.3 17.8 ×2.85 ×1.00 1% (0.6) 0% (0.0) 5% (2.9) 94% (52.1) match
kor_Hang lang 3.9 20.2 ×5.20 ×1.03 1% (0.6) 0% (0.0) 7% (3.6) 91% (44.6) match
rus_Cyrl lang 4.6 14.7 ×3.18 ×1.03 1% (0.6) 0% (0.0) 5% (3.3) 94% (62.9) match
tam_Taml lang 6.7 17.5 ×2.63 ×0.99 1% (0.6) 0% (0.0) 5% (2.7) 94% (53.0) match
tha_Thai lang 7.3 15.1 ×2.07 ×1.03 1% (0.6) 0% (0.0) 3% (2.2) 96% (63.5) match
added_normalized_dense modalities 6.2 23.3 ×3.78 ×1.00 2% (0.8) 0% (0.0) 7% (2.7) 92% (38.2) match
added_normalized_sparse modalities 5.5 19.5 ×3.52 ×1.02 3% (1.3) 0% (0.0) 8% (3.8) 90% (44.9) match
added_special_dense modalities 3.7 36.4 ×9.73 ×1.04 24% (6.3) 2% (0.5) 24% (6.3) 51% (13.4) match
added_special_sparse modalities 4.1 20.3 ×4.98 ×1.04 8% (3.9) 0% (0.1) 14% (6.8) 77% (37.0) match
agentic-traces modalities 3.0 14.1 ×4.72 ×1.02 3% (1.9) 0% (0.0) 8% (5.5) 89% (61.9) match
agentic_swe modalities 3.1 15.0 ×4.85 ×1.02 2% (1.4) 0% (0.0) 6% (3.9) 92% (60.5) match
code_mixed modalities 3.6 15.3 ×4.29 ×1.01 3% (1.7) 0% (0.0) 7% (4.7) 90% (57.2) match
math_latex modalities 2.9 13.9 ×4.74 ×1.05 3% (2.0) 0% (0.0) 8% (5.4) 89% (63.0) match

Pre-tokenize: classify + fsm vs regex engines — ns/byte, lower better. The fsm is the scalar jump-table in both pipe columns; SIMD / scalar is the classify pass (regex pre-tokenizers have no SIMD fsm). ×vs = engine ÷ our pipeline (SIMD / scalar classify); onig & pcre2 (JIT) are C, fancy is pure-Rust fancy-regex, logos is a compile-time DFA lexer (approximate grammar; n/a for deepseek).

Fixture classify SIMD classify scalar pipe (SIMD cls + fsm) pipe (scalar cls + fsm) onig fancy pcre2 logos ×vs onig ×vs fancy ×vs pcre2 ×vs logos
amh_Ethi 2.79 3.44 4.79 5.44 42.2 20.5 9.2 8.8× / 7.7× 4.3× / 3.8× 1.9× / 1.7×
arb_Arab 1.15 2.93 3.43 5.20 49.1 22.8 10.2 14.3× / 9.4× 6.7× / 4.4× 3.0× / 2.0×
ben_Beng 1.62 2.95 3.11 4.44 35.8 16.3 7.6 11.5× / 8.0× 5.2× / 3.7× 2.4× / 1.7×
cmn_Hani 1.12 2.24 3.19 4.31 60.7 34.7 14.4 19.0× / 14.1× 10.9× / 8.1× 4.5× / 3.3×
ell_Grek 0.58 2.99 3.40 5.81 47.2 21.3 9.5 13.9× / 8.1× 6.3× / 3.7× 2.8× / 1.6×
eng_Latn 0.09 1.45 5.20 6.56 66.8 39.1 16.7 12.8× / 10.2× 7.5× / 6.0× 3.2× / 2.5×
heb_Hebr 1.16 3.03 3.54 5.41 51.1 24.3 10.6 14.4× / 9.4× 6.9× / 4.5× 3.0× / 2.0×
hin_Deva 1.52 3.06 3.32 4.86 38.2 19.0 8.5 11.5× / 7.9× 5.7× / 3.9× 2.6× / 1.8×
jpn_Jpan 1.71 3.31 3.00 4.61 53.0 27.7 11.9 17.7× / 11.5× 9.2× / 6.0× 4.0× / 2.6×
kat_Geor 1.54 2.53 2.92 3.90 33.2 15.3 7.2 11.4× / 8.5× 5.2× / 3.9× 2.5× / 1.8×
kor_Hang 1.23 2.73 3.64 5.14 50.2 27.2 11.8 13.8× / 9.8× 7.5× / 5.3× 3.2× / 2.3×
rus_Cyrl 1.17 2.92 3.30 5.05 47.0 21.2 9.4 14.3× / 9.3× 6.4× / 4.2× 2.8× / 1.9×
tam_Taml 0.93 2.98 2.69 4.74 31.5 13.9 6.5 11.7× / 6.6× 5.2× / 2.9× 2.4× / 1.4×
tha_Thai 1.54 2.60 2.17 3.23 26.9 10.1 5.2 12.4× / 8.3× 4.7× / 3.1× 2.4× / 1.6×
added_normalized_dense 0.06 1.48 2.71 4.13 43.5 19.8 9.1 16.0× / 10.5× 7.3× / 4.8× 3.4× / 2.2×
added_normalized_sparse 0.06 1.77 3.76 5.47 49.5 26.1 11.4 13.2× / 9.1× 6.9× / 4.8× 3.0× / 2.1×
added_special_dense 0.06 1.77 6.27 7.98 176.7 99.8 38.1 28.2× / 22.1× 15.9× / 12.5× 6.1× / 4.8×
added_special_sparse 0.06 1.47 6.79 8.21 104.0 59.2 24.0 15.3× / 12.7× 8.7× / 7.2× 3.5× / 2.9×
agentic-traces 0.74 1.55 5.47 6.29 82.1 53.1 19.9 15.0× / 13.1× 9.7× / 8.5× 3.6× / 3.2×
agentic_swe 0.66 1.53 3.88 4.76 97.9 66.7 23.6 25.2× / 20.6× 17.2× / 14.0× 6.1× / 5.0×
code_mixed 0.06 1.54 4.72 6.20 75.2 55.2 18.4 15.9× / 12.1× 11.7× / 8.9× 3.9× / 3.0×
math_latex 0.72 1.71 5.45 6.44 79.9 48.5 19.4 14.7× / 12.4× 8.9× / 7.5× 3.6× / 3.0×
gpt2 — gpt2 ByteLevel regex · ×7.35 vs v0.23.1 · ×1.01 vs base gpt2 speedup gpt2 stage decomposition gpt2 thread scaling

Memory (RSS MB, load+encode): v0.23.1 25+2 (peak 27) · Pipeline 30+0 (peak 30)

Fixture Group v0.23.1 MB/s Pipeline MB/s Speedup Δ base added-token normalize pre-tokenize model Ids
amh_Ethi lang 4.2 49.5 ×11.67 ×1.05 3% (0.7) 0% (0.0) 19% (3.7) 77% (14.8) match
arb_Arab lang 4.2 26.1 ×6.28 ×1.00 2% (0.6) 0% (0.0) 6% (2.3) 92% (35.3) match
ben_Beng lang 3.2 46.0 ×14.32 ×1.00 3% (0.6) 0% (0.0) 14% (3.0) 83% (17.9) match
cmn_Hani lang 4.0 29.2 ×7.35 ×1.01 2% (0.6) 0% (0.0) 7% (2.3) 91% (30.3) match
ell_Grek lang 4.6 29.1 ×6.36 ×0.99 2% (0.6) 0% (0.0) 7% (2.2) 92% (30.8) match
eng_Latn lang 3.7 13.8 ×3.73 ×1.01 3% (2.1) 0% (0.0) 4% (3.1) 93% (65.2) match
heb_Hebr lang 4.2 28.6 ×6.86 ×0.97 2% (0.6) 0% (0.0) 7% (2.3) 92% (31.5) match
hin_Deva lang 3.4 38.5 ×11.43 ×0.99 2% (0.6) 0% (0.0) 12% (3.1) 86% (21.9) match
jpn_Jpan lang 4.7 22.6 ×4.78 ×1.01 1% (0.6) 0% (0.0) 5% (2.1) 94% (40.7) match
kat_Geor lang 4.9 73.1 ×14.84 ×1.06 5% (0.6) 0% (0.0) 16% (2.1) 79% (10.3) match
kor_Hang lang 3.5 42.0 ×11.85 ×0.95 3% (0.6) 0% (0.0) 11% (2.5) 87% (19.9) match
rus_Cyrl lang 4.4 26.6 ×6.05 ×0.96 2% (0.6) 0% (0.0) 6% (2.1) 93% (33.9) match
tam_Taml lang 2.9 65.2 ×22.37 ×1.00 4% (0.6) 0% (0.0) 18% (2.6) 78% (11.3) match
tha_Thai lang 3.8 37.6 ×9.94 ×1.04 2% (0.6) 0% (0.0) 10% (2.5) 88% (22.9) match
added_normalized_dense modalities 6.4 26.3 ×4.14 ×1.02 2% (0.7) 0% (0.0) 3% (1.1) 95% (35.0) match
added_normalized_sparse modalities 5.6 21.8 ×3.90 ×1.01 3% (1.3) 0% (0.0) 5% (2.0) 93% (41.1) match
added_special_dense modalities 4.4 47.1 ×10.59 ×1.02 24% (4.8) 1% (0.2) 20% (4.2) 55% (11.2) match
added_special_sparse modalities 4.5 23.6 ×5.21 ×1.02 8% (3.3) 0% (0.0) 12% (4.8) 80% (33.1) match
agentic-traces modalities 3.4 16.3 ×4.78 ×1.02 3% (1.9) 0% (0.0) 6% (3.6) 91% (55.6) match
agentic_swe modalities 3.6 24.5 ×6.73 ×1.02 3% (1.4) 0% (0.0) 6% (2.4) 91% (36.9) match
code_mixed modalities 3.8 20.4 ×5.44 ×1.02 3% (1.7) 0% (0.0) 6% (3.0) 90% (43.6) match
math_latex modalities 3.4 15.1 ×4.46 ×1.01 3% (2.1) 0% (0.0) 5% (3.4) 92% (60.9) match

Pre-tokenize: classify + fsm vs regex engines — ns/byte, lower better. The fsm is the scalar jump-table in both pipe columns; SIMD / scalar is the classify pass (regex pre-tokenizers have no SIMD fsm). ×vs = engine ÷ our pipeline (SIMD / scalar classify); onig & pcre2 (JIT) are C, fancy is pure-Rust fancy-regex, logos is a compile-time DFA lexer (approximate grammar; n/a for deepseek).

Fixture classify SIMD classify scalar pipe (SIMD cls + fsm) pipe (scalar cls + fsm) onig fancy pcre2 logos ×vs onig ×vs fancy ×vs pcre2 ×vs logos
amh_Ethi 2.78 3.42 3.69 4.33 27.9 21.3 5.7 4.8 7.6× / 6.5× 5.8× / 4.9× 1.5× / 1.3× 1.3× / 1.1×
arb_Arab 1.15 2.97 2.31 4.13 32.4 27.0 6.6 5.2 14.1× / 7.9× 11.7× / 6.5× 2.9× / 1.6× 2.2× / 1.3×
ben_Beng 1.61 2.92 3.01 4.32 67.5 57.2 13.6 4.0 22.4× / 15.6× 19.0× / 13.2× 4.5× / 3.1× 1.3× / 0.9×
cmn_Hani 1.12 2.21 2.31 3.40 26.3 21.6 5.8 2.4 11.4× / 7.7× 9.4× / 6.3× 2.5× / 1.7× 1.0× / 0.7×
ell_Grek 0.58 3.00 2.21 4.62 28.7 22.6 5.8 4.8 13.0× / 6.2× 10.2× / 4.9× 2.6× / 1.3× 2.2× / 1.0×
eng_Latn 0.11 1.46 3.10 4.46 46.0 43.3 11.7 3.9 14.8× / 10.3× 14.0× / 9.7× 3.8× / 2.6× 1.3× / 0.9×
heb_Hebr 1.14 3.04 2.31 4.21 32.3 26.5 6.7 3.1 14.0× / 7.7× 11.5× / 6.3× 2.9× / 1.6× 1.4× / 0.7×
hin_Deva 1.52 3.08 3.09 4.64 62.5 55.3 13.4 4.3 20.3× / 13.5× 17.9× / 11.9× 4.3× / 2.9× 1.4× / 0.9×
jpn_Jpan 1.69 3.39 2.12 3.82 23.4 18.0 4.9 3.8 11.0× / 6.1× 8.5× / 4.7× 2.3× / 1.3× 1.8× / 1.0×
kat_Geor 1.54 2.50 2.08 3.04 17.7 14.6 4.1 2.0 8.5× / 5.8× 7.0× / 4.8× 2.0× / 1.3× 1.0× / 0.7×
kor_Hang 1.22 2.70 2.49 3.97 32.1 28.7 7.4 3.7 12.9× / 8.1× 11.5× / 7.2× 3.0× / 1.9× 1.5× / 0.9×
rus_Cyrl 1.16 2.92 2.13 3.90 27.1 21.4 5.6 2.4 12.7× / 7.0× 10.0× / 5.5× 2.6× / 1.4× 1.1× / 0.6×
tam_Taml 0.93 2.93 2.65 4.65 70.1 60.0 14.1 3.8 26.5× / 15.1× 22.7× / 12.9× 5.3× / 3.0× 1.4× / 0.8×
tha_Thai 1.52 2.54 2.51 3.54 40.4 33.0 8.6 3.2 16.1× / 11.4× 13.2× / 9.3× 3.4× / 2.4× 1.3× / 0.9×
added_normalized_dense 0.06 1.48 1.12 2.54 24.1 23.5 6.2 2.0 21.5× / 9.5× 21.0× / 9.3× 5.6× / 2.5× 1.8× / 0.8×
added_normalized_sparse 0.06 1.47 2.01 3.43 31.9 31.4 8.4 2.7 15.9× / 9.3× 15.6× / 9.2× 4.1× / 2.4× 1.3× / 0.8×
added_special_dense 0.06 1.48 4.16 5.58 96.3 100.3 19.6 2.9 23.1× / 17.3× 24.1× / 18.0× 4.7× / 3.5× 0.7× / 0.5×
added_special_sparse 0.06 1.47 4.79 6.20 62.4 61.7 14.1 3.4 13.0× / 10.1× 12.9× / 9.9× 2.9× / 2.3× 0.7× / 0.6×
agentic-traces 0.75 1.51 3.61 4.37 63.3 61.8 14.9 4.8 17.5× / 14.5× 17.1× / 14.1× 4.1× / 3.4× 1.3× / 1.1×
agentic_swe 0.65 1.45 2.43 3.22 61.2 69.9 14.3 3.5 25.2× / 19.0× 28.8× / 21.7× 5.9× / 4.4× 1.4× / 1.1×
code_mixed 0.06 1.50 3.01 4.44 60.4 69.1 14.8 4.1 20.1× / 13.6× 23.0× / 15.6× 4.9× / 3.3× 1.4× / 0.9×
math_latex 0.71 1.50 3.44 4.22 53.2 52.8 13.5 4.3 15.5× / 12.6× 15.4× / 12.5× 3.9× / 3.2× 1.2× / 1.0×
gpt-oss — o200k-regex byte-level BPE (gpt-oss) · ×7.65 vs v0.23.1 · ×1.02 vs base gpt-oss speedup gpt-oss stage decomposition gpt-oss thread scaling

Memory (RSS MB, load+encode): v0.23.1 4+11 (peak 16) · Pipeline 7+0 (peak 7)

Fixture Group v0.23.1 MB/s Pipeline MB/s Speedup Δ base added-token normalize pre-tokenize model Ids
amh_Ethi lang 3.9 62.6 ×16.14 ×1.01 4% (0.7) 0% (0.0) 31% (4.7) 65% (9.9) match
arb_Arab lang 4.3 25.6 ×5.96 ×1.00 2% (0.6) 0% (0.0) 8% (3.2) 90% (35.0) match
ben_Beng lang 5.7 28.5 ×5.02 ×1.05 2% (0.6) 0% (0.0) 10% (3.6) 88% (30.6) match
cmn_Hani lang 4.3 39.1 ×9.03 ×1.01 2% (0.6) 0% (0.0) 13% (3.3) 84% (21.0) match
ell_Grek lang 4.1 32.3 ×7.83 ×1.00 2% (0.6) 0% (0.0) 11% (3.2) 87% (26.7) match
eng_Latn lang 3.3 21.3 ×6.54 ×1.01 5% (2.1) 0% (0.0) 10% (4.6) 86% (39.6) match
heb_Hebr lang 3.9 28.8 ×7.41 ×1.03 2% (0.6) 0% (0.0) 10% (3.3) 89% (30.6) match
hin_Deva lang 5.0 24.7 ×4.90 ×1.05 1% (0.6) 0% (0.0) 9% (3.7) 89% (35.8) match
jpn_Jpan lang 4.6 37.3 ×8.07 ×0.99 2% (0.6) 0% (0.0) 12% (3.0) 86% (22.4) match
kat_Geor lang 5.4 26.7 ×4.94 ×1.06 2% (0.6) 0% (0.0) 8% (2.8) 91% (33.5) match
kor_Hang lang 3.4 45.3 ×13.24 ×0.99 3% (0.6) 0% (0.0) 17% (3.6) 80% (17.1) match
rus_Cyrl lang 4.4 23.6 ×5.34 ×1.05 1% (0.6) 0% (0.0) 7% (3.1) 91% (38.2) match
tam_Taml lang 5.6 31.0 ×5.59 ×1.07 2% (0.6) 0% (0.0) 10% (3.2) 88% (27.7) match
tha_Thai lang 6.1 27.9 ×4.54 ×0.98 2% (0.6) 0% (0.0) 9% (3.2) 89% (31.6) match
added_normalized_dense modalities 4.3 46.6 ×10.89 ×1.01 4% (0.7) 0% (0.0) 11% (2.2) 86% (17.3) match
added_normalized_sparse modalities 3.9 36.3 ×9.31 ×1.00 5% (1.3) 0% (0.0) 12% (3.2) 83% (21.6) match
added_special_dense modalities 3.3 55.9 ×17.09 ×1.02 29% (5.0) 0% (0.0) 31% (5.3) 40% (7.0) match
added_special_sparse modalities 3.4 33.8 ×9.87 ×0.99 12% (3.3) 0% (0.0) 22% (6.1) 67% (18.9) match
agentic-traces modalities 3.1 22.7 ×7.39 ×1.01 4% (1.9) 0% (0.0) 12% (5.0) 84% (36.5) match
agentic_swe modalities 3.5 21.9 ×6.20 ×1.02 3% (1.4) 0% (0.0) 8% (3.8) 89% (39.8) match
code_mixed modalities 3.5 30.0 ×8.55 ×1.01 5% (1.7) 0% (0.0) 13% (4.4) 82% (26.9) match
math_latex modalities 3.2 22.5 ×7.00 ×1.01 5% (2.0) 0% (0.0) 11% (4.8) 84% (36.7) match

Pre-tokenize: classify + fsm vs regex engines — ns/byte, lower better. The fsm is the scalar jump-table in both pipe columns; SIMD / scalar is the classify pass (regex pre-tokenizers have no SIMD fsm). ×vs = engine ÷ our pipeline (SIMD / scalar classify); onig & pcre2 (JIT) are C, fancy is pure-Rust fancy-regex, logos is a compile-time DFA lexer (approximate grammar; n/a for deepseek).

Fixture classify SIMD classify scalar pipe (SIMD cls + fsm) pipe (scalar cls + fsm) onig fancy pcre2 logos ×vs onig ×vs fancy ×vs pcre2 ×vs logos
amh_Ethi 2.85 3.41 4.75 5.31 30.8 14.2 7.0 4.8 6.5× / 5.8× 3.0× / 2.7× 1.5× / 1.3× 1.0× / 0.9×
arb_Arab 1.15 2.96 3.24 5.06 34.6 16.2 7.5 5.1 10.7× / 6.8× 5.0× / 3.2× 2.3× / 1.5× 1.6× / 1.0×
ben_Beng 1.62 2.94 3.64 4.96 24.3 10.6 5.4 2.7 6.7× / 4.9× 2.9× / 2.1× 1.5× / 1.1× 0.7× / 0.5×
cmn_Hani 1.12 2.26 3.26 4.41 21.8 11.0 5.5 2.5 6.7× / 4.9× 3.4× / 2.5× 1.7× / 1.3× 0.8× / 0.6×
ell_Grek 0.58 3.02 3.22 5.66 30.4 14.8 7.0 5.1 9.4× / 5.4× 4.6× / 2.6× 2.2× / 1.2× 1.6× / 0.9×
eng_Latn 0.09 1.48 4.55 5.94 45.3 28.8 13.5 4.2 10.0× / 7.6× 6.3× / 4.9× 3.0× / 2.3× 0.9× / 0.7×
heb_Hebr 1.14 3.05 3.29 5.20 34.3 16.8 8.1 2.9 10.4× / 6.6× 5.1× / 3.2× 2.5× / 1.6× 0.9× / 0.6×
hin_Deva 1.51 3.10 3.74 5.33 26.4 12.7 6.4 3.1 7.1× / 5.0× 3.4× / 2.4× 1.7× / 1.2× 0.8× / 0.6×
jpn_Jpan 1.70 3.42 3.03 4.75 20.4 9.1 4.8 3.8 6.7× / 4.3× 3.0× / 1.9× 1.6× / 1.0× 1.3× / 0.8×
kat_Geor 1.54 2.54 2.82 3.82 19.0 10.1 4.7 2.0 6.7× / 5.0× 3.6× / 2.7× 1.7× / 1.2× 0.7× / 0.5×
kor_Hang 1.24 2.69 3.63 5.08 34.1 18.9 8.8 3.6 9.4× / 6.7× 5.2× / 3.7× 2.4× / 1.7× 1.0× / 0.7×
rus_Cyrl 1.16 2.92 3.10 4.86 30.4 14.8 6.7 4.9 9.8× / 6.3× 4.8× / 3.0× 2.2× / 1.4× 1.6× / 1.0×
tam_Taml 0.93 2.97 3.17 5.21 19.4 8.9 4.3 2.9 6.1× / 3.7× 2.8× / 1.7× 1.4× / 0.8× 0.9× / 0.6×
tha_Thai 1.52 2.62 3.19 4.29 13.2 5.8 2.8 2.2 4.2× / 3.1× 1.8× / 1.3× 0.9× / 0.6× 0.7× / 0.5×
added_normalized_dense 0.06 1.48 2.19 3.61 35.6 17.7 11.2 2.2 16.3× / 9.9× 8.1× / 4.9× 5.1× / 3.1× 1.0× / 0.6×
added_normalized_sparse 0.06 1.47 3.19 4.61 37.6 20.6 11.4 3.0 11.8× / 8.2× 6.4× / 4.5× 3.6× / 2.5× 0.9× / 0.6×
added_special_dense 0.06 1.47 5.25 6.67 89.1 66.3 23.9 3.3 17.0× / 13.4× 12.6× / 9.9× 4.6× / 3.6× 0.6× / 0.5×
added_special_sparse 0.06 1.47 6.07 7.48 60.1 40.6 16.6 3.7 9.9× / 8.0× 6.7× / 5.4× 2.7× / 2.2× 0.6× / 0.5×
agentic-traces 0.71 1.48 5.00 5.77 54.9 40.2 16.9 5.0 11.0× / 9.5× 8.0× / 7.0× 3.4× / 2.9× 1.0× / 0.9×
agentic_swe 0.65 1.47 3.76 4.58 55.8 48.0 16.8 3.6 14.9× / 12.2× 12.8× / 10.5× 4.5× / 3.7× 1.0× / 0.8×
code_mixed 0.06 1.45 4.38 5.76 55.0 45.6 16.7 4.3 12.6× / 9.5× 10.4× / 7.9× 3.8× / 2.9× 1.0× / 0.7×
math_latex 0.71 1.50 4.85 5.64 52.4 35.5 15.5 4.6 10.8× / 9.3× 7.3× / 6.3× 3.2× / 2.8× 0.9× / 0.8×
glm-5.2 — cl100k-variant regex byte-level BPE (glm-5.2) · ×13.35 vs v0.23.1 · ×1.02 vs base glm-5.2 speedup glm-5.2 stage decomposition glm-5.2 thread scaling

Memory (RSS MB, load+encode): v0.23.1 4+11 (peak 16) · Pipeline 6+0 (peak 6)

Fixture Group v0.23.1 MB/s Pipeline MB/s Speedup Δ base added-token normalize pre-tokenize model Ids
amh_Ethi lang 4.6 65.0 ×14.03 ×1.05 8% (1.2) 0% (0.0) 25% (3.8) 66% (9.8) match
arb_Arab lang 4.1 72.5 ×17.60 ×1.02 9% (1.2) 0% (0.0) 18% (2.3) 73% (9.4) match
ben_Beng lang 3.5 69.1 ×19.93 ×1.00 8% (1.2) 0% (0.0) 22% (3.1) 70% (9.8) match
cmn_Hani lang 4.6 67.2 ×14.67 ×0.98 8% (1.2) 0% (0.0) 17% (2.4) 75% (10.6) match
ell_Grek lang 3.9 70.5 ×17.99 ×0.96 9% (1.2) 0% (0.0) 16% (2.2) 75% (10.1) match
eng_Latn lang 3.4 22.7 ×6.62 ×1.00 6% (2.7) 0% (0.0) 7% (3.1) 87% (37.8) match
heb_Hebr lang 3.6 76.0 ×20.86 ×1.15 9% (1.2) 0% (0.0) 19% (2.3) 72% (8.9) match
hin_Deva lang 3.0 67.3 ×22.20 ×1.07 8% (1.2) 0% (0.0) 22% (3.2) 70% (10.1) match
jpn_Jpan lang 4.6 72.4 ×15.87 ×0.97 9% (1.2) 0% (0.0) 16% (2.1) 75% (9.8) match
kat_Geor lang 4.3 84.0 ×19.44 ×1.04 10% (1.2) 0% (0.0) 18% (2.1) 71% (8.0) match
kor_Hang lang 3.3 68.0 ×20.31 ×1.03 8% (1.2) 0% (0.0) 18% (2.5) 74% (10.3) match
rus_Cyrl lang 3.9 40.5 ×10.41 ×1.01 5% (1.2) 0% (0.0) 9% (2.1) 86% (20.7) match
tam_Taml lang 3.1 73.5 ×23.47 ×1.04 9% (1.2) 0% (0.0) 20% (2.7) 71% (9.4) match
tha_Thai lang 3.5 71.1 ×20.11 ×0.97 9% (1.2) 0% (0.0) 19% (2.5) 73% (9.9) match
added_normalized_dense modalities 4.4 47.2 ×10.67 ×1.03 6% (1.3) 0% (0.0) 5% (1.1) 88% (17.8) match
added_normalized_sparse modalities 4.0 40.5 ×10.23 ×1.06 8% (1.8) 0% (0.0) 8% (2.0) 84% (19.8) match
added_special_dense modalities 3.2 41.2 ×12.70 ×1.01 51% (11.9) 0% (0.0) 21% (5.0) 28% (6.5) match
added_special_sparse modalities 3.3 33.5 ×10.01 ×1.00 24% (6.6) 0% (0.1) 17% (4.7) 60% (16.8) match
agentic-traces modalities 3.0 23.6 ×7.81 ×1.00 6% (2.6) 0% (0.0) 9% (3.7) 85% (35.4) match
agentic_swe modalities 3.5 22.1 ×6.36 ×1.00 5% (2.0) 0% (0.0) 6% (2.9) 89% (39.6) match
code_mixed modalities 3.5 31.0 ×8.86 ×1.01 7% (2.3) 0% (0.0) 10% (3.2) 82% (25.9) match
math_latex modalities 3.1 23.8 ×7.68 ×1.00 6% (2.6) 0% (0.1) 9% (3.5) 85% (34.6) match

Pre-tokenize: classify + fsm vs regex engines — ns/byte, lower better. The fsm is the scalar jump-table in both pipe columns; SIMD / scalar is the classify pass (regex pre-tokenizers have no SIMD fsm). ×vs = engine ÷ our pipeline (SIMD / scalar classify); onig & pcre2 (JIT) are C, fancy is pure-Rust fancy-regex, logos is a compile-time DFA lexer (approximate grammar; n/a for deepseek).

Fixture classify SIMD classify scalar pipe (SIMD cls + fsm) pipe (scalar cls + fsm) onig fancy pcre2 logos ×vs onig ×vs fancy ×vs pcre2 ×vs logos
amh_Ethi 2.78 3.43 3.76 4.41 26.9 16.6 6.0 4.8 7.2× / 6.1× 4.4× / 3.8× 1.6× / 1.4× 1.3× / 1.1×
arb_Arab 1.15 3.01 2.30 4.16 30.5 19.2 6.7 5.1 13.3× / 7.3× 8.4× / 4.6× 2.9× / 1.6× 2.2× / 1.2×
ben_Beng 1.62 2.97 3.07 4.42 44.7 27.9 10.3 3.7 14.6× / 10.1× 9.1× / 6.3× 3.4× / 2.3× 1.2× / 0.8×
cmn_Hani 1.12 2.26 2.36 3.49 19.1 11.9 4.7 2.3 8.1× / 5.5× 5.0× / 3.4× 2.0× / 1.3× 1.0× / 0.7×
ell_Grek 0.58 2.99 2.19 4.59 27.9 17.4 6.1 4.8 12.7× / 6.1× 8.0× / 3.8× 2.8× / 1.3× 2.2× / 1.0×
eng_Latn 0.34 1.47 3.07 4.20 43.1 33.0 12.1 3.8 14.0× / 10.3× 10.7× / 7.9× 3.9× / 2.9× 1.2× / 0.9×
heb_Hebr 1.15 3.01 2.32 4.18 30.4 19.8 6.8 3.0 13.1× / 7.3× 8.5× / 4.7× 2.9× / 1.6× 1.3× / 0.7×
hin_Deva 1.52 3.09 3.16 4.73 47.2 30.8 11.3 4.0 15.0× / 10.0× 9.8× / 6.5× 3.6× / 2.4× 1.3× / 0.8×
jpn_Jpan 1.70 3.35 2.15 3.80 18.0 9.9 4.1 3.8 8.4× / 4.7× 4.6× / 2.6× 1.9× / 1.1× 1.8× / 1.0×
kat_Geor 1.74 2.59 2.08 2.93 16.9 11.5 4.2 2.0 8.1× / 5.8× 5.5× / 3.9× 2.0× / 1.4× 1.0× / 0.7×
kor_Hang 1.23 2.70 2.50 3.97 30.3 21.3 7.5 3.7 12.1× / 7.6× 8.5× / 5.4× 3.0× / 1.9× 1.5× / 0.9×
rus_Cyrl 1.17 2.96 2.13 3.91 26.2 16.7 5.8 2.5 12.3× / 6.7× 7.9× / 4.3× 2.7× / 1.5× 1.2× / 0.6×
tam_Taml 0.93 2.90 2.66 4.64 43.4 26.9 9.9 3.4 16.3× / 9.4× 10.1× / 5.8× 3.7× / 2.1× 1.3× / 0.7×
tha_Thai 1.53 2.54 2.54 3.55 27.9 16.6 6.8 3.0 11.0× / 7.9× 6.5× / 4.7× 2.7× / 1.9× 1.2× / 0.9×
added_normalized_dense 0.06 1.47 1.08 2.50 23.4 17.1 6.6 1.8 21.7× / 9.4× 15.9× / 6.9× 6.1× / 2.6× 1.7× / 0.7×
added_normalized_sparse 0.06 1.48 1.97 3.38 30.7 23.3 8.7 2.6 15.6× / 9.1× 11.9× / 6.9× 4.4× / 2.6× 1.3× / 0.8×
added_special_dense 0.06 1.47 5.02 6.43 93.5 73.2 21.6 3.1 18.6× / 14.5× 14.6× / 11.4× 4.3× / 3.4× 0.6× / 0.5×
added_special_sparse 0.06 1.47 4.68 6.10 59.8 45.2 15.3 3.4 12.8× / 9.8× 9.6× / 7.4× 3.3× / 2.5× 0.7× / 0.6×
agentic-traces 0.78 1.49 3.67 4.38 52.1 44.0 15.2 4.6 14.2× / 11.9× 12.0× / 10.1× 4.1× / 3.5× 1.3× / 1.0×
agentic_swe 0.66 1.49 2.87 3.71 54.7 51.1 15.5 3.4 19.0× / 14.8× 17.8× / 13.8× 5.4× / 4.2× 1.2× / 0.9×
code_mixed 0.07 1.46 3.19 4.58 52.0 50.0 15.0 4.0 16.3× / 11.4× 15.6× / 10.9× 4.7× / 3.3× 1.3× / 0.9×
math_latex 0.98 1.49 3.47 3.97 50.0 39.8 13.9 4.2 14.4× / 12.6× 11.5× / 10.0× 4.0× / 3.5× 1.2× / 1.0×
llama-2 — model-bounded BPE, no pre-tokenizer · ×3.26 vs v0.23.1 · ×1.02 vs base llama-2 speedup llama-2 stage decomposition llama-2 thread scaling

Memory (RSS MB, load+encode): v0.23.1 19+0 (peak 23) · Pipeline 22+0 (peak 21)

Fixture Group v0.23.1 MB/s Pipeline MB/s Speedup Δ base added-token normalize pre-tokenize model Ids
amh_Ethi lang 5.7 47.3 ×8.23 ×1.04 0% (0.0) 14% (2.8) 1% (0.1) 85% (16.8) match
arb_Arab lang 12.5 53.9 ×4.31 ×1.03 0% (0.0) 18% (3.3) 1% (0.1) 81% (14.4) match
ben_Beng lang 13.6 93.4 ×6.84 ×1.07 0% (0.0) 22% (2.2) 1% (0.1) 77% (7.8) match
cmn_Hani lang 11.4 70.3 ×6.15 ×1.04 0% (0.1) 4% (0.4) 0% (0.0) 96% (12.0) match
ell_Grek lang 13.0 62.5 ×4.81 ×1.05 0% (0.0) 21% (3.2) 1% (0.1) 78% (11.7) match
eng_Latn lang 4.4 6.3 ×1.43 ×1.03 0% (0.1) 5% (7.0) 0% (0.2) 95% (146.8) match
heb_Hebr lang 12.7 65.0 ×5.13 ×1.02 0% (0.0) 23% (3.4) 1% (0.1) 75% (10.9) match
hin_Deva lang 14.7 83.5 ×5.67 ×0.99 0% (0.0) 26% (2.9) 1% (0.1) 72% (8.0) match
jpn_Jpan lang 16.6 93.6 ×5.63 ×1.08 1% (0.1) 4% (0.4) 0% (0.0) 96% (9.4) match
kat_Geor lang 17.7 97.4 ×5.52 ×1.03 1% (0.1) 20% (1.9) 1% (0.1) 78% (7.4) match
kor_Hang lang 8.8 55.3 ×6.30 ×1.02 0% (0.1) 20% (3.3) 1% (0.1) 79% (13.3) match
rus_Cyrl lang 9.1 16.7 ×1.84 ×1.02 0% (0.0) 5% (2.9) 0% (0.1) 95% (55.7) match
tam_Taml lang 15.7 98.6 ×6.29 ×1.04 0% (0.0) 19% (1.8) 1% (0.1) 80% (7.6) match
tha_Thai lang 19.6 92.6 ×4.73 ×1.02 0% (0.0) 10% (1.0) 0% (0.0) 90% (8.9) match
added_normalized_dense modalities 6.0 8.5 ×1.43 ×0.98 0% (0.1) 3% (3.8) 0% (0.2) 96% (106.5) match
added_normalized_sparse modalities 5.1 7.0 ×1.38 ×0.93 0% (0.0) 5% (6.1) 0% (0.2) 95% (124.3) match
added_special_dense modalities 5.2 20.2 ×3.88 ×1.02 11% (5.1) 32% (15.2) 2% (1.1) 55% (26.2) match
added_special_sparse modalities 7.3 10.4 ×1.42 ×1.01 2% (2.1) 15% (13.6) 0% (0.2) 83% (77.2) match
agentic-traces modalities 4.7 7.1 ×1.49 ×0.99 0% (0.1) 5% (6.2) 0% (0.2) 95% (130.5) match
agentic_swe modalities 4.4 7.4 ×1.70 ×0.99 0% (0.0) 7% (9.9) 0% (0.3) 92% (122.6) match
code_mixed modalities 4.5 7.1 ×1.58 ×0.98 0% (0.0) 6% (8.1) 0% (0.2) 94% (127.7) match
math_latex modalities 4.7 6.7 ×1.44 ×1.01 0% (0.1) 4% (6.5) 0% (0.2) 95% (138.0) match
llama-3 — cl100k-regex byte-level BPE (llama-3), single regex · ×6.95 vs v0.23.1 · ×1.07 vs base llama-3 speedup llama-3 stage decomposition llama-3 thread scaling

Memory (RSS MB, load+encode): v0.23.1 143+0 (peak 199) · Pipeline 144+0 (peak 199)

Fixture Group v0.23.1 MB/s Pipeline MB/s Speedup Δ base added-token normalize pre-tokenize model Ids
amh_Ethi lang 4.5 52.2 ×11.58 ×1.02 4% (0.7) 0% (0.0) 21% (3.7) 75% (12.8) match
arb_Arab lang 4.6 18.7 ×4.08 ×1.07 1% (0.6) 0% (0.0) 4% (2.3) 94% (48.5) match
ben_Beng lang 4.2 32.8 ×7.81 ×1.04 2% (0.6) 0% (0.0) 10% (3.1) 88% (26.0) match
cmn_Hani lang 5.0 17.1 ×3.45 ×1.10 1% (0.6) 0% (0.0) 4% (2.3) 95% (51.1) match
ell_Grek lang 5.3 20.3 ×3.84 ×1.03 1% (0.6) 0% (0.0) 5% (2.2) 94% (44.7) match
eng_Latn lang 4.3 42.6 ×9.95 ×1.26 11% (2.1) 0% (0.0) 16% (3.1) 74% (14.4) match
heb_Hebr lang 4.3 27.8 ×6.46 ×1.02 2% (0.6) 0% (0.0) 7% (2.3) 92% (32.1) match
hin_Deva lang 4.3 78.6 ×18.17 ×1.04 5% (0.6) 0% (0.0) 28% (3.2) 67% (7.6) match
jpn_Jpan lang 6.0 17.1 ×2.87 ×1.08 1% (0.6) 0% (0.0) 4% (2.1) 95% (53.6) match
kat_Geor lang 5.8 39.0 ×6.76 ×0.98 2% (0.6) 0% (0.0) 8% (2.1) 89% (21.8) match
kor_Hang lang 4.2 19.8 ×4.68 ×1.10 1% (0.6) 0% (0.0) 5% (2.5) 94% (44.8) match
rus_Cyrl lang 5.2 17.1 ×3.32 ×1.08 1% (0.6) 0% (0.0) 4% (2.1) 95% (54.0) match
tam_Taml lang 4.1 36.4 ×8.85 ×1.03 2% (0.6) 0% (0.0) 10% (2.7) 88% (23.5) match
tha_Thai lang 5.3 21.5 ×4.06 ×1.06 1% (0.6) 0% (0.0) 6% (2.5) 93% (40.8) match
added_normalized_dense modalities 6.0 27.7 ×4.60 ×1.00 2% (0.7) 0% (0.0) 3% (1.1) 95% (33.4) match
added_normalized_sparse modalities 5.9 43.3 ×7.39 ×1.00 6% (1.3) 0% (0.0) 10% (2.1) 85% (18.8) match
added_special_dense modalities 4.5 74.8 ×16.75 ×1.08 39% (4.9) 1% (0.1) 39% (5.0) 21% (2.6) match
added_special_sparse modalities 4.6 69.7 ×15.06 ×1.00 25% (3.3) 0% (0.0) 38% (5.0) 37% (4.9) match
agentic-traces modalities 3.9 35.7 ×9.10 ×1.19 8% (1.9) 0% (0.0) 15% (3.7) 77% (19.0) match
agentic_swe modalities 4.3 28.1 ×6.47 ×1.11 4% (1.4) 0% (0.0) 9% (2.9) 87% (29.2) match
code_mixed modalities 4.1 45.6 ×11.01 ×1.12 9% (1.7) 0% (0.0) 17% (3.2) 75% (14.6) match
math_latex modalities 3.9 38.1 ×9.85 ×1.19 9% (2.1) 0% (0.0) 15% (3.5) 76% (17.5) match

Pre-tokenize: classify + fsm vs regex engines — ns/byte, lower better. The fsm is the scalar jump-table in both pipe columns; SIMD / scalar is the classify pass (regex pre-tokenizers have no SIMD fsm). ×vs = engine ÷ our pipeline (SIMD / scalar classify); onig & pcre2 (JIT) are C, fancy is pure-Rust fancy-regex, logos is a compile-time DFA lexer (approximate grammar; n/a for deepseek).

Fixture classify SIMD classify scalar pipe (SIMD cls + fsm) pipe (scalar cls + fsm) onig fancy pcre2 logos ×vs onig ×vs fancy ×vs pcre2 ×vs logos
amh_Ethi 2.79 3.43 3.69 4.33 27.3 16.6 6.1 4.8 7.4× / 6.3× 4.5× / 3.8× 1.7× / 1.4× 1.3× / 1.1×
arb_Arab 1.15 2.98 2.27 4.10 31.0 19.2 6.8 5.2 13.6× / 7.5× 8.4× / 4.7× 3.0× / 1.7× 2.3× / 1.3×
ben_Beng 1.62 2.98 3.06 4.42 45.4 29.2 10.4 3.7 14.8× / 10.2× 9.5× / 6.6× 3.4× / 2.3× 1.2× / 0.8×
cmn_Hani 1.12 2.23 2.34 3.45 19.3 12.0 4.7 2.4 8.3× / 5.6× 5.1× / 3.5× 2.0× / 1.4× 1.0× / 0.7×
ell_Grek 0.58 2.95 2.17 4.53 28.3 17.6 6.1 4.7 13.0× / 6.2× 8.1× / 3.9× 2.8× / 1.3× 2.2× / 1.0×
eng_Latn 0.11 1.45 3.09 4.43 44.5 34.1 12.3 3.8 14.4× / 10.0× 11.0× / 7.7× 4.0× / 2.8× 1.2× / 0.8×
heb_Hebr 1.14 3.04 2.29 4.19 31.0 20.1 6.9 3.1 13.6× / 7.4× 8.8× / 4.8× 3.0× / 1.7× 1.4× / 0.7×
hin_Deva 1.51 3.12 3.16 4.77 48.1 30.9 11.7 4.0 15.2× / 10.1× 9.8× / 6.5× 3.7× / 2.4× 1.3× / 0.8×
jpn_Jpan 1.69 3.35 2.13 3.79 18.1 10.0 4.1 3.7 8.5× / 4.8× 4.7× / 2.6× 1.9× / 1.1× 1.7× / 1.0×
kat_Geor 1.53 2.54 2.07 3.08 17.3 11.4 4.2 2.0 8.3× / 5.6× 5.5× / 3.7× 2.0× / 1.4× 1.0× / 0.7×
kor_Hang 1.23 2.72 2.49 3.98 31.0 21.6 7.6 3.7 12.5× / 7.8× 8.7× / 5.4× 3.1× / 1.9× 1.5× / 0.9×
rus_Cyrl 1.16 2.95 2.12 3.90 27.0 16.6 5.9 2.4 12.7× / 6.9× 7.9× / 4.3× 2.8× / 1.5× 1.1× / 0.6×
tam_Taml 0.93 2.95 2.66 4.68 44.5 28.5 10.0 3.4 16.7× / 9.5× 10.7× / 6.1× 3.8× / 2.1× 1.3× / 0.7×
tha_Thai 1.52 2.57 2.52 3.58 28.2 16.5 6.7 3.0 11.2× / 7.9× 6.5× / 4.6× 2.7× / 1.9× 1.2× / 0.8×
added_normalized_dense 0.06 1.47 1.06 2.47 24.0 17.5 6.7 1.8 22.7× / 9.7× 16.6× / 7.1× 6.3× / 2.7× 1.7× / 0.7×
added_normalized_sparse 0.06 1.48 2.11 3.53 31.6 22.9 8.7 2.5 15.0× / 9.0× 10.9× / 6.5× 4.1× / 2.5× 1.2× / 0.7×
added_special_dense 0.06 1.47 5.00 6.42 96.1 74.7 21.3 3.1 19.2× / 15.0× 14.9× / 11.6× 4.3× / 3.3× 0.6× / 0.5×
added_special_sparse 0.06 1.47 4.95 6.37 61.2 46.5 15.7 3.4 12.4× / 9.6× 9.4× / 7.3× 3.2× / 2.5× 0.7× / 0.5×
agentic-traces 0.74 1.58 3.73 4.57 53.5 46.1 14.9 4.6 14.4× / 11.7× 12.4× / 10.1× 4.0× / 3.3× 1.2× / 1.0×
agentic_swe 0.65 1.47 2.89 3.70 56.0 53.2 15.5 3.4 19.4× / 15.1× 18.4× / 14.4× 5.4× / 4.2× 1.2× / 0.9×
code_mixed 0.07 1.45 3.25 4.64 53.4 51.4 15.1 3.9 16.4× / 11.5× 15.8× / 11.1× 4.6× / 3.3× 1.2× / 0.8×
math_latex 0.71 1.48 3.48 4.26 51.4 40.6 14.1 4.1 14.7× / 12.1× 11.6× / 9.5× 4.1× / 3.3× 1.2× / 1.0×
Not yet supported: t5-base
t5-base not supported
### Python bindings — `tokenizers_pipeline` vs `tokenizers` 0.23.1 (PyPI)

Python bindings encode_batch speedup vs the released tokenizers wheel

numbers (MB/s)
model pipeline 1t release 1t speedup 1t pipeline mt release mt speedup mt
bert-base-uncased 18 3 5.18× 123 23 5.37×
deepseek-v4 15 3 4.83× 103 22 4.75×
gpt2 24 3 9.33× 164 17 9.75×
gpt-oss 25 4 6.92× 173 23 7.40×
glm-5.2 38 3 12.09× 269 18 15.08×
llama-2 18 7 2.50× 116 43 2.72×
llama-3 26 4 7.44× 171 23 7.43×
t5-base not supported

@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@SBrandeis
SBrandeis force-pushed the feat/pipeline-python-api branch from 711a49c to 4a17bff Compare July 23, 2026 13:27
SBrandeis and others added 3 commits July 23, 2026 15:48
* golden end-to-end tests through transformers v5

Same suite, two builds: `make golden-release` runs it on the tokenizers
wheel transformers resolves (always green, defines the target behavior);
`make golden` runs it on the in-tree build, where the failures enumerate
what the 1.0 rewrite is still missing. Four layers: the tokenizers API
driven directly, the transformers tokenizer API, inference (generate/
pipeline), and training (Trainer/collators).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* deepen golden tests with the transformers example recipes

Scenarios lifted from the maintained examples/pytorch/ scripts at
v5.14.1: run_qa's overflow/stride/sequence_ids/offsets span labeling,
run_ner's word_ids label alignment, run_mlm's special_tokens_mask +
masking collator, run_translation's text_target and seq2seq collator,
plus token-classification pipeline spans, encoder-decoder generate,
and the T5 Unigram+Metaspace archetype in the direct-API layer.
31 tests, all green on the release wheel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* golden production flows: chat serving, RAG, SFT

Story-shaped tests mirroring how production stacks drive the tokenizer:
chat serving (ChatML template + control tokens as added specials +
history truncation to a token budget + left-padded batch generate +
TextIteratorStreamer streaming == one-shot decode), RAG (token-budget
chunking via offsets with exact source spans + mean-pooled embeddings +
retrieval), and SFT (TRL-style completion-only masking, tokenizer
pickled through datasets.map(num_proc=2), Trainer steps). 34 tests
green on the release wheel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* golden conformance layer; rename the scenario suite to e2e

tests/golden now holds true golden-master tests: goldens/*.jsonl record
everything the released wheel (0.23.1) produces on the 8 bench-model
tokenizers — ids, tokens, offsets, masks, word ids, decodes and pair
encodings for fixture excerpts and edge-case strings, plus ids digests
over the fixture corpora. generate.py regenerates them from .release/
(never hand-edited, guarded); test_golden.py replays the inputs on the
current build, one test per output domain per model, so failures read
as a conformance matrix. Opt-in via TOKENIZERS_GOLDEN (make golden)
until the rewrite is green, then the gate should be dropped.

The transformers scenario suite moves to tests/e2e (make e2e /
e2e-release) — flows there, values here. CI: e2e-release and
golden-freshness (regen must reproduce the committed goldens byte for
byte) required; one informational in-tree job runs both.

First catch, dev build vs release on llama-2: identical ids but
tokens[0] renders as '▁<s>' instead of '<s>' — the Prepend normalizer
leaks into the inserted special token's string.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* add huggingface_hub to the dev venv

from_pretrained needs it (the wheel's optional hub extra), so the
network-marked pretrained test failed in a fresh venv — it only worked
after `make examples` pulled the dep in via datasets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* review pass: scope HF_TOKEN per step, unshadow offset loop var

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* iter Makefile

* fix tk-encode doctest: fence PipelinePostProcessor example as text

rustdoc compiles indented doc blocks as Rust doctests; the example is an
illustration, not compilable code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix Python lint under ruff 0.16 defaults; pin ruff in CI

ruff 0.16.0 widened the default rule set, breaking CI with no code
change: import sorting (I001), loop vars captured by bench lambdas
(B023), implicit string concat in lists (ISC004), open() without a
context manager (SIM115), zip-for-pairwise (RUF007), and a blind
pytest.raises(Exception) (B017). Pin the CI ruff so rule-set changes
land deliberately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants