快速准确的文本语义分块Python库
semchunk是一个高效的Python文本分块库,能将文本分割成语义连贯的片段。与同类库相比,它在语义准确性和处理速度方面都有显著提升。该库采用先进的分块算法,兼容多种分词器和token计数工具,可处理单条或批量文本,并支持多进程加速。semchunk适用于大规模文本处理和各类自然语言分析任务。
<a href="https://pypi.org/project/semchunk/" alt="PyPI 版本"><img src="https://img.shields.io/pypi/v/semchunk"></a> <a href="https://github.com/umarbutler/semchunk/actions/workflows/ci.yml" alt="构建状态"><img src="https://img.shields.io/github/actions/workflow/status/umarbutler/semchunk/ci.yml?branch=main"></a> <a href="https://app.codecov.io/gh/umarbutler/semchunk" alt="代码覆盖率"><img src="https://img.shields.io/codecov/c/github/umarbutler/semchunk"></a> <a href="https://pypistats.org/packages/semchunk" alt="下载量"><img src="https://img.shields.io/pypi/dm/semchunk"></a>
semchunk
是一个快速轻量的Python库,用于将文本分割成语义有意义的块。
由于其复杂而高效的分块算法,semchunk
在语义准确性上比langchain.text_splitter.RecursiveCharacterTextSplitter
更优(参见工作原理🔍),同时也比semantic-text-splitter
快90%以上(参见基准测试📊)。
可以使用pip
安装semchunk
:
pip install semchunk
以下代码片段演示了如何使用semchunk
对文本进行分块:
import semchunk from transformers import AutoTokenizer # `transformers`和`tiktoken`都不是必需的, import tiktoken # 这里仅用于演示目的。 chunk_size = 2 # 这里使用较小的块大小仅用于演示。请注意, # 除非使用自定义token计数器,否则`semchunk`不会考虑特殊token, # 所以你可能需要将块大小减去tokenizer添加的特殊token数量。 text = 'The quick brown fox jumps over the lazy dog.' # 如下所示,`semchunk.chunkerify`接受所有OpenAI模型名称、OpenAI `tiktoken`编码和 # Hugging Face模型(按此优先顺序),以及具有`encode()`方法的自定义tokenizer #(如`tiktoken`、`transformers`和`tokenizers`的tokenizer),最后是任何能接受文本 # 并返回其token数量的函数。 chunker = semchunk.chunkerify('umarbutler/emubert', chunk_size) or \ semchunk.chunkerify('gpt-4', chunk_size) or \ semchunk.chunkerify('cl100k_base', chunk_size) or \ semchunk.chunkerify(AutoTokenizer.from_pretrained('umarbutler/emubert'), chunk_size) or \ semchunk.chunkerify(tiktoken.encoding_for_model('gpt-4'), chunk_size) or \ semchunk.chunkerify(lambda text: len(text.split()), chunk_size) # 生成的`chunker`可以处理单个文本或文本列表,分别返回块列表或块列表的列表。 assert chunker(text) == ['The quick', 'brown', 'fox', 'jumps', 'over the', 'lazy', 'dog.'] assert chunker([text], progress = True) == [['The quick', 'brown', 'fox', 'jumps', 'over the', 'lazy', 'dog.']] # 如果你有大量文本需要分块,且速度是一个考虑因素,你也可以通过将`processes`设置为大于1的数值来启用多进程。 assert chunker([text], processes = 2) == [['The quick', 'brown', 'fox', 'jumps', 'over the', 'lazy', 'dog.']]
def chunkerify( tokenizer_or_token_counter: str | tiktoken.Encoding | transformers.PreTrainedTokenizer | \ tokenizers.Tokenizer | Callable[[str], int], chunk_size: int = None, max_token_chars: int = None, memoize: bool = True, ) -> Callable[[str | Sequence[str], bool, bool], list[str] | list[list[str]]]:
chunkerify()
构建一个分块器,将一个或多个文本分割成由指定tokenizer或token计数器确定大小的语义有意义的块。
tokenizer_or_token_counter
可以是:tiktoken
或transformers
tokenizer的名称(优先考虑前者);具有encode
属性的tokenizer(例如tiktoken
、transformers
或tokenizers
的tokenizer);或返回输入token数量的token计数器。
chunk_size
是一个块可能包含的最大令牌数。它默认为None
,在这种情况下,它将被设置为与分词器的model_max_length
属性相同的值(减去尝试对空字符串进行分词返回的令牌数),如果可能的话;否则将引发ValueError
。
max_token_chars
是一个令牌可能包含的最大字符数。它用于显著加快长输入的令牌计数。它默认为None
,在这种情况下,要么不使用它,要么如果可能,将其设置为分词器词汇表中最长令牌的字符数,由token_byte_values
或get_vocab
方法确定。
memoize
标志是否对令牌计数器进行记忆化。它默认为True
。
此函数返回一个分块器,它接受单个文本或一系列文本,如果提供了单个文本,则返回最多chunk_size
个令牌长的块列表,去除用于分割文本的任何空白;如果提供了多个文本,则返回块的列表列表,每个内部列表对应于所提供输入文本之一的块。
生成的分块器可以传递一个processes
参数,指定在对多个文本进行分块时要使用的进程数。
还可以传递一个progress
参数,如果设置为True
并且传递了多个文本,将显示一个进度条。
从技术上讲,分块器将是semchunk.Chunker
类的一个实例,以协助类型提示,尽管这应该不会影响其使用方式。
def chunk( text: str, chunk_size: int, token_counter: Callable, memoize: bool = True, ) -> list[str]
chunk()
函数将文本分割成语义上有意义的块,大小由提供的令 牌计数器确定。
text
是要分块的文本。
chunk_size
是一个块可能包含的最大令牌数。
token_counter
是一个可调用对象,它接受一个字符串并返回其中的令牌数。
memoize
标志是否对令牌计数器进行记忆化。它默认为True
。
此函数返回最多chunk_size
个令牌长的块列表,去除用于分割文本的任何空白。
semchunk
通过递归分割文本,直到所有结果块等于或小于指定的块大小。具体而言,它:
为确保块在语义上尽可能有意义,semchunk
按以下优先顺序使用以下分割器:
\n
)和/或回车符(\r
)序列;\s
字符类定义);.
、?
、!
和*
);;
、,
、(
、)
、[
、]
、"
、"
、'
、'
、'
、"
和`
);:
、—
和…
);/
、\
、–
、&
和-
);