@@ -4,37 +4,88 @@ neuralnet.cpp 生态的 **BPE / CharBPE 分词器**库(header-only)。
44
55| 头文件 | 内容 |
66| ---| ---|
7- | ` domain_tokenizer.hpp ` | 聚合入口 |
8- | ` domain_tokenizer_base.hpp ` | ` Tokenizer ` 基类 + 并行预分词 + 词表持久化(` load ` /` save ` ) |
9- | ` domain_tokenizer_bpe.hpp ` | ` BPETokenizer ` |
10- | ` domain_tokenizer_charbpe.hpp ` | ` CharBPETokenizer ` + ` make_tokenizer ` 工厂 |
7+ | ` domain_tokenizer.hpp ` | 聚合入口(include 它即可) |
8+ | ` domain_tokenizer_base.hpp ` | ` Tokenizer ` 基类 + 并行预分词( ` pre_tokenize ` ) + 词表持久化(` to_kvrec ` /` load_from_kvrec ` / ` save ` / ` load ` )+ 多轮对话 prompt 构建( ` chat_prompt ` )+ ` encode_docs_parallel ` |
9+ | ` domain_tokenizer_bpe.hpp ` | ` BPETokenizer ` (GPT 风格字节对编码) |
10+ | ` domain_tokenizer_charbpe.hpp ` | ` CharBPETokenizer ` + ` make_tokenizer ` 工厂 + ` load_tokenizer_from_{string,bytes,file} ` |
1111
12- ## 用法
12+ ## API 速览
1313
1414``` cpp
1515#include < neuralnet.cpp/domain_tokenizer.hpp>
1616
17- auto tok = nn::make_tokenizer(...); // 工厂
18- tok->train (...);
19- tok->save("vocab.nnvocab");
17+ // ── 训练 ──────────────────────────────────────────────────────
18+ nn::BPETokenizer tok;
19+ nn::BPETokenizer::Config cfg;
20+ cfg.vocab_size = 320 ;
21+ cfg.min_freq = 1 ;
22+ cfg.threads = 0 ; // 0 = 自动(线程池全部核心)
23+ cfg.log = [](std::string_view) {}; // 训练日志回调
24+ auto tr = tok.train(corpus, cfg); // Result<void>
25+
26+ // ── 编解码 ────────────────────────────────────────────────────
27+ std::vector<std::size_t > ids = tok.encode(" hello world" );
28+ std::string text = tok.decode(ids); // encode∘decode 字节级往返一致
29+ std::size_t n = tok.vocab_size();
30+
31+ // 批量文档并行编码(保序:任意并行度与顺序 encode 逐字节一致)
32+ auto per_doc = nn::encode_docs_parallel(tok, docs);
33+
34+ // ── 对话标记 ──────────────────────────────────────────────────
35+ tok.has_dialogue_markers();
36+ tok.assistant_marker_id(); tok.end_assistant_marker_id(); // 及 system/user 等
37+ std::vector<std::size_t > prompt = tok.chat_prompt(
38+ {{/* user=* /true, "hi", /* tokens=* /{}}, {false, "hello", {}}},
39+ /* system_prompt=* /"", /* max_tokens=* /0);
40+
41+ // ── 词表持久化(.nnvocab,kvrec v2)────────────────────────────
42+ tok.save("vocab.nnvocab"); // Result<void >
43+ nn::KeyValueRecord rec = tok.to_kvrec(); // 模型内嵌词表字节来源
44+ auto loaded = nn::load_tokenizer_from_file("vocab.nnvocab"); // Result<unique_ptr<Tokenizer >>
45+ auto made = nn::make_tokenizer("bpe"); // 按类型字符串造工厂实例
46+
47+ // ── CharBPE(字符级 BPE)───────────────────────────────────────
48+ nn::CharBPETokenizer cbpe;
49+ cbpe.train(corpus, cbpe.Config{/* ...* /});
50+ ```
51+
52+ ## 用法 / CMake
53+
54+ ```cmake
55+ add_subdirectory(tokenizer) # 自动拉起 extern/{base,threadpool,kvrecord,dataset}
56+ target_link_libraries(app PRIVATE neuralnet::tokenizer) # 提供 include + C++23
2057```
2158
2259## 依赖
2360
2461均以 submodule 位于 ` extern/ ` :
2562
2663- [ ` base.neuralnet.cpp ` ] ( https://github.com/neuralnet-cpp-dev/base.neuralnet.cpp ) — ` Result<T> ` / 断言 / 精度 / 常量
27- - [`threadpool.neuralnet.cpp`](https://github.com/neuralnet-cpp-dev/threadpool.neuralnet.cpp) — 并行预分词
64+ - [ ` threadpool.neuralnet.cpp ` ] ( https://github.com/neuralnet-cpp-dev/threadpool.neuralnet.cpp ) — 并行预分词( ` parallel_for_samples ` )
2865- [ ` kvrecord.neuralnet.cpp ` ] ( https://github.com/neuralnet-cpp-dev/kvrecord.neuralnet.cpp ) — 词表二进制容器
29- - [`dataset.neuralnet.cpp`](https://github.com/neuralnet-cpp-dev/dataset.neuralnet.cpp) — 词表文件格式(`parse_nnvocab`)
66+ - [ ` dataset.neuralnet.cpp ` ] ( https://github.com/neuralnet-cpp-dev/dataset.neuralnet.cpp ) — 词表文件格式(` parse_nnvocab ` / ` write_nnvocab ` )+ ` .nndataset ` 集成
3067
3168``` bash
3269git clone --recurse-submodules .../tokenizer.neuralnet.cpp
70+ # 或已 clone 后:git submodule update --init --recursive
3371```
3472
35- CMake:
73+ ## 构建与测试
3674
37- ``` cmake
38- add_subdirectory(tokenizer) # 自动拉起 extern/{base,threadpool,kvrecord,dataset}
39- target_link_libraries(app PRIVATE neuralnet::tokenizer)
75+ ``` bash
76+ git submodule update --init --recursive
77+ cmake -B build
78+ cmake --build build
79+ ctest --test-dir build --output-on-failure
4080```
81+
82+ | 测试 | 覆盖 |
83+ | ---| ---|
84+ | ` tokenizer_tokenizer_test ` | ` pre_tokenize ` 手写状态机 ↔ ` std::regex ` 参考逐字节对拍(缩写/数字/空白/标点/非 ASCII/标记边界 + 随机字节);标记边界训练后仍按单 token 识别;encode∘decode 字节级往返;并行 encode 确定性(任意并行度逐字节一致) |
85+ | ` tokenizer_nnvocab_test ` | 旧 JSON 词表 → ` .nnvocab ` → 加载语义一致(vocab/merges/markers/编解码);训练态 save/load 往返逐位一致(BPE + CharBPE);旧 ` .json ` 词表明确拒绝;词表镜像字节直载(v5 JSON / v6 kvrec) |
86+ | ` tokenizer_dataset_integration_test ` | 真实 BPE 训练 → ` encode_docs_parallel ` 保序 → ` mark_assistant_span ` 掩码与全局扫描逐位一致 → 写读 ` .nndataset ` 逐位 round-trip(all/assistant 双模式、空 doc、train/test 双子集)→ ` .nnvocab ` 独立加载 |
87+
88+ 被父工程 ` add_subdirectory ` 消费时测试** 默认不构建** (` NN_BUILD_TESTS ` 默认值 =
89+ 是否顶层工程);显式 ` -DNN_BUILD_TESTS=ON ` 可在嵌入时强制打开。
90+
91+ 许可证:LGPL-3.0(见 [ LICENSE] ( LICENSE ) )。
0 commit comments