文本分割的艺术:从基础到高级的语言模型技术

2024年12月24日 由 alex 发表 47 0

文本分割是使用语言模型 (LLM) 时一个至关重要但经常被忽视的方面。在本文中,我们将探讨文本分割的五个级别,特别关注塑造 AI 应用程序未来的先进技术。


介绍

在使用大型语言模型(LLM)时,数据的准备和分割方式会显著影响性能。正如该领域所强调的,“你的目标不是为了分割而分割,而是为了让数据以能够在日后提取出价值的格式存在。”


文本分割的演变


第一级:字符分割

字符分割是文本分割的最基本形式,它根据固定的字符数将文本分割成块。


# Example implementation using LangChain
from langchain_text_splitters import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    chunk_size=35,
    chunk_overlap=0,
    separator=""
)
text = "This is the text I would like to chunk up. It is an example text for this exercise."
chunks = text_splitter.split_text(text)


优点:

  • 实现简单
  • 分块大小可预测
  • 处理开销最小


缺点:

  • 经常在句子中间断开单词
  • 忽略自然的文本边界
  • 不适合语义理解
  • 在生产环境中很少使用


第二级:递归字符分割

这是一种更智能的方法,它使用分层分隔符来尊重文本结构。


from langchain_text_splitters pimport RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
    separators=["\n\n", "\n", " ", ""],
    chunk_size=1000,
    chunk_overlap=200,
    length_function=len,
)
# Example text with natural boundaries
text = """
Chapter 1: Introduction
AI is transforming rapidly.
We need to adapt quickly.
The future is exciting.
Innovation continues daily.
"""
chunks = splitter.split_text(text)


关键特性:

  • 尊重文档结构
  • 使用多级分隔符
  • 保持段落完整性
  • 可配置的块重叠
  • 许多应用的行业标准


使用场景:

  • 一般文档
  • 文章和博客帖子
  • 电子邮件内容
  • 标准文本文档


第三级:特定文档分割

特定文档分割代表了文本分块策略的一次重大演进,它认识到不同类型的文档需要量身定制的方法以实现最佳处理。与基本字符分割的一刀切方法不同,这一级别适应了各种文档格式的独特结构和特征。


Markdown文档:

在处理Markdown文件时,分割策略会尊重标题和格式的层次结构。可以将其想象成书中的章节,每个主要部分(H1)可能包含子部分(H2、H3),并在保留文档逻辑流程的同时自然断开。系统会识别Markdown特定的元素,如:

  • 标题层次结构
  • 代码块
  • 列表和嵌套列表
  • 块引用
  • 表格结构


from langchain_text_splitter import MarkdownTextSplitter
markdown_document = "# Foo\n\n    ## Bar\n\nHi this is Jim\n\nHi this is Joe\n\n ### Boo \n\n Hi this is Lance \n\n ## Baz\n\n Hi this is Molly"
headers_to_split_on = [
    ("#", "Header 1"),
    ("##", "Header 2"),
    ("###", "Header 3"),
]
markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on)
md_header_splits = markdown_splitter.split_text(markdown_document)
md_header_splits


[Document(page_content='Hi this is Jim  \nHi this is Joe', metadata={'Header 1': 'Foo', 'Header 2': 'Bar'}),'Hi this is Jim  \nHi this is Joe', metadata={'Header 1': 'Foo', 'Header 2': 'Bar'}),
 Document(page_content='Hi this is Lance', metadata={'Header 1': 'Foo', 'Header 2': 'Bar', 'Header 3': 'Boo'}),
 Document(page_content='Hi this is Molly', metadata={'Header 1': 'Foo', 'Header 2': 'Baz'})]


Python 代码:


from langchain_text_splitter import PythonCodeTextSplitter
python_text = """
class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age
p1 = Person("John", 36)
for i in range(10):
    print (i)
"""
code_splitter = PythonCodeTextSplitter(
    chunk_size=100, chunk_overlap=0,
)
code_splitter.create_documents([python_text])


[Document(metadata={}, page_content='class Person:\n  def __init__(self, name, age):\n    self.name = name\n    self.age = age'),Document(metadata={}, page_content='class Person:\n  def __init__(self, name, age):\n    self.name = name\n    self.age = age'),
 Document(metadata={}, page_content='p1 = Person("John", 36)\n\nfor i in range(10):\n    print (i)')]


PDF处理:


