35 个版本 (14 个破坏性更新)
0.15.0 | 2024年8月11日 |
---|---|
0.14.1 | 2024年7月6日 |
0.14.0 | 2024年6月21日 |
0.8.1 | 2024年3月26日 |
0.4.2 | 2023年7月2日 |
32 在 文本处理 中排名
11,273 每月下载量
在 15 个 crates 中使用 (12 个直接使用)
140KB
2.5K SLoC
text-splitter
- Rust Crate: text-splitter
- Python 绑定: semantic-text-splitter(不幸的是无法获得相同的包名)
大型语言模型(LLMs)可以用于许多任务,但通常具有有限上下文大小,可能小于您可能希望使用的文档。为了使用较长的文档,您通常需要将文本拆分为块以适应此上下文大小。
此 crate 提供将较长的文本拆分为较小块的方法,旨在最大化所需的块大小,但尽可能在语义上合理的边界处拆分。
开始使用
将以下内容添加到您的项目中
cargo add text-splitter
按字符数量
使用此 crate 的最简单方法是使用默认实现,它使用字符计数作为块大小。
use text_splitter::TextSplitter;
// Maximum number of characters in a chunk
let max_characters = 1000;
// Default implementation uses character count for chunk size
let splitter = TextSplitter::new(max_characters);
let chunks = splitter.chunks("your document text");
使用 Hugging Face Tokenizer
需要启用 tokenizers
功能并将 tokenizers
添加到依赖项中。下面的示例还要求启用 tokenizers http
功能。
cargo add text-splitter --features tokenizers
cargo add tokenizers --features http
use text_splitter::{ChunkConfig, TextSplitter};
// Can also use anything else that implements the ChunkSizer
// trait from the text_splitter crate.
use tokenizers::Tokenizer;
let tokenizer = Tokenizer::from_pretrained("bert-base-cased", None).unwrap();
let max_tokens = 1000;
let splitter = TextSplitter::new(ChunkConfig::new(max_tokens).with_sizer(tokenizer));
let chunks = splitter.chunks("your document text");
使用 Tiktoken Tokenizer
需要启用 tiktoken-rs
功能并将 tiktoken-rs
添加到依赖项中。
cargo add text-splitter --features tiktoken-rs
cargo add tiktoken-rs
use text_splitter::{ChunkConfig, TextSplitter};
// Can also use anything else that implements the ChunkSizer
// trait from the text_splitter crate.
use tiktoken_rs::cl100k_base;
let tokenizer = cl100k_base().unwrap();
let max_tokens = 1000;
let splitter = TextSplitter::new(ChunkConfig::new(max_tokens).with_sizer(tokenizer));
let chunks = splitter.chunks("your document text");
使用范围指定块容量
您还可以指定块容量为范围。
一旦块达到长度在范围内,它将被返回。
可能返回的块小于 start
值,因为添加下一部分文本可能使其大于 end
容量。
use text_splitter::{ChunkConfig, TextSplitter};
// Maximum number of characters in a chunk. Will fill up the
// chunk until it is somewhere in this range.
let max_characters = 500..2000;
// Default implementation uses character count for chunk size
let splitter = TextSplitter::new(max_characters);
let chunks = splitter.chunks("your document text");
Markdown
上述所有示例也可以与Markdown文本一起工作。如果您启用markdown
功能,您可以使用与TextSplitter
相同的方式使用MarkdownSplitter
。
cargo add text-splitter --features markdown
use text_splitter::MarkdownSplitter;
// Maximum number of characters in a chunk. Can also use a range.
let max_characters = 1000;
// Default implementation uses character count for chunk size.
// Can also use all of the same tokenizer implementations as `TextSplitter`.
let splitter = MarkdownSplitter::new(max_characters);
let chunks = splitter.chunks("# Header\n\nyour document text");
代码
上述所有示例也可以与可以使用tree-sitter解析的代码一起工作。如果您启用code
功能,您可以使用与TextSplitter
相同的方式使用CodeSplitter
。
cargo add text-splitter --features code
cargo add tree-sitter-<language>
use text_splitter::CodeSplitter;
// Maximum number of characters in a chunk. Can also use a range.
let max_characters = 1000;
// Default implementation uses character count for chunk size.
// Can also use all of the same tokenizer implementations as `TextSplitter`.
let splitter = CodeSplitter::new(tree_sitter_rust::language(), max_characters).expect("Invalid tree-sitter language");
let chunks = splitter.chunks("your code file");
方法
为了在块中尽可能保留语义意义,每个块都由可以适合下一个给定块的最大的语义单元组成。对于每种拆分器类型,都有一组定义的语义级别。以下是一个使用步骤的示例
- 按递增语义级别拆分文本。
- 检查每个级别的第一个项目,并选择第一个项目仍然适合块大小的高级别。
- 将此级别或更高级别的相邻部分尽可能多地合并成一个块,以最大化块长度。合并时始终包含更高语义级别的边界,这样块就不会无意中跨越语义边界。
使用chunks
方法拆分文本时使用的边界,按升序排列
TextSplitter
语义级别
- 字符
- Unicode图形簇边界
- Unicode单词边界
- Unicode句子边界
- 新行序列的递增长度。(换行符是
\r\n
、\n
或\r
)每个连续换行符序列的唯一长度被视为其自己的语义级别。因此,2个换行符的序列比1个换行符的序列级别更高,依此类推。
拆分不会低于字符级别,否则可能会得到不完整的字符字节,这可能不是一个有效的Unicode字符串。
MarkdownSplitter
语义级别
Markdown按照CommonMark
规范进行解析,以及一些可选功能,如GitHub Flavored Markdown。
- 字符
- Unicode图形簇边界
- Unicode单词边界
- Unicode句子边界
- 软换行符(单个换行符),这不一定是一个Markdown中的新元素。
- 内联元素,如:文本节点、强调、加粗、删除线、链接、图片、表格单元格、内联代码、脚注引用、任务列表标记和内联HTML。
- 块元素,如:段落、代码块、脚注定义、元数据。还包括可以包含其他“块”类型元素的块引用或表格或列表中的行/项,以及包含项目的列表或表格。
- 主题分隔线或水平线。
- 按级别划分的标题
拆分不会低于字符级别,否则可能会得到不完整的字符字节,这可能不是一个有效的Unicode字符串。
CodeSplitter
语义级别
- 字符
- Unicode图形簇边界
- Unicode单词边界
- Unicode句子边界
- 语法树的递增深度。因此,函数的级别比函数内部的语句级别更高,依此类推。
拆分不会低于字符级别,否则可能会得到不完整的字符字节,这可能不是一个有效的Unicode字符串。
关于句子的说明
有许多确定句子分割的方法,准确度各不相同,许多需要ML模型来完成。我们不是试图找到完美的句子分割,而是依赖于Unicode句子边界的方法,在大多数情况下,如果段落太大,这种方法足以找到合理的语义分割点,并避免了许多其他方法带来的性能惩罚。
功能标志
文档格式支持
功能 | 描述 |
---|---|
code |
启用CodeSplitter 结构以通过tree-sitter解析器解析代码文档。 |
markdown |
启用MarkdownSplitter 结构以通过CommonMark 规范解析Markdown文档。 |
令牌化支持
依赖特征 | 支持的版本 | 描述 |
---|---|---|
rust_tokenizers |
^8.0.0 |
启用 (Text/Markdown)Splitter::new 接受提供的任何标记化器作为参数。 |
tiktoken-rs |
^0.5.0 |
启用 (Text/Markdown)Splitter::new 接受 tiktoken_rs::CoreBPE 作为参数。这对于为 OpenAI 模型分割文本很有用。 |
标记化器 |
^0.20.0 |
启用 (Text/Markdown)Splitter::new 接受 tokenizers::Tokenizer 作为参数。这对于分割具有 Hugging Face 兼容标记化器的文本模型很有用。 |
灵感
这个软件包受到 LangChain 的 TextSplitter 的启发。但是,在查看实现时,我们发现有可能在性能和语义块化方面有更好的表现。
向 unicode-rs 团队致以诚挚的感谢,他们开发的 unicode-segmentation 软件包管理了匹配单词和句子的 Unicode 规则的许多复杂性。
依赖项
~4–16MB
~170K SLoC