人工智能大模型预训练微调LoRARLHF强化学习分布式训练【免费下载链接】PaddleNLPEasy-to-use and powerful LLM and SLM library with awesome model zoo.项目地址https://gitcode.com/gh_mirrors/pa/PaddleNLP点击查看免费下载PaddleNLP 作为覆盖 LLM 与 SLM 的深度学习工具库其分词器Tokenizer是文本进入模型的第一道关卡。本文基于 tokenizer_utils.rst 指向的 tokenizer_utils.py2199 行完整讲解PretrainedTokenizer、BPETokenizer、ChatTemplate等核心类的设计、实现原理与实战用法帮助开发者理解分词流程、特殊 Token 管理、对话模板渲染并能基于此开发自定义分词器。1. 模块定位tokenizer 体系中的承上启下层tokenizer_utils.py位于paddlenlp/transformers/目录是 PaddleNLP 分词器体系的核心实现文件之一与同级文件共同构成完整的分层架构文件职责tokenizer_utils_base.py定义PretrainedTokenizerBase、BatchEncoding、PaddingStrategy、TruncationStrategy等基础设施与策略枚举tokenizer_utils.py定义PretrainedTokenizer抽象基类、BPETokenizer、ChatTemplate及文本预处理工具函数tokenizer_utils_fast.py基于 Rusttokenizers的快速分词器实现PretrainedTokenizer继承自ChatTemplateMixin与PretrainedTokenizerBase源码是所有具体模型分词器如BertTokenizer、LlamaTokenizer、QwenTokenizer等的统一基类。模块顶层通过__all__导出了PretrainedTokenizer、BPETokenizer、tokenize_chinese_chars、is_chinese_char、normalize_chars、tokenize_special_chars、convert_to_unicode七个公开符号源码。从仓库中大量模型分词器的继承关系可以印证这一点例如tests/transformers/下的 bert、llama、qwen、chatglm 等测试目录均直接依赖本模块导出的类test_tokenizer_common.py 中的TokenizerTesterMixin统一从paddlenlp.transformers导入PretrainedTokenizer进行通用性测试。2. 文本预处理工具函数unicode 世界的第一步清洗在真正的分词发生之前原始文本需要经过一系列字符级预处理。本模块提供了一组独立的纯函数工具。2.1 convert_to_unicode统一编码入口convert_to_unicode源码将输入统一转为 UTF-8 解码后的 str。str直接返回bytes以utf-8编码并忽略非法字节解码其他类型抛出ValueError。所有下游分词入口如BPETokenizer._tokenize都会先调用它保证编码一致性。2.2 字符分类判定_is_whitespace / _is_control / _is_punctuation这三个内部函数基于 Unicode 分类unicodedata.category判定字符类型_is_whitespace空格、\t、\n、\r以及 UnicodeZs分类字符_is_controlUnicodeC*分类字符但\t、\n、\r被排除在外它们按空白处理_is_punctuationASCII 标点区间33–47、58–64、91–96、123–126以及 UnicodeP*分类字符。它们进一步被_is_end_of_word/_is_start_of_word组合使用用于判断词边界。2.3 中文字符处理is_chinese_char 与 tokenize_chinese_charsis_chinese_char源码按 CJK Unicode 区块判断字符是否属于汉字覆盖了基本区0x4E00–0x9FFF、扩展 A0x3400–0x4DBF、扩展 B/C/D0x20000–0x2CEAF以及兼容区0xF900–0xFAFF、0x2F800–0x2FA1F。tokenize_chinese_chars源码则遍历输入文本在每个汉字字符前后用空白分隔将其从整句中独立出来——这是中英混合文本正确分词的经典做法被大量中文模型分词器复用。2.4 多语言字符规范化normalize_chars 与 tokenize_special_charsnormalize_chars源码针对多语言与中文模型做 NFKC 规范化全角/半角字符、小型变体、CJK 兼容字符通过unicodedata.normalize(NFKC, ...)归一带圈数字等非规范数字符号转换为普通数字并加空白特殊码位0xF979兼容区的一个特殊汉字被替换为“凉”。tokenize_special_chars源码为日文0x3040–0x30FF、希腊文/西里尔文0x0370–0x04FF、IPA 扩展0x0250–0x02AF以及 Unicode 符号S*分类字符添加前后空白避免这些特殊书写系统被错误粘连进单词。3. Trie 数据结构一次遍历完成特殊 Token 切分Trie类源码是用 Python 实现的字典树核心用途是在单次线性扫描中识别出文本中的所有已添加 Tokenadded tokens并保证“最长匹配优先”。其核心接口add(word)将单词逐字符插入self.data嵌套字典空串键标记单词终止操作幂等split(text)返回按已注册 Token 边界切分后的片段列表。算法借助OrderedDict状态机同时跟踪多个可能的起始位置配合 lookahead 机制实现贪心最长匹配例如同时注册了extra_id_1与extra_id_100时extra_id_100会被整体匹配而非被extra_id_1截断cut_text(text, offsets)依据收集到的切割偏移量完成实际切分并带有防零宽切割与越界恢复逻辑。from paddlenlp.transformers.tokenizer_utils import Trie trie Trie() trie.add([CLS]) trie.add(extra_id_1) trie.add(extra_id_100) # 最长匹配优先extra_id_100 不会被拆成 extra_id_1 print(trie.split([CLS] This is a extra_id_100)) # [[CLS], This is a , extra_id_100]在PretrainedTokenizer中tokens_trie Trie()是类级共享实例每次调用_create_trie(unique_no_split_tokens)会依据当前的“不可切分 Token”列表重建源码并在do_lower_caseTrue时对非特殊 Token 统一小写后再插入保证与大小写折叠逻辑一致。4. PretrainedTokenizer所有分词器的抽象基类PretrainedTokenizer源码是 PaddleNLP 中所有“慢速”纯 Python分词器的统一基类。类 docstring 明确列出了子类需要声明的一组类属性用于描述模型的词表资源与输入形态类属性含义resource_files_names映射__init__参数名到词表文件保存名的字典pretrained_resource_files_map从预训练模型快捷名到词表文件 URL 的嵌套字典max_model_input_sizes模型允许的最大输入长度None表示无限制pretrained_init_configuration加载预训练分词器时传入__init__的默认参数model_input_names模型前向所需输入名列表如input_ids、token_type_idspadding_side/truncation_side默认填充/截断方向right或left此外基类通过InitTrackerMeta元类见 utils.py自动追踪子类__init__参数并把以_token结尾的参数自动注册为特殊 Token 属性。4.1 词表与特殊 Token 管理vocab_size属性返回基础词表大小不含 added tokens而__len__返回vocab_size len(added_tokens_encoder)源码。add_tokens/_add_tokens源码向词表追加新 Token。非特殊 Token 在do_lower_caseTrue时会被自动小写只有“不在词表中且不等于 unk_token”的 Token 才会真正加入新增 Token 从当前len(self)开始编号并同步维护added_tokens_encodertoken→id与added_tokens_decoderid→token两个映射。之后还会把新 Token 插入unique_no_split_tokens列表并重建 Trie确保它们不被二次切分。get_added_vocab返回added_tokens_encoder字典。_build_special_tokens_map_extended源码校验并设置特殊 Token 属性additional_special_tokens必须为 str/AddedToken 列表其余特殊 Token 必须是 str 或AddedToken。以官方文档示例为基础的典型用法tokenizer BertTokenizer.from_pretrained(bert-base-uncased) num_added tokenizer.add_tokens([new_tok1, my_new-tok2]) print(We have added, num_added, tokens)4.2 词表文件读写load_vocabulary / save_vocabularyload_vocabulary源码逐行读取词表文件每行一个 Token行号即索引构建token_to_idx后交给 vocab.py 的Vocab.from_dict实例化并注入unk_token、pad_token、bos_token、eos_token等特殊 Tokensave_vocabulary源码接受Vocab或dict按索引升序把每个 Token 逐行写出。4.3 完整分词流水线tokenizetokenize源码是慢速分词器的核心入口流程如下取出split_special_tokens开关决定特殊 Token 是否参与再切分调用prepare_for_tokenization做模型定制的前处理基类默认原样返回子类可覆写若do_lower_caseTrue用正则保护特殊 Token 后对其他文本做小写折叠split_special_tokensFalse默认时用tokens_trie.split(text)一次性切出特殊 Token 与普通片段True时整段作为一个整体走后续流程依据AddedToken的lstrip/rstrip属性普通特殊 Token 默认两侧去空白剥离相邻空白对非特殊片段调用子类实现的_tokenize完成真正切词最后拼接返回 Token 列表。_tokenize在基类中直接raise NotImplementedError源码强制子类实现具体切词算法WordPiece、SentencePiece、BPE 等。4.4 Token 与 ID 互转convert_tokens_to_ids源码单 Token 或 Token 列表统一经_convert_token_to_id_with_added_voc转换——先查added_tokens_encoder未命中再走_convert_token_to_id默认委托self.vocab.to_indicesconvert_ids_to_tokens源码支持skip_special_tokens过滤特殊 TokenAddedToken返回其contentconvert_tokens_to_string默认以 .join(tokens)拼接源码convert_to_unicode与whitespace_tokenize组成基础预处理对。4.5 编码与批次编码_encode_plus / _batch_encode_plus_encode_plus源码将单条文本或文本对转为BatchEncoding其内部get_input_ids支持三种输入形态strtokenize后转 ID字符串列表配合is_split_into_wordsTrue时逐词切分后扁平化拼接否则视为已切好的 Token 直接转 ID整数列表视为已编码的 ID 直接透传。随后调用prepare_for_model统一完成加特殊 Token、截断、填充等处理。_batch_encode_plus源码对一批输入执行相同逻辑先逐条解析(ids, pair_ids)再经_batch_prepare_for_model逐条prepare_for_model此阶段不填充最后统一pad对齐并按return_dict返回BatchEncoding或列表。当stride 0且存在文本对时_batch_prepare_for_model源码会以滑动窗口方式对第二序列生成带overflow_to_sample标记的溢出样本用于长文档切片等场景。4.6 解码_decode_decode源码把 ID 序列还原为文本先经convert_ids_to_tokens过滤特殊 Token可选再将普通 Token 与 added tokens 分桶拼接避免 byte-level BPE 与 Unicode 混排spaces_between_special_tokens控制特殊 Token 之间是否加空格最后按clean_up_tokenization_spaces决定是否调用clean_up_tokenization清理多余空白。4.7 偏移映射get_offset_mappingget_offset_mapping源码返回每个 Token 在原字符串中的字符起止区间用于序列标注、抽取式问答等需要对齐原文的任务。实现上先做normalize_chars规范化并构建char_mapping再逐个 Token 在规范文本中定位对 BERT 系含basic_tokenizer/wordpiece_tokenizer属性走专用的_get_bert_like_offset_mapping源码并处理了##前缀、小写折叠、希腊字母 σ/ς 两种小写形态、连续 UNK 等边界情况。5. ChatTemplate 与 ChatTemplateMixin对话模板渲染LLM 对话场景需要把多轮对话按模型特定格式拼装。本模块实现了两套方案ChatTemplatePaddleNLP 原生 JSON 模板与 Jinja2 模板兼容层。5.1 ChatTemplateJSON 驱动的多轮对话模板ChatTemplate源码是一个dataclass包含三个字段字段含义conversation每轮对话的渲染模板列表user 与 bot 各一个 Jinja2 片段systemsystem 消息渲染模板query最后一轮用户 query 的渲染模板渲染通过_compile_jinja_template源码完成使用ImmutableSandboxedEnvironment沙箱环境编译并注入raise_exception全局函数以及regex_findall、tojson过滤器tojson覆写了默认实现避免 HTML 转义并支持缩进/分隔符参数。核心方法render_conversation(conversation_data, index, context_data)将[user_query, bot_answer]二元组渲染成[user 模板结果, bot 模板结果]render_query(query, index, context_data)/render_system(context_data)渲染最后 query 与 system 文本__call__(conversations, context_data)把多轮对话整体渲染成最终字符串并注入length、is_first、is_last等上下文变量最后一轮必须是单 queryfrom_dict/from_file从字典或 JSON 文件加载。5.2 ChatTemplateMixin挂在分词器上的对话能力ChatTemplateMixin源码为PretrainedTokenizer提供对话相关能力核心方法apply_chat_template(conversation, tokenizeTrue, context_data{})源码渲染对话文本tokenizeTrue时继续走self(...)分词编码且强制add_special_tokensFalse模板中已包含特殊 TokentokenizeFalse时仅返回文本encode_chat_inputs(conversations, context_data{})源码返回{system: ids, conversations: [[user_ids, bot_ids], ...]}形式的“可学习/不可学习片段”结构供 SFT 训练直接构造输入与标签_encode_chat_inputs/_extract_non_learnable_parts通过整段渲染再按每轮答案切分抽出非学习部分prompt与答案部分。5.3 加载与保存机制from_pretrained源码在基类加载完成后会检查 tokenizer 目录下是否存在chat_template.json文件名由 env.py 的CHAT_TEMPLATE_CONFIG_NAME定义存在则调用init_chat_template覆盖加载同时会打印提示chat_template.json未来将废弃建议直接写在tokenizer_config.json中。save_resources源码则会把ChatTemplate以 JSON 形式落盘。init_chat_template源码支持四种输入存在的文件路径、合法的 Jinja2 模板字符串编译为Template、字典、ChatTemplate实例。6. BPETokenizer字节级 BPE 的基础实现BPETokenizer源码是面向 GPT 系模型如 GPT、GPT-2 风格词表的字节级 BPE 基类其构造参数为参数默认值说明vocab_file—词表文件路径每行一个 Tokenencoder_json_path./configs/encoder.jsontoken→id 映射的 JSON 文件vocab_bpe_path./configs/vocab.bpeBPE merge 规则文件unk_token[UNK]未知 Tokensep_token[SEP]分隔 Tokenpad_token[PAD]填充 Tokencls_token[CLS]句首 Tokenmask_token[MASK]掩码 Token内部嵌套Encoder类源码实现完整 BPE 编解码_bytes_to_unicode构造 UTF-8 字节到 Unicode 字符的可逆映射规避空格/控制字符bpe(token)基于 merge 优先级反复合并相邻符号对结果带lru_cache缓存tokenize用regex预切分支持s、t等收缩词特殊 Token 保持原样tokenize_bpe/encode/decode完成字节编码→BPE→ID 的闭环。_tokenize源码默认按句子nltk.sent_tokenize分批编码再拼接is_sentencepieceFalse时直接整段编码。7. 测试体系与工程验证仓库通过两层测试保障本模块的正确性通用测试 mixintest_tokenizer_common.py 的TokenizerTesterMixin提供tokenizer_class、test_sentencepiece、test_offsets等开关统一验证各模型分词器的编解码往返、特殊 Token、偏移映射等通用行为专项测试test_chat_template.py 覆盖ChatTemplate的渲染、上下文注入、特殊 Token、截断与文件持久化其chat_template_config_file指向 tests/fixtures/chat_template.jsontest_tokenizer_util.py 覆盖PretrainedTokenizer的公共行为。此外llama、qwen、chatglm、gemma 等模型的 test_tokenizer.py 均继承上述 mixin验证了从PretrainedTokenizer派生的各实现满足统一契约。8. 总结tokenizer_utils.py是 PaddleNLP 分词体系的中枢Trie提供最长匹配的特殊 Token 切分PretrainedTokenizer以抽象基类形式沉淀了词表管理、编码、解码、填充截断与偏移映射的完整框架ChatTemplate/ChatTemplateMixin让分词器原生支持对话模板渲染与训练输入构造BPETokenizer则给出字节级 BPE 的参考实现。理解该模块是深入源码改造分词逻辑、为自有模型接入 PaddleNLP、或排查 tokenize/decode 行为不一致问题的起点。赞分享人工智能大模型预训练微调LoRARLHF强化学习分布式训练【免费下载链接】PaddleNLPEasy-to-use and powerful LLM and SLM library with awesome model zoo.项目地址https://gitcode.com/gh_mirrors/pa/PaddleNLP点击查看免费下载相关推荐PaddleNLP 中文分词利器paddlenlp.data.tokenizer 模块与 JiebaTokenizer 实战指南PaddleNLP 中文分词利器paddlenlp.data.tokenizer 模块与 JiebaTokenizer 实战指南 导读 paddlenlp.d人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLPGARbro源码分析核心模块实现详解GARbro源码分析核心模块实现详解 GARbro是一款功能强大的视觉小说资源浏览器工具能够解析和提取各种游戏资源格式。本文将对GARbro项目的核心模块进开发工具游戏开发DGL 分布式训练模块完全指南dgl.distributed 核心 API 与源码级实践解析DGL 分布式训练模块完全指南dgl.distributed 核心 API 与源码级实践解析 导读 本文以 DGLDeep Graph Library官方人工智能机器学习深度学习图计算上一篇VLC播放器美化终极指南5款全新皮肤打造个性化影音体验下一篇Markdown转PPT终极指南md2pptx工具快速上手教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
