大模型(LLMs)RAG 版面分析------文本分块面

一、为什么需要对文本分块?

使用大型语言模型(LLM)时,切勿忽略文本分块的重要性,其对处理结果的好坏有重大影响。

考虑以下场景:你面临一个几百页的文档,其中充满了文字,你希望对其进行摘录和问答式处理。在这个流程中,最初的一步是提取文档的嵌入向量,但这样做会带来几个问题:

  • 信息丢失的风险:试图一次性提取整个文档的嵌入向量,虽然可以捕捉到整体的上下文,但也可能会忽略掉许多针对特定主题的重要信息,这可能会导致生成的信息不够精确或者有所缺失。

  • 分块大小的限制:在使用如OpenAI这样的模型时,分块大小是一个关键的限制因素。例如,GPT-4模型有一个32K的窗口大小限制。尽管这个限制在大多数情况下不是问题,但从一开始就考虑到分块大小是很重要的。

因此,恰当地实施文本分块不仅能够提升文本的整体品质和可读性,还能够预防由于信息丢失或不当分块引起的问题。这就是为何在处理长篇文档时,采用文本分块而非直接处理整个文档至关重要的原因。

二、能不能介绍一下常见的文本分块方法?

一般的文本分块方法

如果不借助任何包,直接按限制长度切分方案:

text = "我是一个名为 ChatGLM3-6B 的人工智能助手,是基于清华大学 KEG 实验室和智谱 AI 公司于 2023 年共同训练的语言模型开发的。我的目标是通过回答用户提出的问题来帮助他们解决问题。由于我是一个计算机程序,所以我没有实际的存在,只能通过互联网来与用户交
流 。 " chunks = []
chunk_size = 128 
for i in range(0, len(text), chunk_size):chunk = text[i:i + chunk_size]chunks.append(chunk) chunks
>>> ['我是一个名为 ChatGLM3-6B 的人工智能助手,是基于清华大学 KEG 实验室和智谱 AI 公司于 2023 年共同训练的语言模型开发的。我的目标是通过回答用户提出的问题来帮助他们解决问题。由于我是一个计算机程序,所以我没有实际的存在,只能通过互联网','来与用户交流。'
]

正则拆分的文本分块方法

  • 动机:【一般的文本分块方法】能够按长度进行分割,但是对于一些长度偏长的句子,容易从中间切开;

  • 方法:在中文文本分块的场景中,正则表达式可以用来识别中文标点符号,从而将文本拆分成单独的句子。这种方法依赖于中文句号、“问号”、"感叹号"等标点符号作为句子结束的标志。

  • 特点:虽然这种基于模式匹配的方法可能不如基于复杂语法和语义分析的方法精确,但它在大多数情况下足以满足基本的句子分割需求,并且实现起来更为简单直接。

import redef split_sentences(text):# 使用正则表达式匹配中文句子结束的标点符号sentence_delimiters = re.compile(u'[。?!;]|\n')sentences = sentence_delimiters.split(text)# 过滤掉空字符串sentences = [s.strip() for s in sentences if s.strip()]return sentencestext ="文本分块是自然语言处理(NLP)中的一项关键技术,其作用是将较长的文本切割成更小、更易于处理的片段。这种分割通常是基于单词的词性和语法结构,例如将文本拆分为名词   短语、动词短语或其他语义单位。这样做有助于更高效地从文本中提取关键信息。" sentences = split_sentences(text)
print(sentences)>>>
#output ['文本分块是自然语言处理(NLP)中的一项关键技术,其作用是将较长的文本切割成更  小、更易于处理的片段', '这种分割通常是基于单词的词性和语法结构,例如将文本拆分为名词短语、动词短语或其  他语义单位', '这样做有助于更高效地从文本中提取关键信息'
]

在上面例子中,我们并没有采用任何特定的方式来分割句子。另外,还有许多其他的文本分块技术 可以使用,例如词汇化(tokenizing)、词性标注(POS tagging)等。

使用正则表达式匹配中文句子结束的标点符号

sentence_delimiters = re.compile(u’[。?!;]|\n’)

