为什么需要文本分割(Chunking)

Picone上的一个博客,翻译过来学习一下,其中加入了一些个人的理解和调整,有兴趣更深入研究的可以看一下文章的原文。

为什么需要文本分割(Chunking)

在构建与LLM相关的应用程序时,Chunking是将大量文本分解为较小段的过程。这是很重要的一环,有助于优化从向量数据库中获得的LLM上下文嵌入内容的相关性。在这篇文章中,我们将探讨它是否以及如何有助于提高与LLM相关的应用程序中的效率和准确性。

如我们所知,我们在Pinecone中索引的任何内容都需要先进行嵌入(Embedded)。Chunking的主要目的是对上下文中的一个片段进行嵌入的过程中尽可能少的噪声,而还要保证内容仍然与语义相关。

例如,在语义搜索场景中,我们为一个文档集建立索引,每个文档都包含有关特定主题的宝贵信息。通过采用有效的分块(chunk)策略,可以确保搜索结果准确匹配用户查询的本意。如果我们的块太小会导致错过真正的相关内容,太大则可能导致搜索结果不准确。一般来说,如果一段文字脱离语境的上下文,对于人类来说仍然可以理解其含义,那么这段文字对于语言模型来说也是可以理解。因此,确定语料库中文档的最佳块大小对提高搜索结果准确性和相关性是非常重要的。

再举一个会话智能体(conversational agents)的例子(之前用Python和Javascript解释过)。使用知识库中嵌入的文本段构建一个让会话智能体使用的知识上下文。这种情况下,必须要对这些文本段作出正确的选择。有两个原因:

  • 首先,这决定嵌入的知识是否与我们的Prompt相关(Prompt中会嵌入真正的的用户问题)。
  • 其次,检索到文本的大小决定了我们是否能够将嵌入到要发送的上下文中传递给外部模型提供商(例如OpenAI),因为每个模型支持的发送Token的数量是有限的。 例如使用有32k上下文窗口的GPT-4,文本切分的问题可能不大。然而,在使用非常大的文本块时,仍需要谨慎处理,因为这可能对从Pinecone得到的结果的相关性产生负面影响。

这篇文章中,我们将探讨几种文本切分方法,并讨论在选择切分尺度和方式时应该考虑的权衡因素。最后,将给出一些建议,帮助确定最适合应用的文本切分尺度和方法。

Embedding大文本和小文本

当嵌入内容时,可以根据内容是简短(例如句子)还是长(例如文本段或整个文档)来设计不同的Embedding行为。

当一个句子被嵌入时,得到的向量会聚焦于该句子的特定含义。当用其他句子的嵌入进行搜索时,通常在这一层面上进行。这也意味着该嵌入可能会遗漏在文本段或文件中会找到的更宽泛的上下文信息。

当一个完整的段落或文档被嵌入时,嵌入过程要关注整体的上下文以及文本内部句子和短语之间的关系。这可能会产生一个更全面的向量表示,向量会表示出文本更广泛的含义和主题。另一方面,较大的输入文本尺寸可能会引入噪声、淡化单个句子或短语的重要性,使得在查询索引时找到精确匹配更困难。

查询的长度也影响着嵌入向量之间的关系。像一个单独的句子或短语这类较短的查询,会专注于具体内容,可能更适合与句子级别的嵌入进行匹配。一个跨越多个句子或一个段落的较长查询可能与段落或文档级别的嵌入更匹配,因为它可能在寻找更广泛的上下文或主题。

索引也可能是非均质的,并包含不同大小块的嵌入。这可能对查询结果的相关性提出挑战,但也可能有一些积极的影响。一方面,由于长短内容的语义表示之间的差异,查询结果的相关性可能会波动。另一方面,非均质索引可能能够更广泛地捕获上下文和信息,因为不同的块大小代表文本中不同级别的粒度。这可能更灵活地适应不同类型的查询。

分块的思路

