LengthTokenizer Rust (DP 最少 token / 最低 TPC) Python extension
Project description
Length-MAX Tokenizer
说明(中文补充):本仓库同时提供
- Rust 训练/统计实现(
length_tokenizer)- Rust 推理分词(DP 最少 token / 最低 TPC):Python 扩展
length_tokenizer_rs.DpTokenizer- HuggingFace remote code 导出(
train_to_hf*生成tokenizer_out/目录)
1) Install
pip install length-tokenizer-rs
If your corpus is parquet (or you want streaming reads via pyarrow):
pip install pyarrow
2) Train a vocab from your corpus (export a local tokenizer directory)
After training you will get a directory (e.g. ./tokenizer_out/) containing:
vocab.json / tokenizer_config.json / special_tokens_map.json / tokenization_length_tokenizer.py / README.md
2.1 Text corpus (one sentence per line)
from length_tokenizer_rs import train_to_hf
train_to_hf(
corpus_file="corpus.txt", # one sentence per line
out_dir="./tokenizer_out",
num_merges=50000,
aim_token_num=20000,
n_max=6,
num_workers=8,
multi_process=False,
use_heap=False, # 默认关闭:更省内存(推荐大语料/大 n_max)
)
2.2 Parquet corpus (streaming read via pyarrow)
from length_tokenizer_rs import train_to_hf_parquet
train_to_hf_parquet(
parquet_path="/path/to/parquet_dir_or_file",
out_dir="./tokenizer_out",
text_column="text",
max_docs=0,
batch_size=8192,
recursive=True,
num_merges=50000,
aim_token_num=20000,
n_max=6,
num_workers=8,
multi_process=False,
use_heap=False, # 默认关闭:更省内存
chunk_size=4096,
)
2.3 推荐最高效设置(大语料 + n_max=9 + 32k vocab)
当你要对齐主流 Llama 系列(vocab_size≈32k)并且 n-gram 上限较大(如 n_max=9)时,内存峰值通常是最大瓶颈。
本实现新增了 use_heap 开关(默认关闭),用于避免候选堆复制一份 n-gram key 导致的额外内存。
-
推荐参数(经验值,适用于 2×GPU 训练前的 vocab 训练阶段):
aim_token_num=32000num_merges=40000(上限,不等于最终词表大小)n_max=9num_workers=64(按 CPU 资源调整)use_heap=False(默认,强烈建议保持)multi_process=False(默认;若你希望进一步隔离峰值内存/更稳定,可尝试True)
-
日志重定向(很重要):训练日志默认写到 stderr,如果你用
tee记日志,需要把 stderr 合并到 stdout:
... 2>&1 | tee run.log
- CLI 示例(适合快速 bench / 复现实验):
cd tokenizers_rust
cargo run --release --bin length_tokenizer -- \
--corpus /path/to/train.txt \
--corpus-format txt \
--output token_table_32k.json \
--num-merges 40000 \
--aim-token-num 32000 \
--n-max 9 \
--num-workers 64 \
2>&1 | tee run_32k_n9.log
如你确实有充足内存并希望加速“找 best n-gram”,可以显式开启 heap:
--use-heap
3) Tokenize your corpus with the new vocab → write ids (data prep)
The examples below write ids.txt: one sample per line, space-separated token ids (high throughput: Rust DpTokenizer.encode_batch()).
3.1 Text corpus (one sentence per line) → ids.txt
import json
from pathlib import Path
from length_tokenizer_rs import DpTokenizer
TOKENIZER_DIR = Path("./tokenizer_out")
VOCAB = TOKENIZER_DIR / "vocab.json"
dp = DpTokenizer(str(VOCAB), "<unk>")
# Optional: add BOS/EOS (adjust to your training pipeline)
vocab = json.loads(VOCAB.read_text(encoding="utf-8"))
bos = vocab.get("<s>")
eos = vocab.get("</s>")
IN_TXT = Path("corpus.txt")
OUT_IDS = Path("corpus.ids.txt")
BATCH = 256
buf = []
with IN_TXT.open("r", encoding="utf-8", errors="ignore") as r, OUT_IDS.open("w", encoding="utf-8") as w:
for line in r:
s = line.strip()
if not s:
continue
buf.append(s)
if len(buf) >= BATCH:
for ids in dp.encode_batch(buf):
if bos is not None:
w.write(str(int(bos)) + " ")
w.write(" ".join(str(int(x)) for x in ids))
if eos is not None:
w.write(" " + str(int(eos)))
w.write("\n")
buf.clear()
if buf:
for ids in dp.encode_batch(buf):
if bos is not None:
w.write(str(int(bos)) + " ")
w.write(" ".join(str(int(x)) for x in ids))
if eos is not None:
w.write(" " + str(int(eos)))
w.write("\n")
3.2 Parquet corpus (streaming read) → ids.txt
import json
from pathlib import Path
import pyarrow.dataset as ds
from length_tokenizer_rs import DpTokenizer
PARQUET = "/path/to/parquet_dir_or_file"
TEXT_COL = "text"
TOKENIZER_DIR = Path("./tokenizer_out")
VOCAB = TOKENIZER_DIR / "vocab.json"
dp = DpTokenizer(str(VOCAB), "<unk>")
vocab = json.loads(VOCAB.read_text(encoding="utf-8"))
bos = vocab.get("<s>")
eos = vocab.get("</s>")
OUT_IDS = Path("parquet.ids.txt")
BATCH = 256
buf = []
dataset = ds.dataset(PARQUET, format="parquet")
scanner = dataset.scanner(columns=[TEXT_COL], batch_size=8192, use_threads=True)
with OUT_IDS.open("w", encoding="utf-8") as w:
for batch in scanner.to_batches():
col = batch.column(0)
for s in col.to_pylist():
if not s or not str(s).strip():
continue
buf.append(str(s))
if len(buf) >= BATCH:
for ids in dp.encode_batch(buf):
if bos is not None:
w.write(str(int(bos)) + " ")
w.write(" ".join(str(int(x)) for x in ids))
if eos is not None:
w.write(" " + str(int(eos)))
w.write("\n")
buf.clear()
if buf:
for ids in dp.encode_batch(buf):
if bos is not None:
w.write(str(int(bos)) + " ")
w.write(" ".join(str(int(x)) for x in ids))
if eos is not None:
w.write(" " + str(int(eos)))
w.write("\n")
4) Load the tokenizer for training (local directory)
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("./tokenizer_out", trust_remote_code=True)
assert getattr(tok, "_rust", None) is not None, "Rust extension not active"
5) 现代架构验证(Llama-style: RoPE + RMSNorm + SwiGLU)
审稿/对外说明时,“现代架构验证”通常指:在 非 GPT-2 的 decoder-only Transformer 上,从零训练(或至少跑通训练环节)并复现同方向的效率收益。
本仓库提供一个最小可复用脚本 validate_modern_arch_llama.py,用你导出的 Length-MAX tokenizer 直接训练一个小的 LlamaForCausalLM(RoPE + RMSNorm + SwiGLU)若干步,验证流程可跑通:
pip install -U torch transformers
python validate_modern_arch_llama.py \
--tokenizer_dir ./tokenizer_out \
--corpus_file corpus.txt \
--seq_len 256 \
--batch_size 8 \
--steps 100
建议用于 rebuttal 的正式实验:保持同语料/同 vocab size/同超参,只替换 tokenizer(BPE vs Length-MAX),并在该现代架构上报告 steps-to-target loss、latency/throughput、以及下游任务指标。
6) Publish to PyPI(推荐用 GitHub Actions)
这个仓库原本就带了 GitHub Actions 发版流程:tokenizers_rust/.github/workflows/publish_pypi.yml。
- GitHub 发版(推荐,跨平台 wheel):
- workflow 触发条件是 push tag,例如
v0.1.7 - 会构建 Linux/macOS/Windows 的 wheels(py3.10/3.11/3.12),并用
PYPI_API_TOKEN发布到 PyPI
- workflow 触发条件是 push tag,例如
示例(在你自己的 git repo 里执行):
git add tokenizers_rust
git commit -m "Release v0.1.7"
git tag v0.1.7
git push origin main --tags
- 本地发布(不推荐,通常只会上传当前平台 wheel):
注意:maturin publish 不需要也不支持 --release(默认就是 release 构建)。
cd tokenizers_rust
maturin publish
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file length_tokenizer_rs-0.1.7-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: length_tokenizer_rs-0.1.7-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 587.2 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
602832bfee2ec38d545d4ec264fcbb819a1a3f5c2e973f20ec67fd59074659ae
|
|
| MD5 |
c8d64cf33838237fdf2fca053ccee3c7
|
|
| BLAKE2b-256 |
475163c2c3d2162214d71db141b16eb7661a8a8ae538e59d5eb2a2da5d7daa92
|
File details
Details for the file length_tokenizer_rs-0.1.7-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: length_tokenizer_rs-0.1.7-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 635.6 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
922020eb9a2f74f564b8dc53148dbda0217dd691f18c337136031b50912e7e33
|
|
| MD5 |
4965ec9bfbc44c6f189fdc1fb1b58fca
|
|
| BLAKE2b-256 |
42d59b74be74b468702ef745426469ff5dbad6fe13c6c46f02ca1644c02c8482
|
File details
Details for the file length_tokenizer_rs-0.1.7-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: length_tokenizer_rs-0.1.7-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 586.6 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14b6117762d37b471cc5198a7dfeba21cf7648cdb59302f2a8fbccc950860ffd
|
|
| MD5 |
b9247cd595f531c8db6295e3f765f438
|
|
| BLAKE2b-256 |
4bd3a7fba397a8f856ae59c0d53af838be8921ad88b012e4f010063fa2708c8a
|
File details
Details for the file length_tokenizer_rs-0.1.7-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: length_tokenizer_rs-0.1.7-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 636.3 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
279d7d1489de70e51e07edc6e9bc06ac209aba36f24047c4be4568d2fb82729b
|
|
| MD5 |
1deda9fd536980dece3c2eb96cbed1cf
|
|
| BLAKE2b-256 |
e26ac4235f50910b899c1c5fd0bd02184d143f8f7d8a83e54962dc60469fcccd
|
File details
Details for the file length_tokenizer_rs-0.1.7-cp310-cp310-win_amd64.whl.
File metadata
- Download URL: length_tokenizer_rs-0.1.7-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 586.8 kB
- Tags: CPython 3.10, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb70364f767135c58486553842b189fbbfb0d438ddeacb9443f7e2011011c7be
|
|
| MD5 |
4f3d38e27aa5ee9dacbd8033f60de3ce
|
|
| BLAKE2b-256 |
090f0832e945b1b8d4f7bb6619aa2b9b60c540ca98845e86733148d3bc10eeb2
|
File details
Details for the file length_tokenizer_rs-0.1.7-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: length_tokenizer_rs-0.1.7-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 636.3 kB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
490c8999b217c35f69992aaa7b0a3bf8b9be6bc4c8e1203a32e1798d60915ae9
|
|
| MD5 |
36b2879dfad0b66efdb0daea54fce306
|
|
| BLAKE2b-256 |
a7131b5f842835d27c17047d2c4befd11be7e3043673d1ac46eea2d924ab8f64
|
File details
Details for the file length_tokenizer_rs-0.1.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: length_tokenizer_rs-0.1.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 714.9 kB
- Tags: CPython 3.8, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bcad6277a274e708d98ec34e58ce754ce510944dce07a57f209d3c2c58845721
|
|
| MD5 |
70a39e10966500d3d1e07268e3b92caf
|
|
| BLAKE2b-256 |
dc6bbd34141db7158662b9e2620290c6cca90211d9dd9f9e439f7d162216d1ba
|