sentences = sentence_delimiters.split(text)

过滤掉空字符串

sentences = [s.strip() for s in sentences if s.strip()]

return sentences

text = “文本分块是自然语言处理(NLP)中的一项关键技术,其作用是将较长的文本切割成更小、更易于处理的片段。这种分割通常是基于单词的词性和语法结构,例如将文本拆分为名词短语、动词短语或其他语义单位。这样做有助于更高效地从文本中提取关键信息。”
sentences = split_sentences(text)

print(sentences)

#output [

‘文本分块是自然语言处理(NLP)中的一项关键技术,其作用是将较长的文本切割成更小、更易于处理的片段’,

‘这种分割通常是基于单词的词性和语法结构,例如将文本拆分为名词短语、动词短语或其他语义单位’,

‘这样做有助于更高效地从文本中提取关键信息’

]

在上面例子中,我们并没有采用任何特定的方式来分割句子。另外,还有许多其他的文本分块技术可以使用,例如词汇化(tokenizing)、词性标注(POS tagging)等。

Spacy Text Splitter 方法

  • 介绍:Spacy是一个用于执行自然语言处理(NLP)各种任务的库。它具有文本拆分器功能,能够在进行文本分割的同时,保留分割结果的上下文信息。
import spacy 
input_text = "文本分块是自然语言处理(NLP)中的一项关键技术,其作用是将较长的文本切割成更小、更易于处理的片段。这种分割通常是基于单词的词性和语法结构,例如将文本拆分为名词短语、动词短语或其他语义单位。这样做有助于更高效地从文本中提取关键信息。"  nlp = spacy.load( "zh_core_web_sm" ) doc = nlp(input_text) 
for s in doc.sents: print (s)
>>> ['文本分块是自然语言处理(NLP)中的一项关键技术,其作用是将较长的文本切割成更  小、更易于处理的片段。',"这种分割通常是基于单词的词性和语法结构,例如将文本拆分为名词短语、动词短语或其  他语义单位。","这样做有助于更高效地从文本中提取关键信息。"
]

基于 langchain 的 CharacterTextSplitter 方法

使用CharacterTextSplitter,一般的设置参数为:chunk_size、chunk_overlap、separator和strip_whitespace。

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(chunk_size = 35, chunk_overlap=0, separator='', strip_whitespace=False) text_splitter.create_documents([text])
>>> [Document(page_content='我是一个名为 ChatGLM3-6B 的人工智能助手,是基于清华大学'),Document(page_content='KEG 实验室和智谱 AI 公司于 2023 年共同训练的语言模型开发'),Document(page_content='的。我的目标是通过回答用户提出的问题来帮助他们解决问题。  由于我是一个计'),Document(page_content='算机程序,所以我没有实际的存在,只能通过互联网来与用户交 流。')
]

基于 langchain 的 递归字符切分 方法

使用RecursiveCharacterTextSplitter,一般的设置参数为:chunk_size、chunk_overlap。

#input text
input_text = "文本分块是自然语言处理(NLP)中的一项关键技术,其作用是将较长的文本切割成更小、更易于处理的片段。这种分割通常是基于单词的词性和语法结构,例如将文本拆分为名词短语、动词短语或其他语义单位。这样做有助于更高效地从文本中提取关键信息。"  from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size = 100 , #设置所需的文本大小chunk_overlap = 20 ) chunks = text_splitter.create_documents([input_text]) print (chunks)>>> [Document(page_content='文本分块是自然语言处理(NLP)中的一项关键技术,其作用是   将较长的文本切割成更小、更易于处理的片段。这种分割通常是基于单词的词性和语法结构,   例如将文本拆分为名词短语、动词短语或其他语义单位。这样做有助'), Document(page_content='短语、动词短语或其他语义单位。这样做有助于更高效地从文本  中提取关键信息。')]

与CharacterTextSplitter不同,RecursiveCharacterTextSplitter不需要设置分隔符,默认的几个分隔符如下:

"\n\n" - 两个换行符,一般认为是段落分隔符"\n" - 换行符
" " - 空格
"" - 字符