确定最佳分块策略的有几个变量,这些变量因使用场景而异。以下是一些需要注意的问题:

  1. 索引内容的特性是什么? 是在处理长篇文档,如文章或书籍,还是较短的内容,如推文或即时消息?这个答案将决定哪种模型更适合目标,并因此决定应用哪种分块策略。
  2. 正在使用哪种嵌入模型,它在哪种块大小上表现最佳? 例如,句子转换模型在单个句子上表现良好,但像text-embedding-ada-002这样的模型在包含256或512个标记的块上表现更优。
  3. 对用户查询的长度和复杂度有什么期望? 用户的问题会简短并具体,还是长且复杂?这也可能影响你选择如何分块你的内容,以便嵌入的查询和嵌入的块之间有更紧密的关系。
  4. 应用中如何利用检索到的结果? 比如,检索的文本段将用于语义搜索、问题回答、摘要,还是其他目的?再比如,结果需要输入另一个有Token限制的LLM,那么必须根据LLM的限制确定召回的块的数量来限制整体输入的大小。 反思这些问题会促使我们制定在性能和准确性之间相对平衡分块策略,这将确保查询结果更加相关。

分块的方法

列出几个不同的Chuking方法,每种方法都有不同的适用场景。了解每种方法的优势和劣势,目标是正确的场景下使用正确的Chunking方法。

定长Chunking(Fixed-size chunking)

这是最常见,也是最直接的分块方法:简单地决定我们的块中的标记数量,并选择性地决定它们之间是否应该有任何重叠。一般来说,块之间应该保持一些重叠,以确保语义上下文不会在块之间丢失。在大多数常见情况下,固定大小的分块将是最佳路径。与其他形式的分块相比,固定大小的分块的计算代价较低且使用成本不高,因为它不需要使用任何NLP库。 LangChain中的一个Demo

python 复制代码
text = "..." # your text
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    separator = "\n\n",
    chunk_size = 256,
    chunk_overlap  = 20
)
docs = text_splitter.create_documents([text])

内容感知分片("Content-aware" Chunking)

这是一系列利用我们正在分块的内容性质并对其应用更复杂分块的方法。以下是一些例子:

句子分割

之前提到过,许多模型都被优化过,用于嵌入句子级内容。当然,我们会使用句子分块,并且有几种方法和工具可以达成目的,包括:

  • Naive splitting: 最简单方法是按(".")和换行符出现的频率分割句子。尽管这种方法直接快速,但这种方法不会考虑所有可能的产生的边界情况。一个很简单的实现例子:
python 复制代码
text = "..." # your text
docs = text.split(".")
    • NLTK: Natural Language Toolkit(NLTK)是一个流行的用于处理自然语言数据的Python库。它提供了一个句子分词器,可以将文本分为句子,可以更有意义的Chunking。例如,要将NLTK与Langchain一起使用,可以按照下面的例子实现:
python 复制代码
text = "..." # your text
from langchain.text_splitter import NLTKTextSplitter
text_splitter = NLTKTextSplitter()
docs = text_splitter.split_text(text)
  • spaCy: Spacy是另一个用于NLP任务的功能强大的Python库。它提供了一个复杂的句子细分功能,该功能可以有效地将文本分为单独的句子,从而可以在结果块中保存更好的上下文。要将Spacy与Langchain一起使用,可以按照下面的例子实现:
python 复制代码
text = "..." # your text
from langchain.text_splitter import SpacyTextSplitter
text_splitter = SpaCyTextSplitter()
docs = text_splitter.split_text(text)

递归Chunking(Recursive Chunking)

Recursive Chunking使用分层、迭代的概念形成一组分割器,用分割器将文本分割为较小的块。如果当前文本拆分出的段大小不满足需求大小,那么会递归地在带有不同的分离器或标准的结果块上继续调用,直到达到所需的块大小或结构为止。这意味着,尽管块的尺寸并不完全相同,但它们仍然与"预期"的尺寸相似。 下面是LangChain中的例子

python 复制代码
text = "..." # your text
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
    # Set a really small chunk size, just to show.
    chunk_size = 256,
    chunk_overlap  = 20
)

docs = text_splitter.create_documents([text])

固定格式的分割