#!pip3 install "unstructured[all-docs]"
from typing import Any
from pydantic import BaseModel
from unstructured.partition.pdf import partition_pdf
# Get elements
raw_pdf_elements = partition_pdf(
    filename="document.pdf",
    
    # Using pdf format to find embedded image blocks
    extract_images_in_pdf=True,
    
    # Use layout model (YOLOX) to get bounding boxes (for tables) and find titles
    # Titles are any sub-section of the document
    infer_table_structure=True,
    
    # Post processing to aggregate text once we have the title
    chunking_strategy="by_title",
    # Chunking params to aggregate text blocks
    # Attempt to create a new chunk 3800 chars
    # Attempt to keep chunks > 2000 chars
    # Hard max on chunks
    max_characters=4000,
    new_after_n_chars=3800,
    combine_text_under_n_chars=2000,
    image_output_dir_path="static/pdfImages/",
)


特殊考虑因素:


表格:

  • 以HTML/Markdown表格形式提取
  • 保留结构以供大型语言模型(LLM)理解
  • 保持列间关系


图片:

  • 单独提取并处理
  • 生成文本描述
  • 链接到原始上下文


代码:

  • 保留函数边界
  • 保持类层次结构
  • 将import语句放在一起


第四级:语义分割——超越结构,深入意义

语义分割代表了我们在为语言模型进行文档分块时的方法上的范式转变。不同于依赖物理文本结构的传统方法,语义分割深入探索内容中的实际意义和关系。它采用了两种复杂的方法:

  • 带位置奖励的层次聚类和带缓冲区分析的顺序比较。第一种方法为每个句子生成嵌入,并根据语义相似性对它们进行聚类,同时添加一个“位置奖励”以保持文档的逻辑流程。这种方法在处理短句跟随长句时特别有效,确保它们保持在上下文中。
  • 顺序比较方法则采用不同的方法,它创建重叠的句子组,并分析它们之间的语义距离。通过研究嵌入距离并使用95百分位阈值来确定显著的语义转变,从而识别出自然的断点。这可以想象为找到话题转变的自然“接合点”,就像熟练的屠夫知道沿着肉的天然缝隙切割一样。他绘制这些距离以可视化语义转变,从而清晰地展示出内容自然分割的位置。这种方法之所以特别强大,是因为它能够适应内容的复杂性,而不是依赖僵硬的规则。虽然它比更简单的方法需要更多的计算资源,但它产生的分块更有意义,更好地保留了上下文和关系。在处理复杂文档时,这种方法尤其有价值,因为在这些文档中,话题的转换并不总是由标题或段落等结构元素清晰地标记出来。随着语言模型的不断发展和计算资源的日益普及,语义分割越来越代表着智能文档处理的未来。


16


17


第五级:主体分割——智能文本处理的未来

主体分割代表了文本处理技术的最前沿,它模仿了人类如何自然地组织和理解内容。这一方法的核心在于首先将文本分解成“命题”——这些命题是可以独立存在同时保持其意义的独立陈述。例如,一个复杂的句子“约翰去了商店,在那里他买了牛奶”会被分解成两个清晰的命题:“约翰去了商店”和“约翰买了牛奶”。然后,系统会调用一个人工智能主体,该主体会就如何将这些命题组合在一起做出智能决策。这一方法的革命性在于其块管理系统,该系统为每个命题组维护了丰富的元数据。每个块都会获得一个唯一标识符、一个随着内容添加而动态变化的标题,以及一个捕捉其内容精髓的详细摘要。该主体会不断将新命题与现有块进行比较,根据语义相关性和上下文来决定是创建新块还是添加到现有块中。这一过程不仅仅是关于将相似内容分组,更是关于理解不同信息片段之间的关系,并通过元数据维护这些联系。虽然主体分割比传统方法需要更多的计算资源,但它能产生极其连贯且上下文感知的块。该系统能够适应复杂文档,理解细微的话题转变,并维护简单方法可能会忽略的上下文关系。可以将其想象为拥有一个智能助手,它不仅能够帮助你组织文档,还能理解不同信息片段之间错综复杂的关系网。随着语言模型变得越来越复杂,计算成本不断降低,这种方法代表着我们未来处理和理解复杂文档的方式。


18


结论

文本分割技术正在从简单的基于字符的方法向复杂的由人工智能驱动的方法演变。虽然像语义分割和主体分割这样的高级技术目前需要更多的资源,但它们代表着语言模型文档处理的未来。恰当地理解和实施这些方法可以显著提高大型语言模型(LLM)应用的性能。


关键在于要记住,目标不仅仅是分割文本,而是以一种能够最大化语言模型有效理解和处理内容能力的方式来准备文本。

文章来源:https://medium.com/@kargarisaac/the-art-of-text-splitting-from-basic-to-advanced-techniques-for-language-models-3842f07c5c42
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
写评论取消
回复取消