拆分器首先查找两个换行符(段落分隔符)。一旦段落被分割,它就会查看块的大小,如果块太大,那么它会被下一个分隔符分割。如果块仍然太大,那么它将移动到下一个块上,以此类推。

HTML 文本拆分 方法

  • 介绍:HTML文本拆分器是一种结构感知的文本分块工具。它能够在HTML元素级别上进行文本拆分,并且会为每个分块添加与之相关的标题元数据。

  • 特点:对HTML结构的敏感性,能够精准地处理和分析HTML文档中的内容。

#input html stringhtml_string = """ 
<!DOCTYPE html> 
<html> 
<body> <div> <h1>Mobot</h1> <p>一些关于Mobot的介绍文字。</p> <div> <h2>Mobot主要部分</h2> <p>有关Mobot的一些介绍文本。</p> <h3>Mobot第1小节</h3> <p>有关Mobot第一个子主题的一些文本。</p> <h3>Mobot第2小节</h3> <p>关于Mobot的第二个子主题的一些文字。</p> </div> <div> <h2>Mobot</h2> <p>关于Mobot的一些文字</p> </ div> <br> <p>关于Mobot的一些结论性文字</p> </div> 
</body> 
</html> """headers_to_split_on = [ ( "h1" , "Header 1" ), ( "h2" , "标题 2" ), ( "h3" , "标题 3" ), 
] from langchain.text_splitter import HTMLHeaderTextSplitter 
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on) html_header_splits = html_splitter.split_text(html_string) print(html_header_split)>>> [Document(page_content='Mobot'), Document(page_content='一些关于Mobot的介绍文字。\nMobot主要部分 Mobot第1小节Mobot第2小节', metadata={'Header 1': 'Mobot'}), Document(page_content='有关Mobot的一些介绍文本。', metadata={'Header 1': 'Mobot', '标题 2': 'Mobot主要部分'}), Document(page_content='有关Mobot第一个子主题的一些文本。', metadata={'Header 1': 'Mobot', '标题 2': 'Mobot主要部分', '标题 3': 'Mobot第1小节'}), Document(page_content='关于Mobot的第二个子主题的一些文字。', metadata={'Header 1': 'Mobot', '标题 2': 'Mobot主要部分', '标题 3': 'Mobot第2小节'}), Document(page_content='Mobot div>', metadata={'Header 1': 'Mobot'}), Document(page_content='关于Mobot的一些文字 \n关于Mobot的一些结论性文字', metadata={'Header 1': 'Mobot', '标题 2': 'Mobot'})
]

仅提取在header_to_split_on参数中指定的HTML标题。

Mrrkdown 文本拆分 方法

  • 介绍:Markdown文本拆分是一种根据Markdown的语法规则(例如标题、Bash代码块、图片和列表)进行文本分块的方法。

  • 特点:具有对结构的敏感性,能够基于Markdown文档的结构特点进行有效的文本分割。

markdown_text = '# Mobot\n\n ## Stone\n\n这是python \n这是\n\n ## markdown\n\n 这是中文文本拆分'from langchain.text_splitter import MarkdownHeaderTextSplitter headers_to_split_on = [("#", "Header 1"),("##", "Header 2"),("###", "Header 3"),
]markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on) md_header_splits = markdown_splitter.split_text(markdown_text) print(md_header_splits)>>> [Document(page_content='这是python\n这是', metadata={'Header 1': 'Mobot', 'Header 2': 'Stone'}), Document(page_content='这是中文文本拆分', metadata={'Header 1': 'Mobot', 'Header 2': 'markdown'})
]

MarkdownHeaderTextSplitter 能够根据设定的 headers_to_split_on 参数,将 Markdown 文本进行拆分。这一功能使得用户可以便捷地根据指定的标题将 Markdown 文件分割成不同部分,从而提高编辑和管理的效率。

Python代码拆分 方法

python_text = """ class Person:def init (self, name, age):self.name = nameself.age = age
p1 = Person("John", 36) for i in range(10):print (i)"""from langchain.text_splitter import PythonCodeTextSplitter python_splitter = PythonCodeTextSplitter(chunk_size=100, chunk_overlap=0)python_splitter.create_documents([python_text])
>>> [Document(page_content='class Person:\n def init (self, name, age):\n self.name = name\n self.age = age'),Document(page_content='p1 = Person("John", 36)\n\nfor i in range(10):\n print (i)')
]

LaTex 文本拆分 方法

LaTex文本拆分工具是一种专用于代码分块的工具。它通过解析LaTex命令来创建各个块,这些块按照逻辑组织,如章节和小节等。这种方式能够产生更加准确且与上下文相关的分块结果,从而有效地提升LaTex文档的组织和处理效率。

#input Latex stringlatex_text = """documentclass{article}begin{document}maketitlesection{Introduction}
大型语言模型 (LLM)
是一种机器学习模型,可以在大量文本数据上进行训练,以生成类似人类的语言。近年来,法学硕士在各种自然语言处理任务中取得了重大进展,包括语言翻译、文本生成和情感分析。subsection{法学硕士的历史}最早的法学硕士是在
20 世纪 80 年代开发的和 20 世纪 90
年代,但它们受到可处理的数据量和当时可用的计算能力的限制。然而,在过去的十年中,硬件和软件的进步使得在海量数据集上训练法学硕士成为可能,从而导致subsection{LLM
的应用}LLM
在工业界有许多应用,包括聊天机器人、内容创建和虚拟助理。它们还可以在学术界用于语言学、心理学和计算语言学的研究。end{document}"""from langchain.text_splitter import LatexTextSplitterLatex_splitter = LatexTextSplitter(chunk_size= 100 , chunk_overlap= 0 )latex_splits = Latex_splitter.create_documents([latex_text]) print (latex_splits)>>> [Document(page_content='documentclass{article}begin{document}maketitlesection{Introduction}大型语言模型 (LLM)'),Document(page_content='是一种机器学习模型,可以在大量文本数据上进行训练,以生成类似人类的语言。近年来,法学硕士在各种自然语言处理任务中取得了重大进展,包括语言翻译、文本生成和情感分析。subsection{法学硕士的历史'),Document(page_content='}最早的法学硕士是在'),Document(page_content='20 世纪 80 年代开发的和 20 世纪 90'),Document(page_content='年代,但它们受到可处理的数据量和当时可用的计算能力的限制。然而,在过去的十年中,硬件和软件的进步使得在海量数据集上训练法学硕士成为可能,从而导致subsection{LLM 的应用}LLM'),Document(page_content='在工业界有许多应用,包括聊天机器人、内容创建和虚拟助理。它们还可以在学术界用于语言学、心理学和计算语言学的研究。end{document}')]

在上述示例中,我们注意到代码分割时的重叠部分设置为0。这是因为在处理代码分割过程中,任何重叠的代码都可能完全改变其原有含义。因此,为了保持代码的原始意图和准确性,避免产生误解或错误,设置重叠部分为0是必要的。

当你决定使用哪种分块器处理数据时,重要的一步是提取数据嵌入并将其存储在向量数据库(Vector DB)中。上面的例子中使用文本分块器结合 LanceDB 来存储数据块及其对应的嵌入。LanceDB 是一个无需配置、开源且无服务器的向量数据库,其数据持久化在硬盘驱动器上,允许用户在不超出预算的情况下实现扩展。此外,LanceDB 与 Python 数据生态系统兼容,因此你可以将其与现有的数据工具(如 pandas、pyarrow 等)结合使用。

总结

本文详细介绍了大模型(LLMs)在RAG(Retrieval-Augmented Generation)应用中的文本分块技术。文章首先阐述了为什么需要对文本进行分块,强调了信息丢失和分块大小限制的问题。接着,文章介绍了多种常见的文本分块方法,包括一般的文本分块方法、正则拆分的文本分块方法、Spacy Text Splitter方法、基于langchain的CharacterTextSplitter和递归字符切分方法、HTML文本拆分方法、Markdown文本拆分方法、Python代码拆分方法和LaTex文本拆分方法。每种方法都有其特定的应用场景和优势,文章通过示例代码展示了如何实现这些方法。最后,文章强调了在处理长篇文档时,采用适当的文本分块技术的重要性,并介绍了如何将分块后的数据存储在向量数据库中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61097.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Python制作动态爱心粒子特效》

一、实现思路 粒子效果&#xff1a; – 使用Pygame模拟粒子运动&#xff0c;粒子会以爱心的轨迹分布并运动。爱心公式&#xff1a; 爱心的数学公式&#xff1a; x16sin 3 (t),y13cos(t)−5cos(2t)−2cos(3t)−cos(4t) 参数 t t 的范围决定爱心形状。 动态效果&#xff1a; 粒子…

免费实时图片编辑工具:MagicQuill

参看&#xff1a; https://huggingface.co/spaces/AI4Editing/MagicQuill 人工智能交互式图像编辑&#xff1a;可以制定涂改增加删除

web——upload-labs——第九关——特殊字符::$DATA绕过

特殊字符::$DATA绕过 典型绕过场景 在一些系统中&#xff0c;::$DATA 被用于绕过文件路径的限制。比如&#xff1a; 路径过滤绕过&#xff1a;如果系统有某种机制来检查和限制文件路径&#xff08;例如&#xff0c;禁止访问某些系统目录或敏感文件&#xff09;&#xff0c;通…

本地部署 excalidraw

本地部署 excalidraw 0. 引言1. 本地部署 excalidraw2. 访问 excalidraw 0. 引言 Excalidraw 编辑器是一款开源虚拟手绘白板&#xff0c;支持协作且端到端加密。 1. 本地部署 excalidraw git clone https://github.com/excalidraw/excalidraw.git; cd excalidrawvi docker-c…

《Java核心技术 卷I》用户界面AWT事件继承层次

AWT事件继承层次 EventObject类有一个子类AWTEvent&#xff0c;它是所有AWT事件类的父类。 Swing组件会生成更多其他事件对象&#xff0c;都直接拓展自EventObject而不是AWTEvent。 AWT将事件分为底层(low-level)事件和语义事件。 语义事件&#xff1a;表示用户的动作事件&…

三周精通FastAPI:42 手动运行服务器 - Uvicorn Gunicorn with Uvicorn

官方文档&#xff1a;Server Workers - Gunicorn with Uvicorn - FastAPI 使用 fastapi 运行命令 可以直接使用fastapi run命令来启动FastAPI应用&#xff1a; fastapi run main.py如创建openapi.py文件&#xff1a; from fastapi import FastAPIapp FastAPI(openapi_url&…

整理iPhone空间:iphone怎么删除相簿

随着时间的积累&#xff0c;我们的iPhone中不仅会堆积大量照片&#xff0c;还可能会有多个不再需要的相簿。这些相簿不仅占用存储空间&#xff0c;还可能使相册应用变得杂乱无章。本文将探讨iphone怎么删除相簿&#xff0c;并介绍精简iPhone相册的技巧&#xff0c;使你的相册管…

路漫漫其修远兮,吾将上下而求索---第一次使用github的过程记录和个人感受

文章目录 1.仓库位置2.新建仓库3.配置仓库4.克隆和上传5.推荐文章和我的感受 1.仓库位置 这个仓库的位置就是在我们的这个个人主页的右上角&#xff1b;如果是第一次注册账号的话&#xff0c;这个主页里面肯定是不存在仓库的&#xff0c;需要我们自己手动的进行创建&#xff1…

ICML24最新开源时序基础模型MOMENT

论文标题&#xff1a;MOMENT: A Family of Open Time-series Foundation Models 论文链接&#xff1a;https://arxiv.org/pdf/2402.03885 前言 当前时间序列数据上预训练大型模型面临以下挑战&#xff1a;(1) 缺乏大型且统一的公共时间序列数据集&#xff0c;(2) 时间序列特…

SpringBoot Data Redis连接Redis-Cluster集群

使用SpringBoot Data Redis无法连接Redis-Cluster集群 最近在研究系统高并发下的缓存架构&#xff0c;因此自己在自己买的云服务器上搭建好Redis 5.0 版本的集群后&#xff0c;使用springboot的 RedisTemplate连接是发现总是访问不到集群节点。上网百度了发现没有好的解决办法&…

鸿蒙中服务卡片数据的获取和渲染

1. 2.在卡片中使用LocalStorageProp接受传递的数据 LocalStorageProp("configNewsHead") configNewsHeadLocal: ConfigNewsHeadInfoItem[] [] 注意&#xff1a;LocalStorageProp括号中的为第一步图片2中的键 3.第一次在服务卡片的第一个卡片中可能会获取不到数据…

ARM64环境部署EFK8.15.3收集K8S集群容器日志

环境规划 主机IP系统部署方式ES版本CPU架构用户名密码192.168.1.225Ubuntu 22.04.4 LTSdockerelasticsearch:8.15.3ARM64elasticllodyi4TMmZD ES集群部署 创建持久化目录(所有节点) mkdir -p /data/es/{data,certs,logs,plugins} mkdir -p /data/es/certs/{ca,es01}服务器…

应用系统开发(12) Zync中实现数字相敏检波

在 Xilinx Zynq 系列(如 Zynq-7000 或 Zynq UltraScale+)中实现数字相敏检波(DSP,Digital Synchronous Detection)可以通过硬件(PL部分,FPGA逻辑)和软件(PS部分,ARM Cortex-A 处理器)的协同工作来实现。以下是一个详细的设计方法,包括基本原理和 Zynq 的实现步骤。…

力扣hot100-->二分查找

目录 二分查找 1. 33. 搜索旋转排序数组 2. 34. 在排序数组中查找元素的第一个和最后一个位置 3. 240. 搜索二维矩阵 II 3. 287. 寻找重复数 二分查找 1. 33. 搜索旋转排序数组 中等 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&am…

南京邮电大学《智能控制技术》课后作业

一、问题一 复现二输入单输出模糊控制系统&#xff0c;改动其中一到两个环节&#xff08;隶属度设置、规则等&#xff09;&#xff0c;对比修改前后控制效果。 定义模糊 %Fuzzy Control for water tank clear all; close all;anewfis(fuzz_tank);%Fuzzy Inference System stru…

苹果ASA归因对接以及API接入

一、归因概要 广告归因&#xff0c;目的是用于衡量广告带来的激活用户的成本以及后续进一步的用户质量表现。 Apple Ads 广告平台是基于 App Store&#xff08;站内广告&#xff09;&#xff0c;同时属于自归因平台&#xff08;通常称为 SAN&#xff09;。这两个因素&#xff…

hhdb数据库介绍(9-18)

Oracle兼容性说明 数据类型兼容 本节主要介绍 HHDB Server与Oracle 数据库中数据类型的详细兼容对比信息。 比较项Oracle数据库数据类型HHDB Server数据类型对应项/替代项字符串/字符VARCHAR2( n )VARCHAR( n )字符串/字符NVARCHAR2( n )VARCHAR( n ) character set utf8字符…

服务器数据恢复—raid5阵列故障导致上层系统分区无法识别的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌DL380服务器&#xff0c;服务器中三块SAS硬盘组建了一组raid5阵列。服务器安装Windows Server操作系统&#xff0c;划分了3个分区&#xff0c;D分区存放数据库&#xff0c;E分区存放数据库备份。 服务器故障&#xff1a; RAID5阵列中有一…

STM32设计电流与温度监控python上位机监控平台设计

目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 电路图采用Altium Designer进行设计&#xff1a; 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 在现代工业自动化和智能设备管理中&#xff0c;对电流和温度的实时监控是…

STM32F103ZET6快速创建工程

1.创建工程目录,点击进目录, 然后复制目录的路径 2.双击打开kile5, 然后点击project, 创建工程 3.找到刚才的目录, 然后加入工程 4.输入芯片 STM32F103ZE, 然后保存 5.勾选对应的初始文件 6.加入main.c函数 7.双击进入Source_code文件夹 , 然后加入User,进入User 8.加入main.c文…