拓冰建站拓冰建站
首页 / 资讯中心 / 正文

PaddleNLP SLM Pipelines 预处理节点深度解析:PreProcessor 与 TextSplitter 的文本清洗与切分原理

人工智能大模型预训练微调LoRARLHF强化学习分布式训练【免费下载链接】PaddleNLPEasy-to-use and powerful LLM and SLM library with awesome model zoo.项目地址https://gitcode.com/gh_mirrors/pa/PaddleNLP点击查看免费下载导读在基于 PaddleNLP 的slm/pipelines检索增强生成RAG体系中文档在进入索引库与检索链路之前必须经过「预处理节点」把非结构化文本清洗并切分成适合向量化与检索的单元。本文以 preprocessor.md 所指向的pipelines.pipelines.nodes.preprocessor包为核心系统讲解PreProcessor面向段落/句子/单词的经典切分器与TextSplitter家族面向字符数、递归分隔符、Spacy 句子与 Markdown 标题的切分器的完整参数语义、底层实现与 Pipeline 集成方式。读完本文你将掌握如何为文档索引、FAQ 问答、文档对话等场景配置最优的清洗与切分策略并理解每一步背后的源码逻辑。模块定位预处理节点在 Pipeline 中的角色在slm/pipelines中预处理节点负责把原始文档通常由 file_converter.md 中的转换器产出的{content: ..., meta: ...}字典加工成一系列可被检索器召回、可被 LLM 上下文容纳的小文档。整个过程分两步清洗Clean去除页眉页脚、首尾空白、多余空行切分Split按单词、句子、段落或字符数阈值把长文档切成多个子文档并携带_split_id元数据标识切分序号。该模块由三个文件构成均位于 slm/pipelines/pipelines/nodes/preprocessor/ 目录下base.py定义BasePreProcessor抽象基类约定process / clean / split / run四类接口preprocessor.py实现核心的PreProcessor类对应文档中的pipelines.pipelines.nodes.preprocessor.preprocessortext_splitter.py实现TextSplitter及五个具体切分器对应文档中的pipelines.pipelines.nodes.preprocessor.text_splitter。所有类都继承自BaseComponent见 pipelines/nodes/base并对外暴露统一的run()接口从而可以被Pipeline.add_node()直接编排为节点。PreProcessor 核心类构造参数与默认值PreProcessor构造函数的签名定义在 preprocessor.py 中其参数共同决定清洗做什么、切分怎么做。参数含义与默认值如下表参数默认值含义与行为clean_whitespaceTrue是否去除文本每一行首尾的空白字符调用str.strip()后重新以\n拼接clean_header_footerFalse是否用启发式方法跨页搜索最长公共子串以删除页眉页脚clean_empty_linesTrue是否将连续两个以上的空行压缩为单个空行正则\n\n→\n\nsplit_byword切分单元可选word、sentence、passage设为None可完全禁用切分split_length200每个输出文档允许包含的切分单元最大数量例如split_bysentence、split_length10表示每个文档含 10 个句子split_overlap0相邻两个子文档之间的单元重叠数大于 0 即等价于滑窗sliding window切分split_answersFalse是否按 FAQ 格式问题\t答案Tab 分隔解析文本并把答案写入meta[answer]split_respect_sentence_boundaryTrue当split_byword时是否保证每个子文档都包含完整句子字数 ≤split_lengthlanguageenNLTKsent_tokenize使用的语言ISO 639 格式如en、es、de、fr中文传chinese两点实现细节值得注意构造函数开头调用self.set_config(...)把全部参数固化下来便于组件配置以 YAML 形式导出这是 Pipeline 配置化编排的基础首次使用时若 NLTK 找不到tokenizers/punkt数据包会尝试自动下载punkt见 preprocessor.py确保句子切分开箱即用。在 preprocessor.py 中还维护了一张iso639_to_nltk语言映射表把 ISO 639 语言代码映射为 NLTK 内部名称如ru→russian、es→spanish、en→english等 18 种语言language参数正是通过这张表传给nltk.tokenize.sent_tokenize。处理主流程process → clean → splitprocess()是 PreProcessor 的入口接受单个dict或dict列表返回切分后的文档列表若传入其他类型会抛出异常preprocessor.py。其内部调用链为process() └─ _process_single() # 单文档先清洗再切分 ├─ clean() # 处理空白、页眉页脚、空行 └─ split() # 按 split_by 切分成子文档 └─ _process_batch() # 批量模式对每个文档执行上述流程并用 tqdm 显示进度_process_batch()会把嵌套列表展平为扁平的文档列表返回preprocessor.py。run()方法则由BasePreProcessor提供base.py它把process()的结果包装为{documents: documents}并返回(output_1)从而与 Pipeline 的标准节点协议对齐——每个切分出来的子文档会额外写入meta[_split_id] i用于记录它在原文档中的切分序号。清洗阶段三类启发式规则clean()按顺序执行三项处理preprocessor.py页眉页脚删除仅clean_header_footerTrue以换页符\f将文本切分为页对每页前 300 字符页眉与后 300 字符页脚做最长公共 n-gram 搜索找到公共串后从所有页中移除。其内部_find_and_remove_header_footer使用了精确匹配启发式能很好处理如Copyright 2019 by XXX这类固定页脚但检测不到Page 3 of 4这类含页码变化的文本默认忽略第 1 页与最后 1 页如目录页往往不含页眉页脚。空白清理clean_whitespaceTrue逐行strip()后重新拼接消除行首行尾的意外空格。空行压缩clean_empty_linesTrue用re.sub(r\n\n, \n\n, text)把三个及以上连续换行压成两个。切分阶段word / sentence / passage 三种单元split()首先做参数合法性校验若split_by为空则直接返回原文档不切分若设置了split_by却没设置split_length会抛出异常split_respect_sentence_boundaryTrue只允许与split_byword组合否则抛出NotImplementedErrorpreprocessor.py。随后按切分单元分别处理split_bysentence用 NLTK 的sent_tokenize按句子粒度切出元素再按split_length个句子合并为一个文档。split_byword非尊重句界模式直接以空格text.split( )切出单词元素再按split_length个词合并。split_bypassage以\n\n段落分隔符切出段落元素再按段落数合并。split_bywordsplit_respect_sentence_boundaryTrue先按句子切分再把句子依次填充进子文档直到加入下一句会超过split_length才封口保证每个子文档都是完整句子、且词数不超过上限若某个单句本身超过split_length会打印一条 warning 并照常保留。元素的合并统一由more_itertools.windowed(elements, nsplit_length, stepsplit_length - split_overlap)完成——windowed的step与n之差正是重叠量这正是滑窗切分的实现基础。滑窗切分的经典示例文档注释中给出了split_byword、split_length5、split_overlap2时的输出形态[w1 w2 w3 w4 w5, w4 w5 w6 w7 w8, w7 w8 w10 w11 w12]即每个子文档长度为 5 个词相邻子文档之间共享后 2 个词作为上下文衔接避免关键信息恰好被切分边界截断。默认split_overlap0则保证子文档之间零重叠。在尊重句界模式下重叠同样按句子回填当封口一个子文档时从尾部往前累积句子直到凑足split_overlap个词作为下一个子文档的开头preprocessor.py。FAQ 场景split_answers 与 Tab 分隔当split_answersTrue且split_bypassage时split()走 FAQ 专用分支文本按\n逐行切分每一行必须是问题\t答案两列结构随后把content设为问题、meta[answer]设为答案preprocessor.py。这一能力用于构建 FAQ 问答库——答案只作为检索命中的上下文不参与正文切分同时它不会像普通模式那样把 FAQ 文本强制切到固定长度避免了把一问一答拦腰截断。若某行 Tab 列数超过 2会抛出异常提示每行必须是两列并以 \t 分隔。TextSplitter 家族面向不同文档类型的五类切分器TextSplitter系列定义在 text_splitter.py 中核心设计是先用某种策略把长文本切碎成小片splits再用_merge_splits按chunk_size与chunk_overlap把碎片合并成大小适中的 chunk。基类TextSplitter的构造参数包括chunk_size默认 4000合并后的 chunk 目标长度由length_function度量chunk_overlap默认 200相邻 chunk 的重叠量必须小于等于chunk_size否则构造时直接抛ValueErrorlength_function默认len长度计算函数可替换为按 token 数计量的自定义函数filters需从文档中剔除的特殊字符列表separatorchunk 合并时的分隔符。基类提供三种通用入口split_text(text)切分单段文本、create_documents(texts, metadatas)由文本列表创建带元数据的文档meta会做深拷贝避免多个 chunk 共享同一份元数据对象、split_documents(documents)切分整批文档run()则是 Pipeline 节点调用入口同样返回(result, output_1)并为每个 chunk 写入_split_idtext_splitter.py。CharacterTextSplitter按字符/分隔符切分CharacterTextSplitter是纯字符粒度的切分器若指定了separator则按分隔符text.split(separator)切碎否则直接list(text)拆成单字符再走_merge_splits合并text_splitter.py。其_merge_splits是长度受限的贪心合并持续累积碎片直到加入下一片会超过chunk_size随后按chunk_overlap从头部弹出已消费的碎片以形成重叠。测试用例验证了其行为test_text_splitter.pysplitter CharacterTextSplitter(separator , chunk_size7, chunk_overlap3) splitter.split_text(foo bar baz 123) # [foo bar, bar baz, baz 123]RecursiveCharacterTextSplitter递归尝试多级分隔符RecursiveCharacterTextSplitter按优先级[\n\n, \n, , ]依次尝试分隔符先用最粗的段落分隔符切分如果某一段仍然超过chunk_size就递归地用下一个更细的分隔符继续切最终确保每个 chunk 都尽量落在语义边界上text_splitter.py。它特别适合结构较松散、分隔符不统一的文档。SpacyTextSplitter基于 Spacy 的句子切分SpacyTextSplitter借助spacy的句法分析器按句子切分构造时需指定语言模型 pipeline默认zh_core_web_sm即中文小模型英文可传en_core_web_sm若本地未安装会尝试spacy.cli.download自动下载对超过 100 万字符的超长文本还会自动调大 tokenizer 的max_lengthtext_splitter.py。split_text按句子产出 splits 后同样交由_merge_splits合并。其输出比正则/NLTK 方案更贴合语义句界测试中表现为Hi.\n\nIm Harrison.这类保持完整语块的 chunktest_text_splitter.py。MarkdownHeaderTextSplitter按标题层级保留文档结构MarkdownHeaderTextSplitter用于保留 Markdown 的结构信息构造时通过headers_to_split_on指定需要跟踪的标题层级默认覆盖#到######六级return_each_lineTrue时逐行输出、False时把具有相同标题元数据的行聚合为 chunk。实现上维护一个header_stack记录嵌套标题结构遇到同级或更高级标题时弹出栈顶、清除对应元数据从而保证同一章节的正文归入同一 chunk并携带章节路径元数据text_splitter.py。测试用例中的预期输出证实了这一点test_text_splitter.pymarkdown_splitter.split_text(## Bar\n\nHi this is Jim \nHi this is Joe\n\n ## Baz\n\n Hi this is Molly) # [Bar\nHi this is Jim\nHi this is Joe, Baz\nHi this is Molly]Pipeline 集成实践从 YAML 配置到文档索引TextSplitter 家族在真实 Pipeline 中承担着按文件类型差异化切分的职责。参考示例配置 chatfile.yaml索引链路按文件后缀挂载不同的转换器与切分器Docx→SpacyTextSplitterchunk_size300Markdown→MarkdownHeaderTextSplitterchunk_size300、return_each_lineFalse让标题成为 chunk 元数据TXT / PDF / 图片→CharacterTextSplitter以\f为分隔符、chunk_size300、chunk_overlap0并过滤\n字符。在代码层面preprocessing.py 的convert_files_to_dicts正是按.pdf、.txt、.docx、.png/.jpg、.md后缀构造suffix2splitter映射并在转换后用document_rough_split粗分、多进程并行执行切分语言参数还会影响 Spacy 切分器的选型——中文使用默认zh_core_web_sm英文使用en_core_web_sm。这说明TextSplitter 家族是处理混合格式文档仓库时按类型定制切分策略的标配。PreProcessor同样深度嵌入了检索组件WebRetriever在构造时可传入preprocessor用于把网页抓取的原始文本切分成段落未提供时默认使用PreProcessor()web.pyElasticsearchDocumentStore.add_evaluation_data等入口也接收可选的PreProcessor对评估文档做预处理但文档注释明确提示该场景暂不支持split_bysentence、非零split_overlap与三类清洗选项需要以word/passage切分、split_overlap0、关闭清洗的组合来使用document_stores/base.py。行为验证测试用例中的可复现基线单元测试 test_preprocessor.py 提供了可直接复现的行为基线测试文本含 3 个段落并以\f分页、夹杂Dr.这类缩写切分配置期望结果split_bysentence、split_length1输出 15 个文档split_bysentence、split_length10输出 2 个文档split_byword、split_length10、不尊重句界输出 11 个文档split_byword、split_length15、尊重句界输出 8 个文档且每个文档词数 ≤ 15首段 14 词split_byword、split_length40、split_overlap10、尊重句界输出 5 个文档split_bypassage、split_length1输出 3 个文档这些基线说明句子切分受 NLTK 对缩写词如Dr.识别能力影响尊重句界模式下子文档词数恒 ≤split_length重叠参数在句子粒度上同样生效。如果你在自己的文档上遇到与预期不符的切分数量可优先检查是否设置了split_respect_sentence_boundary、split_overlap以及language是否匹配语种。小结如何选择切分策略场景推荐组件与配置通用长文档网页、论文入索引PreProcessor(split_byword, split_length200, split_overlap20, split_respect_sentence_boundaryTrue)兼顾完整句界与滑窗衔接结构明确的 Markdown 文档MarkdownHeaderTextSplitter(return_each_lineFalse)chunk 携带章节标题元数据FAQ 问答库构建PreProcessor(split_answersTrue, split_bypassage)按问题\t答案行解析混合格式文件批量入库按后缀配置suffix2splitter映射参考 preprocessing.py中文长文本PreProcessor(languagechinese)或SpacyTextSplitter(pipelinezh_core_web_sm)无论选择哪条路线清洗去页眉页脚、空白、空行与切分单元、长度、重叠都是决定检索召回质量的两道关键闸门。掌握PreProcessor与TextSplitter的参数语义就能针对不同语种、不同文档结构精细调控索引粒度让下游检索器与 LLM 拿到语义完整、长度适中的上下文。赞分享人工智能大模型预训练微调LoRARLHF强化学习分布式训练【免费下载链接】PaddleNLPEasy-to-use and powerful LLM and SLM library with awesome model zoo.项目地址https://gitcode.com/gh_mirrors/pa/PaddleNLP点击查看免费下载相关推荐Chat LangChain数据预处理技术文档清洗与分块的深度解析Chat LangChain数据预处理技术文档清洗与分块的深度解析 Chat LangChain数据预处理是构建智能问答系统的关键环节通过文档清洗与分块技术人工智能AI 应用AI AgentRAG后端前端Axolotl数据预处理脚本文本清洗与格式转换Axolotl数据预处理脚本文本清洗与格式转换 数据预处理核心流程解析 Axolotl的数据集预处理是模型训练前的关键步骤负责将原始数据转换为模型可理解的格人工智能大模型微调LoRA强化学习PyTorch情感分析中的数据预处理文本清洗与标准化技巧PyTorch情感分析中的数据预处理文本清洗与标准化技巧 在构建高效的PyTorch情感分析模型时 数据预处理 是整个机器学习流程中最关键的环节之一。本文将示例工程教程上一篇京东自动化工具高效管理商品评价的智能解决方案下一篇网盘直链下载终极解决方案LinkSwift完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门