资讯动态

核心组件——文本分割器(Text splitters)

发布时间:2026/10/22 21:00:09 来源:尧图企业网站定制
6.1 概念我们知道通过文档加载器可以完成各种数据源的加载将其转换为文档对象Document。那么接下来要做的就是文档拆分。文档拆分通常是将大文本分解为更小的、易于管理的块。这对于索引数据并将其传递到模型中都很有用。因为大块更难搜索并且不适合模型的有限上下文窗口。拆分可以提高搜索结果的粒度从而可以更精确地将查询与相关文档部分进行匹配。LangChain的文本分割器便能将大型文档分解为更小的块。如下图所示:6.2 根据文档长度与文档语义拆分我们可以直接根据文档的长度拆分文档是最简单且有效的方法。可确保每个块不超过指定的大小限制。对于长度拆分其实也分为两种基于字符长度拆分、基于Token长度拆分6.2.1 基于字符长度拆分根据给定的字符序列进行拆分拆分的块长度则按字符数来衡量。markdown_path ../Docs/Markdown/脚手架级微服务租房平台QA.md # single 模式加载后默认只有一个 Document 对象 loader UnstructuredMarkdownLoader(markdown_path) data loader.load() # 文本分割器 text_splitter CharacterTextSplitter( separator\n\n, # 选择分隔符它有一个默认的分隔符优先级列表通常是[\n\n, \n, , ]. 它会按顺序尝试这些分隔符 chunk_size100, # 设定目标目标块大小 chunk_overlap20, # 设定目标块之间的重叠大小 length_functionlen, # 使用测量长度的函数 is_separator_regexFalse,# 分隔符是正则表达式吗 ) # 分割文档返回被分割的文档列表 texts text_splitter.split_documents(data) # 打印前10个被分割出来的文档 for document in texts[:10]: print(* * 30) print(f{document}\n)关于CharacterTextSplitter 所有初始化参数见CharacterTextSplitter | langchain_text_splitters | LangChain Reference打印结果:Created a chunk of size 128, which is longer than the specified 100 Created a chunk of size 133, which is longer than the specified 100 Created a chunk of size 108, which is longer than the specified 100 Created a chunk of size 104, which is longer than the specified 100 Created a chunk of size 127, which is longer than the specified 100 Created a chunk of size 112, which is longer than the specified 100 Created a chunk of size 121, which is longer than the specified 100 Created a chunk of size 137, which is longer than the specified 100 Created a chunk of size 133, which is longer than the specified 100 Created a chunk of size 108, which is longer than the specified 100 Created a chunk of size 1171, which is longer than the specified 100 Created a chunk of size 1171, which is longer than the specified 100 Created a chunk of size 112, which is longer than the specified 100 Created a chunk of size 128, which is longer than the specified 100 Created a chunk of size 102, which is longer than the specified 100 Created a chunk of size 155, which is longer than the specified 100 Created a chunk of size 121, which is longer than the specified 100 Created a chunk of size 284, which is longer than the specified 100 Created a chunk of size 107, which is longer than the specified 100 Created a chunk of size 206, which is longer than the specified 100 Created a chunk of size 161, which is longer than the specified 100 Created a chunk of size 115, which is longer than the specified 100 Created a chunk of size 159, which is longer than the specified 100 Created a chunk of size 125, which is longer than the specified 100 Created a chunk of size 150, which is longer than the specified 100 Created a chunk of size 102, which is longer than the specified 100 Created a chunk of size 106, which is longer than the specified 100 Created a chunk of size 107, which is longer than the specified 100 Created a chunk of size 238, which is longer than the specified 100 Created a chunk of size 113, which is longer than the specified 100 Created a chunk of size 102, which is longer than the specified 100 Created a chunk of size 206, which is longer than the specified 100 Created a chunk of size 282, which is longer than the specified 100 ****************************** page_content通用问题 为什么做这个项目 回答1:出于兴趣爱好开发 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content大学期间我和同学在外合租过一段时间使用了一些租房平台于是我有个想法自己能不能开发一个租房平台可以让我将理论知识与实践相结合。我希望通过实际项目来加深对 Java 编程语言和相关技术的理解。于是我便查找了一些资料看了一些开源项目进行了一些改进。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content回答2:开源项目的解释 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content这个项目其实是在 github 上找到的一个开源项目主要是可以支持一些常规的聊天项目我对于聊天如何实现的比较感兴趣。顺便也想锻炼一下自己工程代码能力在网上就找到了这个开源项目和项目的一些比较完善的文档和介绍再加上找了一个业务场景租房。所以就确定了这个项目。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content回答3:学校课设的解释 这是学校的课设题目然后在课设项目的基础上查找了一些资料进行了一些改进。 这个项目为啥和上个(之前)同学的项目一样? 回答1:开源项目的回答 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content因为这个项目本身就是开源项目网上一搜都是好多都是这个项目的博客分析写得优质的主要就是那几篇可能我们参考了一样的博客讲解梳理框架吧。抽奖系统虽然听起来简单但实际上涉及到数据存储、状态转换、异常处理等多个技术点。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content回答2:学校课设的回答 这个问题面试官可能会直接的指出: 上个同学和你学校不同但是跟你的项目完全一样。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content这个项目确实是我们学校的开源项目但是我在实现的时候也在网上找了跟课设要求类似的开源项目而且发现网上针对这个类型的项目文档还听完善的可能其他的同学也是在网上跟我一样找到了类似的博客或开源项目进行借鉴的吧。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content注以下内容需要同学自己思考项目扩展如不清楚不建议参照话术容易给自己挖坑。说到上面的内容就可以了。不要使用课上讲解的扩展大家都说一样的也不行 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content但这个项目除了常规流程我还进行了功能扩展/性能优化/代码优化……(并解释一下扩展点) metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md}Created a chunk of size xxx, which is longer than the specified 100这表示分割时超出了我们设定的 chunk_size100 目标块大小。【在这里要说明这是一个在使用LangChain 的文本分割器时非常常见的问题。看到这个信息不要担心这不是错误而是预期的行为。】原因是为了保持语义的完整性当文本分割器用尽所有指定的分隔符都无法将一段文本分割到你的目标大小 chunk_size 以下时它会选择保留整个文本块而不是强行将其截断为无意义的片段因此我们会看到这个提示信息。因此我们可以看到被分割出来的段落基本上都是语义完整的一段话。那么分割逻辑到底是什么可以支持保持语义完整性尝试分割首先它尝试用 separator我们设置的是 \n\n 双换行这通常代表段落之间来分割文本。如果分割后的任何一个段落仍然大于 chunk_size它会继续下一步。如果仍然有单个单词或字符串的长度超过了 100分割器就陷入了两难境地选项A强行把这个长字符串在任意位置比如第100个字符处截断。但这会破坏单词、URL或数据的完整性导致生成无意义的片段例如把Christopher截断成Christop和her严重影响后续的嵌入或语言模型处理效果。选项B保留这个完整的、超长的字符串作为一个块并记录一条信息告知用户。那么很明显这里它选择了B选项。因此我们看到了 Created a chunk of size 128, which is longer than the specified 100 这条日志信息。如何应对和处理——增大 chunk_size如果我们的大部分块都超长可能是 chunk_size 设置得太小了尝试适当增大它。因此根据打印的日志可以发现被拆分的文本大都徘徊的100~200之间因此可以将chunk_size设置为200运行后可以看到超出的分割已经很少了。6.2.2 基于 Token长度拆分之前我们讲过LLM 大模型实际上并不是直接接收字符串而是需要先做 token 切分编码。这里我们可以借助【tiktoken 分词器】来进行 token 的切分编码。先看个例子给定一个文本字符串my name is LiHua!使用 【tiktoken 分词器】进行切分编码会得到什么结果import tiktoken # 定于cl100k_base编码方式的分词器 enc tiktoken.get_encoding(cl100k_base) # 进行切分编码 enc_output enc.encode(my name is LiHua!) # 打印结果 print(f编码后的token: {str(enc_output)}) for token in enc_output: print(f将token: {str(token)} 变成文本: {str(enc.decode_single_token_bytes(token))})cl100k_base是 tiktoken 分词器中的一种编码方式。gpt-4、gpt-3.5-turbo 等都采用这种切分编码方式。可以看到采用切分编码cl100k_base拆解后的文本字符串为[my, name, is, Li, H, ua, !]。token 编码表示为[2465, 836, 374, 14851, 39, 4381, 0]。以上跟大家介绍了基于 Token 拆分文本的基本方式主要就是了解设定了某种编码格式的 tiktoken 分词器可以进行文本拆分。那么接下来我们就可以使用根据cl100k_base编码方式的 tiktoken 分词器来拆分文档。这对于 OpenAI 模型来说会更准确。在LangChain中我们可以使用CharacterTextSplitter分割器的.from_tiktoken_encoder()方法来定义根据 tiktoken 分词器拆分文本的分割器代码如下所示from langchain_community.document_loaders import UnstructuredMarkdownLoader from langchain_text_splitters import CharacterTextSplitter markown_path ../Docs/Markdown/脚手架级微服务租房平台QA.md # single 模式加载后默认只有一个 Document 对象 loader UnstructuredMarkdownLoader(markown_path) data loader.load() # 生成分割器 text_splitter CharacterTextSplitter.from_tiktoken_encoder( encoding_namecl100k_base, chunk_size200, chunk_overlap50 ) # 分割文档 texts text_splitter.split_documents(data) # 打印前10个被分割出来的文档 for document in texts[:10]: print(* * 30) print(f{document}\n) # 输出 Created a chunk of size 916, which is longer than the specified 200 Created a chunk of size 916, which is longer than the specified 200 Created a chunk of size 260, which is longer than the specified 200 ****************************** page_content通用问题 为什么做这个项目 回答1出于兴趣爱好开发 大学期间我和同学在外合租过一段时间使用了一些租房平台于是我有个想法自己能不能开发一个租房平台可以让我将理论知识与实践相结合。我希望通过实际项目来加深对 Java 编程语言和相关技术的理解。于是我便查找了一些资料看了一些开源项目进行了一些改进。 回答2开源项目的解释 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content回答2开源项目的解释 这个项目其实是在 github 上找到的一个开源项目主要是可以支持一些常规的聊天项目我对于聊天如何实现的比较感兴趣。顺便也想锻炼一下自己工程代码能力在网上就找到了这个开源项目和项目的一些比较完善的文档和介绍再加上找了一个业务场景租房。所以就确定了这个项目。 ****************************** page_content回答3学校课设的解释 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content回答3学校课设的解释 这是学校的课设题目然后在课设项目的基础上查找了一些资料进行了一些改进。 这个项目为啥和上个(之前)同学的项目一样 回答1开源项目的回答 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content这个项目为啥和上个(之前)同学的项目一样? 回答1开源项目的回答 因为这个项目本身就是开源项目网上一搜都是好多都是这个项目的博客分析写得优质的主要就是那几篇可能我们参考了一样的博客讲解梳理框架吧。抽奖系统虽然听起来简单但实际上涉及到数据存储、状态转换、异常处理等多个技术点。 回答2学校课设的回答 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content回答2学校课设的回答 这个问题面试官可能会直接的指出上个同学和你学校不同但是跟你的项目完全一样。 这个项目确实是我们学校的开源项目但是我在实现的时候也在网上找了跟课设要求类似的开源项目而且发现网上针对这个类型的项目文档还挺完善的可能其他的同学也是在网上跟我一样找到了类似的博客或开源项目进行借鉴的吧。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content注以下内容需要同学自己思考项目扩展如不清楚不建议参照话术容易给自己挖坑。说到上面的内容就可以了。不要使用课上讲解的扩展大家都说一样的也不行 但这个项目除了常规流程我还进行了功能扩展/性能优化/代码优化……(并解释一下扩展点) 可以参考的回答思路即使面试官的指控让你感到不舒服也要尽量保持冷静和专注。无论情况如何保持专业和礼貌的态度是非常重要的。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content诚实面对 如果确实使用了代码而没有适当的引用或修改那么诚实地承认这一点可以说是从github上找的开源项目并解释你当时的想法和决策过程参考答案举例。同时如果抄袭代码被面试官发现要及时表明你已经认识到了这个问题并在未来的工作中会更加注意。 展示学习过程 如果是面试官发现项目确实有抄袭现象也可以说项目原本的一些问题你进行了优化解决体现自己有过思考并解释问题与优化思路。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content请求反馈 询问面试官对你的项目有什么具体的反馈或建议这表明你愿意学习和改进。 介绍一下这个项目。 回答一精简版 基于脚手架的微服务在线租房系统业务模型对标了贝壳、安居客、闲鱼等流行应用。无论是交互体验、架构设计还是数据模拟都达到真实的工业水准设计。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content本项目是一个 Java 综合项目涵盖【前端】与【后端】开发业务上包含房源管理、租户和房东沟通、房源上下架等整套业务流程。核心技术包括微服务、分布式集群、高并发、分布式对象存储、高速缓存、消息队列、即时通信、解决方案设计。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content后端采用 Spring Cloud 微服务架构引入脚手架将系统拆分为五个微服务。服务间借助 OpenFeign 实现相互调用。同时项目集成了 Nginx、Nacos、MySQL 等 10 多个主流 Java 后端组件技术栈丰富且前沿。 前端包含 Web管理端 和 微信小程序端基于 Vue 3 框架使用 Vite 构建工具以 JavaScript 为主要语言利用 Axios 高效交互数据并引入 Element-Plus 组件库让系统界面既实用又美观。C 端使用了微信小程序作为面向移动端应用入口。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md}同样为了保持语义的完整性文本分割器无法将一段文本分割到你的目标大小chunk_size以下它会选择保留整个文本块。6.2.3 硬性约束长度拆分如果我们就想要求任何块都不能超过指定大小可以使用RecursivecharacterTextSplitter类或RecursivecharacterTextSplitter.from_tiktoken_encoder方法它会严格遵守对块大小的硬约束。from langchain_community.document_loaders import UnstructuredMarkdownLoader from langchain_text_splitters import RecursiveCharacterTextSplitter markown_path ../Docs/Markdown/脚手架级微服务租房平台QA.md # single 模式加载后默认只有一个 Document 对象 loader UnstructuredMarkdownLoader(markown_path) data loader.load() # 生成分割器 text_splitter RecursiveCharacterTextSplitter.from_tiktoken_encoder( encoding_namecl100k_base, chunk_size100, chunk_overlap0, ) # 分割文档 texts text_splitter.split_documents(data) # 打印前10个被分割出来的文档 for document in texts[:10]: print(* * 30) print(f{document}\n) # 结果如下严格不超出指定块大小: ****************************** page_content通用问题 为什么做这个项目 回答1出于兴趣爱好开发 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content大学期间我和同学在外合租过一段时间使用了一些租房平台于是我有个想法自己能不能开发一个租房平台可以让我将理论知识与实践相结合。我希望通过实际项目来加深对 Java metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content编程语言和相关技术的理解。于是我便查找了一些资料看了一些开源项目进行了一些改进。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content回答2开源项目的解释 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content这个项目其实是在 github metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content上找到的一个开源项目主要是可以支持一些常规的聊天项目我对于聊天如何实现的比较感兴趣。顺便也想锻炼一下自己工程代码能力在网上就找到了这个开源项目和项目的一些比较完善的 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content文档和介绍再加上找了一个业务场景租房。所以就确定了这个项目。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content回答3学校课设的解释 这是学校的课设题目然后在课设项目的基础上查找了一些资料进行了一些改进。 这个项目为啥和上个(之前)同学的项目一样 回答1开源项目的回答 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content因为这个项目本身就是开源项目网上一搜都是好多都是这个项目的博客分析写得优质的主要就是那几篇可能我们参考了一样的博客讲解梳理框架吧。抽奖系统虽然听起来简单但实 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md} ****************************** page_content际上涉及到数据存储、状态转换、异常处理等多个技术点。 metadata{source: ../Docs/Markdown/脚手架级微服务租房平台QA.md}但这样其实是剥夺了一些保证语义完整性的能力可以看到某些含义相似的内容被强制分开。除此之外还要再说明的是文本内容是中文时使用默认分隔符列表[“\n\n”“n””“”]拆分文本可能会导致一个词组被拆分成两个字导致语义失效。若要将词组放在一起可以覆盖分隔符列表以包含其他标点符号例如中文的逗号、句号。或其他中文符号如下所示:text_splitter RecursiveCharacterTextSplitter( separators[ \n\n, \n, , 。, ,, , ], # Existing args )这样在分割时将递归用separators来尝试分割文本首先它尝试用\n\n双换行通常代表段落来分割如果分割后的任何一个段落仍然大于chunk_size它会继续下一步。接着它尝试用\n单换行通常代表行之间来分割那些仍然过大的段落。然后它尝试用 空格单词之间来分割。.....6.3 特殊文档结构拆分若对于代码等特殊文本可以尝试使用Language提供的不同的分割器效果会更好如PythonCodeTextSplitter、HTMLHeaderTextSplitter等它会理解代码的语法结构。这里了解下常见的拆分原则即可Markdown根据标头拆分例如#、##、###HTML使用标签拆分JSON按对象或数组元素拆分Code 代码按函数、类或逻辑块拆分这里我们以 Python 代码举例其他的使用姿势可以参考官网接口实际上用法与我们上面讲解的类似。from langchain_text_splitters import PythonCodeTextSplitter # 字符串文档 PYTHON_CODE def hello_world(): print(Hello, World!) def hello_python(): print(Hello, Python!) python_splitter PythonCodeTextSplitter(chunk_size50, chunk_overlap0) python_docs python_splitter.create_documents([PYTHON_CODE]) for document in python_docs[:2]: print(* * 30) print(f{document}\n) # 输出 ****************************** page_contentdef hello_world():\n print(Hello, World!) ****************************** page_contentdef hello_python():\n print(Hello, Python!)

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