Haystack 中文文档切分实战:HanLP 集成 ChineseDocumentSplitter 完全指南
【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack
中文文本不依赖空格分词,词与词之间连续书写,这给 RAG(检索增强生成)与语义检索系统中的文档切分带来了独特挑战。Haystack 通过 HanLP 集成提供ChineseDocumentSplitter组件,以语言学感知的方式对中文文档进行分词与分句,支持 coarse/fine 两种粒度、七种切分单位与自定义切分函数。本文基于仓库内 HanLP 集成 API 参考 与 ChineseDocumentSplitter 组件指南,完整讲解其参数体系、使用方法、在索引流水线中的集成方式以及底层实现原理,帮助你为中文语料构建高质量切分方案。
为什么中文文档需要专门的切分器
英文文本以空格天然分隔单词,切分器按空格或标点即可工作。中文则完全不同:词语连续书写、词与词之间没有显式边界,且一个词可以由多个汉字组成。API 参考文档中给出了典型例子:
- 英文单词 "America" 译为中文 "美国",两个汉字构成一个词;
- "Portugal" 译为 "葡萄牙",三个汉字构成一个词。
因此,"按词切分"意味着按这些**多字词元(multi-character token)**切分,而不是按单个汉字或空格简单截断。如果直接按字符数硬切,极容易把完整词义拦腰截断,破坏语义完整性,进而降低后续 Embedding 与检索的质量。
ChineseDocumentSplitter正是为此设计:它调用 HanLP(Han Language Processing)完成中文分词与分句,让切分结果符合中文语言习惯。
组件定位与输入输出
按组件指南中的定位表,ChineseDocumentSplitter在流水线中最常见的位置是索引流水线中、Converter 与 DocumentCleaner 之后(此时文本已被提取并清理),通常位于分类器、Embedding 与写入器之前。
| 项目 | 说明 |
|---|---|
| 必填运行变量 | documents:包含中文文本内容的 Document 列表 |
| 输出变量 | documents:切分后的 Document 列表,每个 Document 包含原文本的一个片段 |
| 安装包 | hanlp-haystack |
| API 参考 | HanLP 集成参考 |
组件导入路径为:
from haystack_integrations.components.preprocessors.hanlp import ChineseDocumentSplitter核心概念:切分单位与两种分词粒度
支持七种切分单位(split_by)
| 取值 | 切分依据 | 典型场景 |
|---|---|---|
word | 按中文词(多字词元)切分(默认) | 通用语义切分 |
sentence | 按 HanLP 分句器切分 | 需要完整句子语义时 |
passage | 按双换行符(\n\n)切分 | 段落结构明显的文本 |
page | 按换页符(\f)切分 | PDF 等多页文档 |
line | 按单换行符(\n)切分 | 按行组织的文本 |
period | 按句号(.)切分 | 以英文句点分隔的文本 |
function | 使用自定义切分函数 | 业务自定义切分逻辑 |
两种分词粒度(granularity)
组件基于 HanLP 提供两级分词粒度:
coarse(粗粒度):面向一般场景的宽泛分词,使用COARSE_ELECTRA_SMALL_ZH模型,为默认值;fine(细粒度):面向专业应用的更细致分词,使用FINE_ELECTRA_SMALL_ZH模型。
API 参考明确指出:coarse代表粗粒度中文分词,fine代表细粒度分词,默认使用粗粒度。若传入的 granularity 不是'coarse'或'fine',组件会抛出ValueError。
句边界尊重(respect_sentence_boundary)
当以word为单位切分时,可以设置respect_sentence_boundary=True,组件会调用 HanLP 的分句模型(UD_CTB_EOS_MUL)检测句子边界,确保切分点只出现在完整句子之间,从而保持每个片段都以完整句子收尾,保留文本的语义完整性。
参数体系详解
ChineseDocumentSplitter的构造函数签名(源自 API 参考):
__init__( split_by: Literal["word", "sentence", "passage", "page", "line", "period", "function"] = "word", split_length: int = 1000, split_overlap: int = 200, split_threshold: int = 0, respect_sentence_boundary: bool = False, splitting_function: Callable | None = None, granularity: Literal["coarse", "fine"] = "coarse", ) -> None各参数含义与默认值:
| 参数 | 默认值 | 说明 |
|---|---|---|
split_by | "word" | 切分单位,见上表七种取值 |
split_length | 1000 | 每个切分片段的最大单位数(词数/句数/行数等) |
split_overlap | 200 | 相邻片段之间的重叠单位数,用于保持上下文衔接 |
split_threshold | 0 | 每个片段的最少单位数;不足阈值的片段会并入前一个片段 |
respect_sentence_boundary | False | 按word切分时是否尊重句子边界 |
splitting_function | None | 当split_by="function"时的自定义切分函数,必须接受单个str输入、返回list[str]输出 |
granularity | "coarse" | 中文分词粒度,coarse或fine |
异常行为:granularity 非法时抛出ValueError;run在分词模型未加载时抛出RuntimeError。
方法速览
API 参考中公开的核心方法:
| 方法 | 签名 | 作用 |
|---|---|---|
run | run(documents: list[Document]) -> dict[str, list[Document]] | 将文档切分为更小的片段 |
warm_up | warm_up() -> None | 预热组件,加载必要的 HanLP 模型 |
chinese_sentence_split | chinese_sentence_split(text: str) -> list[dict[str, Any]] | 将中文文本切分为句子列表 |
to_dict/from_dict | 标准序列化/反序列化 | 将组件配置转为字典或从字典还原,便于流水线 YAML 序列化 |
实战:四种典型用法
1. 独立使用(不接入流水线)
from haystack import Document from haystack_integrations.components.preprocessors.hanlp import ChineseDocumentSplitter # 以词为单位切分:每 10 个词为一段,段间重叠 3 个词 splitter = ChineseDocumentSplitter( split_by="word", split_length=10, split_overlap=3, granularity="coarse", ) doc = Document( content="这是第一句话,这是第二句话,这是第三句话。这是第四句话,这是第五句话,这是第六句话!", ) splitter.warm_up() # 首次运行前加载 HanLP 模型 result = splitter.run(documents=[doc]) print(result["documents"]) # 切分后的 Document 列表API 参考中的最小示例同样验证了这一调用方式:
doc = Document(content= "这是第一句话,这是第二句话,这是第三句话。" "这是第四句话,这是第五句话,这是第六句话!" "这是第七句话,这是第八句话,这是第九句话?" ) splitter = ChineseDocumentSplitter( split_by="word", split_length=10, split_overlap=3, respect_sentence_boundary=True ) result = splitter.run(documents=[doc]) print(result["documents"])注意:
warm_up()用于预加载分词/分句模型。若跳过该步骤直接运行,组件也会在run中检查模型是否就绪,未就绪时抛出RuntimeError。
2. 尊重句子边界切分
当split_by="word"且respect_sentence_boundary=True时,每个片段都会以完整句子结尾:
from haystack import Document from haystack_integrations.components.preprocessors.hanlp import ChineseDocumentSplitter doc = Document( content="这是第一句话,这是第二句话,这是第三句话。" "这是第四句话,这是第五句话,这是第六句话!" "这是第七句话,这是第八句话,这是第九句话?", ) splitter = ChineseDocumentSplitter( split_by="word", split_length=10, split_overlap=3, respect_sentence_boundary=True, granularity="coarse", ) splitter.warm_up() result = splitter.run(documents=[doc]) # 验证每个片段都以完整句子收尾 for doc in result["documents"]: print(f"Chunk: {doc.content}") print(f"Ends with sentence: {doc.content.endswith(('。', '!', '?'))}")3. 细粒度分词(fine)
对需要更精细分词的专业场景(如术语密集的技术文档),使用granularity="fine":
from haystack import Document from haystack_integrations.components.preprocessors.hanlp import ChineseDocumentSplitter doc = Document(content="人工智能技术正在快速发展,改变着我们的生活方式。") splitter = ChineseDocumentSplitter( split_by="word", split_length=5, split_overlap=0, granularity="fine", # 更细致的分词 ) splitter.warm_up() result = splitter.run(documents=[doc]) print(result["documents"])4. 自定义切分函数(function)
当内置切分单位不满足需求时,可通过splitting_function传入自定义函数。函数签名约束为:接受单个str,返回list[str]。
from haystack import Document from haystack_integrations.components.preprocessors.hanlp import ChineseDocumentSplitter def custom_split(text: str) -> list[str]: """按中文逗号切分的自定义函数""" return text.split(",") doc = Document(content="第一段,第二段,第三段,第四段") splitter = ChineseDocumentSplitter(split_by="function", splitting_function=custom_split) splitter.warm_up() result = splitter.run(documents=[doc]) print(result["documents"])在索引流水线中集成
ChineseDocumentSplitter的典型位置是 Converter 与 DocumentCleaner 之后、Embedding 与写入之前。下面是一个完整的 RAG 索引流水线:
from haystack import Pipeline, Document from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack.components.converters.txt import TextFileToDocument from haystack_integrations.components.preprocessors.hanlp import ChineseDocumentSplitter from haystack.components.preprocessors import DocumentCleaner from haystack.components.writers import DocumentWriter # 初始化组件 document_store = InMemoryDocumentStore() p = Pipeline() p.add_component(instance=TextFileToDocument(), name="text_file_converter") p.add_component(instance=DocumentCleaner(), name="cleaner") p.add_component( instance=ChineseDocumentSplitter( split_by="word", split_length=100, split_overlap=20, respect_sentence_boundary=True, granularity="coarse", ), name="chinese_splitter", ) p.add_component(instance=DocumentWriter(document_store=document_store), name="writer") # 连接组件 p.connect("text_file_converter.documents", "cleaner.documents") p.connect("cleaner.documents", "chinese_splitter.documents") p.connect("chinese_splitter.documents", "writer.documents") # 运行流水线,处理中文文本文件 p.run({"text_file_converter": {"sources": ["path/to/your/chinese/files.txt"]}})该流水线的数据流为:文本文件 → 转换为 Document → 文本清理 → HanLP 中文切分 → 写入文档存储,为后续检索与生成提供语言学合理的片段。
切分产物的元数据
每个切分出的片段不仅保留原文档的元数据,还会附带以下字段,便于溯源与拼接:
source_id:原始文档的 ID;page_number:片段所属页码;split_id:片段在文档内的顺序 ID;split_idx_start:片段在原始文档中的起始索引。
这些字段让切分结果可回溯、可排序,为下游检索命中定位和答案引用提供了数据基础。
补充说明
- 本仓库为 Haystack 核心框架,
ChineseDocumentSplitter属于独立的hanlp-haystack集成包,仓库内的 组件指南 与 API 参考 提供了该组件在本框架中的完整使用契约; - 若在
run前未加载分词模型,组件会抛出RuntimeError,因此生产环境建议显式调用warm_up()预加载模型,避免首次运行延迟; - 选择
coarse还是fine取决于语料与任务:通用文本建议默认coarse,术语密集或对分词边界敏感的任务可尝试fine并对比切分质量; - 切分长度与重叠度的设置(
split_length、split_overlap)需结合 Embedding 模型的上下文窗口与检索粒度综合调优,中文按"词"切分时,split_length的单位是词数而非字符数,这一点与英文字符切分有本质区别。
【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考