neuralnet.cpp 生态的 BPE / CharBPE 分词器库(header-only)。
| 头文件 | 内容 |
|---|---|
domain_tokenizer.hpp |
聚合入口(include 它即可) |
domain_tokenizer_base.hpp |
Tokenizer 基类 + 并行预分词(pre_tokenize)+ 词表持久化(to_kvrec/load_from_kvrec/save/load)+ 多轮对话 prompt 构建(chat_prompt)+ encode_docs_parallel |
domain_tokenizer_bpe.hpp |
BPETokenizer(GPT 风格字节对编码) |
domain_tokenizer_charbpe.hpp |
CharBPETokenizer + make_tokenizer 工厂 + load_tokenizer_from_{string,bytes,file} |
#include <neuralnet.cpp/domain_tokenizer.hpp>
// ── 训练 ──────────────────────────────────────────────────────
nn::BPETokenizer tok;
nn::BPETokenizer::Config cfg;
cfg.vocab_size = 320;
cfg.min_freq = 1;
cfg.threads = 0; // 0 = 自动(线程池全部核心)
cfg.log = [](std::string_view) {}; // 训练日志回调
auto tr = tok.train(corpus, cfg); // Result<void>
// ── 编解码 ────────────────────────────────────────────────────
std::vector<std::size_t> ids = tok.encode("hello world");
std::string text = tok.decode(ids); // encode∘decode 字节级往返一致
std::size_t n = tok.vocab_size();
// 批量文档并行编码(保序:任意并行度与顺序 encode 逐字节一致)
auto per_doc = nn::encode_docs_parallel(tok, docs);
// ── 对话标记 ──────────────────────────────────────────────────
tok.has_dialogue_markers();
tok.assistant_marker_id(); tok.end_assistant_marker_id(); // 及 system/user 等
std::vector<std::size_t> prompt = tok.chat_prompt(
{{/*user=*/true, "hi", /*tokens=*/{}}, {false, "hello", {}}},
/*system_prompt=*/"", /*max_tokens=*/0);
// ── 词表持久化(.nnvocab,kvrec v2)────────────────────────────
tok.save("vocab.nnvocab"); // Result<void>
nn::KeyValueRecord rec = tok.to_kvrec(); // 模型内嵌词表字节来源
auto loaded = nn::load_tokenizer_from_file("vocab.nnvocab"); // Result<unique_ptr<Tokenizer>>
auto made = nn::make_tokenizer("bpe"); // 按类型字符串造工厂实例
// ── CharBPE(字符级 BPE)───────────────────────────────────────
nn::CharBPETokenizer cbpe;
cbpe.train(corpus, cbpe.Config{/*...*/});add_subdirectory(tokenizer) # 自动拉起 extern/{base,threadpool,kvrecord,dataset}
target_link_libraries(app PRIVATE neuralnet::tokenizer) # 提供 include + C++23均以 submodule 位于 extern/:
base.neuralnet.cpp—Result<T>/ 断言 / 精度 / 常量threadpool.neuralnet.cpp— 并行预分词(parallel_for_samples)kvrecord.neuralnet.cpp— 词表二进制容器dataset.neuralnet.cpp— 词表文件格式(parse_nnvocab/write_nnvocab)+.nndataset集成
git clone --recurse-submodules .../tokenizer.neuralnet.cpp
# 或已 clone 后:git submodule update --init --recursivegit submodule update --init --recursive
cmake -B build
cmake --build build
ctest --test-dir build --output-on-failure| 测试 | 覆盖 |
|---|---|
tokenizer_tokenizer_test |
pre_tokenize 手写状态机 ↔ std::regex 参考逐字节对拍(缩写/数字/空白/标点/非 ASCII/标记边界 + 随机字节);标记边界训练后仍按单 token 识别;encode∘decode 字节级往返;并行 encode 确定性(任意并行度逐字节一致) |
tokenizer_nnvocab_test |
旧 JSON 词表 → .nnvocab → 加载语义一致(vocab/merges/markers/编解码);训练态 save/load 往返逐位一致(BPE + CharBPE);旧 .json 词表明确拒绝;词表镜像字节直载(v5 JSON / v6 kvrec) |
tokenizer_dataset_integration_test |
真实 BPE 训练 → encode_docs_parallel 保序 → mark_assistant_span 掩码与全局扫描逐位一致 → 写读 .nndataset 逐位 round-trip(all/assistant 双模式、空 doc、train/test 双子集)→ .nnvocab 独立加载 |
被父工程 add_subdirectory 消费时测试默认不构建(NN_BUILD_TESTS 默认值 =
是否顶层工程);显式 -DNN_BUILD_TESTS=ON 可在嵌入时强制打开。
许可证:LGPL-3.0(见 LICENSE)。