RAG项目中PDF文档划分的三种方法:pdf分块解析、pdf滑窗法解析、pdf非滑窗法解析

在学习RAG的项目中需要用到PDF文档分块的相关知识点,现在将回顾的NLP中的分块技术以及具体的PDF分块方法总结如下:

NLP分块

  1. 按字符分块
    此方法将文本分解为单个字符。它适用于需要细粒度文本分析的任务,例如字符级语言模型或某些类型的文本预处理。

  2. 按Token分块
    将文本分割成token,是自然语言处理中的一种标准方法。基于令牌的组块对于文本分类、语言建模和其他依赖于token化输入的 NLP 应用程序等任务来说是必不可少的。

  3. 按段落分块
    按段落分段整理文本有助于维护文档的整体结构和流程。此方法适用于需要较大上下文的任务,如文档摘要或内容提取。

  4. 递归分块
    这涉及到重复地将数据分解成更小的块,通常用于分层数据结构。递归组块有利于需要多级分析的任务,如主题建模或层次聚类。

  5. 语义分块
    根据意义而非结构元素对文本进行分组对于需要理解数据上下文的任务至关重要。语义块利用诸如句子嵌入等技术来确保每个块代表一个连贯的主题或想法。

  6. 代理分块
    这种方法的重点是在识别和分组文本的基础上增加参与的代理,如人或组织。它在信息抽取和实体识别任务中非常有用,因为理解不同实体之间的角色和关系非常重要。

基于Langchain的文本分块技术——5行代码

递归字符分块

charSplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)  
chunks = charSplitter.split_text(text

token分块

splitter = TokenSplitter(max_tokens=512)  
chunks = splitter.split_text(text)  

句子分块

# 初始化SentenceSplitter ,每个块最多5个句子  
splitter = SentenceSplitter(max_length=5)  
chunks = splitter.split_text(text)  

正则分块

splitter = RegexSplitter(pattern=r'\n\n+')  
chunks = splitter.split_text(text)  

Markdown分块

splitter = MarkdownSplitter()  
chunks = splitter.split_text(text)  

PDF分块

首先需要明白虽然三种PDF分块方法,但是内容最开始都按照不同行划分。如下图所示,每行的内容包含原本内容、id、height、width以及size这些属性,这些属性与后面信息拼接相关。
原本PDF文档

这是加载后PDF的内容按照每行划分

pdf分块解析

pdf分块解析,尽量保证一个小标题+对应文档在一个文档块,其中文档块的长度分别是512和1024。这种方式划分文本块,是按照文本字体的大小区分!
代码:

 def ParseBlock(self, max_seq = 1024):

     with pdfplumber.open(self.pdf_path) as pdf:

         for i, p in enumerate(pdf.pages):
             header = self.GetHeader(p)

             if(header == None):
                 continue
             # 这个代码是将页面中的每行代码进行分块  并计算它的位置信息
             texts = p.extract_words(use_text_flow=True, extra_attrs = ["size"])[::]

             squence = ""
             lastsize = 0

             for idx, line in enumerate(texts):
                 if(idx <1):
                     continue
                 if(idx == 1):
                     if(line["text"].isdigit()):
                         continue
                 cursize = line["size"]
                 text = line["text"]
                 if(text == "□" or text == "•"):
                     continue
                 elif(text== "警告!" or text == "注意!" or text == "说明!"):
                     # 注意标识提醒你:如未按照该警告内容操作可能会对您或者她人造成人身伤害或生命危险-----说明
                     if(len(squence) > 0):
                         self.Datafilter(squence, header, i, max_seq = max_seq)
                     squence = ""
                 # 两个数值在保留五位小数后相等,那么这个比较表达式的结果将是True;如果不相等,结果将是False。
                 elif(format(lastsize,".5f") == format(cursize,".5f")):
                     if(len(squence)>0):
                         squence = squence + text
                     else:
                         squence = text
                 else:
                     lastsize = cursize
                     if(len(squence) < 15 and len(squence)>0):
                         squence = squence + text
                     else:
                         if(len(squence) > 0):
                             self.Datafilter(squence, header, i, max_seq = max_seq)
                         squence = text
             if(len(squence) > 0):
                 self.Datafilter(squence, header, i, max_seq = max_seq)

最终分块的结果
在这里插入图片描述

在这里插入图片描述
通过这个方法我们可以将一个小标题下的信息划分到一起(满足不超过最大长度的情况下)

pdf滑窗法解析

pdf滑窗法解析,把文档句号分割,然后构建滑动窗口,其中文档块的长度分别是256和512。

def SlidingWindow(self, sentences, kernel = 512, stride = 1):
	 sz = len(sentences)
	 cur = ""
	 fast = 0
	 slow = 0
	 while(fast < len(sentences)):
	     sentence = sentences[fast]
	     if(len(cur + sentence) > kernel and (cur + sentence) not in self.data):
	         self.data.append(cur + sentence + "。")
	         cur = cur[len(sentences[slow] + "。"):]
	         slow = slow + 1
	     cur = cur + sentence + "。"
	     fast = fast + 1
	     
 def ParseAllPage(self, max_seq = 512, min_len = 6):
     all_content = ""
     for idx, page in enumerate(PdfReader(self.pdf_path).pages):
         page_content = ""
         text = page.extract_text()
         words = text.split("\n")
         for idx, word in enumerate(words):
             text = word.strip().strip("\n")
             if("...................." in text or "目录" in text):
                 continue
             if(len(text) < 1):
                 continue
             if(text.isdigit()):
                 continue
             page_content = page_content + text
         if(len(page_content) < min_len):
             continue
         all_content = all_content + page_content
     sentences = all_content.split("。")
     self.SlidingWindow(sentences, kernel = max_seq)

在这里插入图片描述
通过这个PDF滑窗法我们可以构造有重叠的文档块,每个文档块的开始是上一个文档块的第二句信息。通过这样避免信息的丢失。

pdf非滑窗法解析

pdf非滑窗法解析,把文档句号分割,然后按照文档块预设尺寸均匀切分,其中文档块的长度分别是256和512。

def ParseOnePageWithRule(self, max_seq = 512, min_len = 6):
    for idx, page in enumerate(PdfReader(self.pdf_path).pages):
        page_content = ""
        text = page.extract_text()
        words = text.split("\n")
        for idx, word in enumerate(words):
            text = word.strip().strip("\n")
            if("...................." in text or "目录" in text):
                continue
            if(len(text) < 1):
                continue
            if(text.isdigit()):
                continue
            page_content = page_content + text
        if(len(page_content) < min_len):
            continue
        if(len(page_content) < max_seq):
            if(page_content not in self.data):
                self.data.append(page_content)
        else:
            sentences = page_content.split("。")
            cur = ""
            for idx, sentence in enumerate(sentences):
                if(len(cur + sentence) > max_seq and (cur + sentence) not in self.data):
                    self.data.append(cur + sentence)
                    cur = sentence
                else:
                    cur = cur + sentence

在这里插入图片描述
按照每页PDF分块 设定固定大小的块 每页的内容可能有没有被加入到data文本块中 有些信息会被忽略。

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值