Markdown和Latex是经常遇到的两个结构化、格式化内容的示例。在这中情况下,可以使用专门的Chunking方法来获取、分割内容。

  • Markdown: Markdown is a lightweight markup language commonly used for formatting text. By recognizing the Markdown syntax (e.g., headings, lists, and code blocks), you can intelligently divide the content based on its structure and hierarchy, resulting in more semantically coherent chunks. For example:
python 复制代码
from langchain.text_splitter import MarkdownTextSplitter
markdown_text = "..."

markdown_splitter = MarkdownTextSplitter(chunk_size=100, chunk_overlap=0)
docs = markdown_splitter.create_documents([markdown_text])
  • LaTex: LaTeX is a document preparation system and markup language often used for academic papers and technical documents. By parsing the LaTeX commands and environments, you can create chunks that respect the logical organization of the content (e.g., sections, subsections, and equations), leading to more accurate and contextually relevant results. For example:
python 复制代码
from langchain.text_splitter import LatexTextSplitter
latex_text = "..."
latex_splitter = LatexTextSplitter(chunk_size=100, chunk_overlap=0)
docs = latex_splitter.create_documents([latex_text])

确定应用中最佳的块大小

有一些经验可以帮助我们明确最佳的块尺寸,如果固定的块(例如固定的块)不容易应用您的用例,请使用最佳的块。

  • 预处理数据:在确定最佳的块大小之前,先预处理数据,保证数据质量。举个例子,如果数据是从网络上获取的,你可能需要删除HTML标签或其他特定元素标签,去掉所有噪音。
  • 决定一个块的尺寸范围: 预处理数据后,下一步就是选择一些尺寸进行测试。如前所述,尺寸的选择需要考虑内容的性质(例如,短消息或冗长的文档)、LLM的限制(例如令牌限制)。目的是在保留环境和保持准确性之间找到平衡。首先探索各种尺寸,包括较小的块(例如128或256Token),以捕获更多的粒状语义信息和较大的块(例如512或1024代币),以保留更多上下文。
  • Evaluating the Performance of Each Chunk Size - In order to test various chunk sizes, you can either use multiple indices or a single index with multiple namespaces. With a representative dataset, create the embeddings for the chunk sizes you want to test and save them in your index (or indices). You can then run a series of queries for which you can evaluate quality, and compare the performance of the various chunk sizes. This is most likely to be an iterative process, where you test different chunk sizes against different queries until you can determine the best-performing chunk size for your content and expected queries.、

原文链接:Chunking Strategies for LLM Applications

之后会整理更多学习、工作中遇到的问题和思考,欢迎大家关注Global AI Pro

相关推荐
PhoenixAI86 分钟前
AI绘画-Stable Diffusion 原理介绍及使用
人工智能·python·机器学习·ai作画·stable diffusion
B站计算机毕业设计超人1 小时前
计算机毕业设计Flink+Hadoop广告推荐系统 广告预测 广告数据分析可视化 广告爬虫 大数据毕业设计 Spark Hive 深度学习 机器学
大数据·hadoop·机器学习·spark·课程设计·数据可视化·推荐算法
MUKAMO1 小时前
【深度学习】图形模型基础(2):概率机器学习模型与人工智能
人工智能·深度学习·机器学习
zhangbin_2372 小时前
【Python机器学习】模型评估与改进——二分类指标
大数据·人工智能·python·学习·机器学习·分类·数据挖掘
1234567今天你有没有摸鱼2 小时前
《昇思25天学习打卡营第02天|快速入门》
深度学习·学习·机器学习·mindspore
qq_393060472 小时前
mindspore打卡机器学习正则化与优化器
人工智能·机器学习
幻兽帕鲁3 小时前
需求预测算法面试
人工智能·算法·机器学习
绎岚科技3 小时前
贝叶斯回归器概览
深度学习·算法·机器学习·回归
刘好念3 小时前
[机器学习]False Positive和False Negative
人工智能·算法·机器学习
HSunR4 小时前
线性代数笔记
笔记·线性代数·机器学习