当前位置: 首页 > news >正文

【中文】PDF文档切分\切片\拆分最优方案-数据预处理阶段,为后续导入RAG向量数据库和ES数据库实现双路召回

目的

将PDF文档拆开,拆开后每个数据是文档中的某一段,目的是保证每条数据都有较完整的语义,并且长度不会太长

项目自述

看了很多切分项目,包括langchain、Langchain-Chatchat、、Chinese-LangChain、LangChain-ChatGLM-Webui、ChatPDF、semchunk等等,效果还行,但是不够完美,毕竟他们的对"\n"的优先级设置的较高,使用pymupdf得到的文本中充斥着大量的"\n",如果全部删掉也十分影响语义

切分逻辑

1、保持段落完整性
2、保持语义完整性

代码逻辑

1、转换PDF文件为DOCX文件
2、循环遍历paragraphs保持段落完整性
3、 以句号为节点,保持语义完整性

代码实现

import re
import os
import csv
from pdf2docx import Converter
from docx import Document_NON_WHITESPACE_SEMANTIC_SPLITTERS = ('。\n\n','。\n','。', '?', '!'';','\n','\r'  ')', '”', '’', '】', '……', # Sentence terminators.'?', '!', '*', # Sentence terminators.';', ',', '(', ')', '[', ']', "“", "”", '‘', '’', "'", '"', '`', # Clause separators.':', '—', '…', # Sentence interrupters.'/', '\\', '–', '&', '-', # Word joiners.
)def split_text(text, chunk_size=400):# 按照标点符号优先级逐级尝试进行切分for splitter in _NON_WHITESPACE_SEMANTIC_SPLITTERS:if splitter:parts = text.split(splitter)chunks = []current_chunk = ''for part in parts:if len(current_chunk) + len(part) + len(splitter) <= chunk_size:current_chunk += part + splitterelse:if current_chunk:chunks.append(current_chunk.strip())current_chunk = part + splitterif current_chunk:chunks.append(current_chunk.strip())# 如果切分后的块总大小符合预期,则返回结果if all(len(chunk) <= chunk_size for chunk in chunks):return chunks# 如果所有标点符号都无法进行有效切分,则按固定大小切分return [text[i:i + chunk_size] for i in range(0, len(text), chunk_size)]def pdf_to_docx(pdf_file_path):try:docx_path = os.path.join(os.path.dirname(pdf_file_path), os.path.basename(pdf_file_path).split(".")[0] +".docx")cv = Converter(pdf_file_path)cv.convert(docx_path)cv.close()return docx_pathexcept Exception as e:print(f"转换过程中发生错误:{str(e)}")return Falsedef pdf2docx_to_csv(pdf_file_path, max_length=400):docx_path = pdf_to_docx(pdf_file_path)if not docx_path:return Falsedocx = Document(docx_path)result = []current_text = ""for paragraph in docx.paragraphs:sections = paragraph.text.strip()sections = re.sub(r'\s+', ' ', sections)sections = re.sub(r'(.)\1{4,}', r'\1', sections)if len(sections) > max_length:chunk_size = int(len(sections) / ((len(sections) // max_length) + 1))sections = split_text(sections, chunk_size=chunk_size)if isinstance(sections,str):sections = [sections,]for section in sections:if not current_text or len(current_text) + len(section) + 1 <= max_length:current_text += " " + sectionelse:period_index = current_text.rfind('。')if period_index != -1:period_text = current_text[:period_index+1].strip()result.append(period_text)current_text = current_text[period_index+1:].strip() + sectionelse:result.append(current_text.strip())current_text = sectionif current_text.strip():result.append(current_text.strip())output_path = os.path.join(os.path.dirname(pdf_file_path), os.path.basename(pdf_file_path).split(".")[0] + "_pdf2docx_"+ ".csv")with open(output_path, 'w', newline='', encoding='utf-8') as csvfile:csvwriter = csv.writer(csvfile)csvwriter.writerow(['filename', 'text'])csvwriter.writerows(result)print(f"{pdf_file_path} 处理完成")if __name__ == "__main__":pdf_file_path = "/path/to/your/xxx.pdf"pdf2docx_to_csv(pdf_file_path)

如果觉得好用就点个赞!

相关文章:

  • 29.Netty进阶-黏包半包
  • C++类和对象总结
  • Oracle--存储结构
  • Springboot整合Kafka消息队列服务实例
  • thinkphp单独为某个接口设置缓存
  • 预期和视角之外是什么?
  • 01--MySQL数据库概述
  • vue3自动导入---组件库elements-ui,vuetify以及scss样式的自动导入
  • 【C++11 之强类型枚举enum class/struct 基本结构及应用场景】了解在enum基础上增加了什么
  • 水系统阻力计算
  • git log 过滤
  • Redis的实战常用一、验证码登录(解决session共享问题)(思路、意识)
  • 数据仓库之离线数仓
  • Android系统 无法绑定1024以下端口问题
  • 力扣每日一题 6/22 字符串/贪心
  • Asm.js的简单介绍
  • ECS应用管理最佳实践
  • Java 网络编程(2):UDP 的使用
  • python3 使用 asyncio 代替线程
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • swift基础之_对象 实例方法 对象方法。
  • TypeScript实现数据结构(一)栈,队列,链表
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • 笨办法学C 练习34:动态数组
  • 对象管理器(defineProperty)学习笔记
  • 和 || 运算
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 离散点最小(凸)包围边界查找
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 前端
  • 实现简单的正则表达式引擎
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 微服务入门【系列视频课程】
  • 一个项目push到多个远程Git仓库
  • 以太坊客户端Geth命令参数详解
  • 与 ConTeXt MkIV 官方文档的接驳
  • 在Unity中实现一个简单的消息管理器
  • 怎样选择前端框架
  • UI设计初学者应该如何入门?
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​io --- 处理流的核心工具​
  • ​Java基础复习笔记 第16章:网络编程
  • #前后端分离# 头条发布系统
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • (libusb) usb口自动刷新
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (蓝桥杯每日一题)love
  • (区间dp) (经典例题) 石子合并
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (转)Oracle 9i 数据库设计指引全集(1)
  • .gitignore文件使用
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net core 依赖注入的基本用发
  • .net core 源码_ASP.NET Core之Identity源码学习