from typing import List
from langchain.document_loaders.unstructured import UnstructuredFileLoader
from document_loaders.ocr import get_ocr
import tqdm
class RapidOCRPDFLoader(UnstructuredFileLoader):
def _get_elements(self) -> List:
def pdf2text(filepath):
import fitz # pyMuPDF里面的fitz包,不要与pip install fitz混淆
import numpy as np
ocr = get_ocr()
doc = fitz.open(filepath)
resp = ""
b_unit = tqdm.tqdm(total=doc.page_count, desc="RapidOCRPDFLoader context page index: 0")
for i, page in enumerate(doc):
# 更新描述
b_unit.set_description("RapidOCRPDFLoader context page index: {}".format(i))
# 立即显示进度条更新结果
b_unit.refresh()
# TODO: 依据文本与图片顺序调整处理方式
text = page.get_text("")
resp += text + "\n"
img_list = page.get_images()
for img in img_list:
pix = fitz.Pixmap(doc, img[0])
img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, -1)
result, _ = ocr(img_array)
if result:
ocr_result = [line[1] for line in result]
resp += "\n".join(ocr_result)
# 更新进度
b_unit.update(1)
return resp
text = pdf2text(self.file_path)
from unstructured.partition.text import partition_text
return partition_text(text=text, **self.unstructured_kwargs)
if __name__ == "__main__":
loader = RapidOCRPDFLoader(file_path="../tests/samples/ocr_test.pdf")
docs = loader.load()
print(docs)
from typing import TYPE_CHECKING
if TYPE_CHECKING:
try:
from rapidocr_paddle import RapidOCR
except ImportError:
from rapidocr_onnxruntime import RapidOCR
def get_ocr(use_cuda: bool = True) -> "RapidOCR":
try:
from rapidocr_paddle import RapidOCR
ocr = RapidOCR(det_use_cuda=use_cuda, cls_use_cuda=use_cuda, rec_use_cuda=use_cuda)
except ImportError:
from rapidocr_onnxruntime import RapidOCR
ocr = RapidOCR()
return ocr
🧠 Langchain代码解析:
from langchain.document_loaders.unstructured import UnstructuredFileLoader
from unstructured.partition.text import partition_text
这两行代码分别导入了两个关键模块:
UnstructuredFileLoader
(来自langchain
)partition_text
(来自unstructured
)
它们通常用于加载非结构化文本文件并将其转换为可用于下游任务(如向量化、问答系统等)的格式。
📦 第一部分:UnstructuredFileLoader
来源:
- 属于 LangChain 库的一部分。
- LangChain 是一个用于构建 LLM(大语言模型)应用的框架。
UnstructuredFileLoader
是其提供的一个文档加载器类。
功能:
将非结构化文本文件(如 .txt、.md、.csv 等)读取为 Document 对象。
Document 是 LangChain 中的一种标准数据结构,形式如下:
class Document:
page_content: str # 实际文本内容
metadata: dict # 元信息,如文件名、来源等
示例用法:
loader = UnstructuredFileLoader("example.txt")
documents = loader.load()
这会返回一个包含多个 Document
的列表,每个 Document
包含一页的内容和元信息。
📄 第二部分:partition_text
来源:
- 属于 Unstructured 库。
- Unstructured 是一个专门处理非结构化数据的开源库,支持多种文件格式(TXT, PDF, DOCX, HTML 等)。
功能:
对纯文本进行语义级别的切分(例如按段落、句子等),便于后续处理。
它能识别出文本中的标题、段落、项目符号等内容,并以结构化方式返回。
示例用法:
from unstructured.partition.text import partition_text
elements = partition_text(filename="example.txt")
for element in elements:
print(element)
输出可能是:
Title: Introduction
NarrativeText: This is the first paragraph of the document.
ListItem: - First item
ListItem: - Second item
🔗 二者结合使用的意义
在实际应用中,你可以这样组合这两个模块:
from langchain.document_loaders.unstructured import UnstructuredFileLoader
from unstructured.partition.text import partition_text
# 自定义一个使用 partition_text 的 Loader
class CustomTextLoader(UnstructuredFileLoader):
def _get_elements(self):
return partition_text(filename=self.file_path)
# 使用自定义 Loader 加载文档
loader = CustomTextLoader("example.txt")
docs = loader.load()
📌 这样做的好处是:
- 利用了
unstructured
强大的文本结构化解析能力 - 同时兼容 LangChain 的接口,方便后续接入向量数据库、检索链、QA 链等功能
📌 总结一句话:
UnstructuredFileLoader
是 LangChain 中用于加载非结构化文件的标准工具,而partition_text
是底层unstructured
库中用于精细切分文本的方法,两者结合可以高效地将原始文本转化为结构化的文档对象,供 LLM 使用。
具体实现代码解析:RapidOCRPDFLoader
这是一个自定义的 PDF 文档加载器类,继承自 LangChain 的 UnstructuredFileLoader
,用于读取 PDF 文件内容并将其转换为结构化文本格式,支持 OCR 图像识别。
🔍 导入部分
from typing import List
from langchain.document_loaders.unstructured import UnstructuredFileLoader
from document_loaders.ocr import get_ocr
import tqdm
解释:
模块 | 功能 |
---|---|
List |
用于类型注解,表示返回的是一个列表 |
UnstructuredFileLoader |
LangChain 提供的基类,用于将文件转为 Document 对象 |
get_ocr |
自定义 OCR 工具函数(来自本地模块) |
tqdm |
显示进度条,提升用户体验 |
📦 类定义与初始化
class RapidOCRPDFLoader(UnstructuredFileLoader):
def _get_elements(self) -> List:
- 继承
UnstructuredFileLoader
- 重写
_get_elements()
方法,这是所有UnstructuredFileLoader
子类必须实现的方法。 - 返回值是一个
List
,包含从 PDF 中提取出的所有“元素”(如段落、标题等)
🧮 核心方法:pdf2text(filepath)
这个函数负责将 PDF 文件中的每一页转换为文本内容,并对图像执行 OCR 提取文字。
函数内部流程如下:
1️⃣ 引入依赖库
import fitz # PyMuPDF 的核心模块
import numpy as np
fitz
是 PyMuPDF 的核心模块,用于处理 PDF 和图像numpy
用于将图像像素数据转换为数组,便于 OCR 处理
2️⃣ 初始化 OCR 工具
ocr = get_ocr()
get_ocr()
是你项目中封装的 OCR 函数,可能调用了 PaddleOCR、EasyOCR 或其它 OCR 引擎
3️⃣ 打开 PDF 文件
doc = fitz.open(filepath)
resp = ""
- 使用
fitz.open()
打开 PDF 文件 resp
用于拼接最终提取出的文本内容
4️⃣ 进度条设置
b_unit = tqdm.tqdm(total=doc.page_count, desc="RapidOCRPDFLoader context page index: 0")
- 设置一个进度条,显示当前正在处理哪一页 PDF
5️⃣ 遍历 PDF 页面
for i, page in enumerate(doc):
b_unit.set_description("RapidOCRPDFLoader context page index: {}".format(i))
b_unit.refresh()
- 遍历每一页 PDF
- 更新进度条描述信息
6️⃣ 提取页面上的纯文本
text = page.get_text("")
resp += text + "\n"
page.get_text("")
提取当前页的纯文本内容- 添加到
resp
字符串中
7️⃣ 提取页面上的图片并执行 OCR
img_list = page.get_images()
for img in img_list:
pix = fitz.Pixmap(doc, img[0])
img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, -1)
result, _ = ocr(img_array)
if result:
ocr_result = [line[1] for line in result]
resp += "\n".join(ocr_result)
page.get_images()
获取该页所有图像对象- 将图像转换为 NumPy 数组
img_array
,以便输入给 OCR - 调用 OCR 工具识别图像中的文字
- 将识别结果添加到
resp
中
✅ 支持混合文本+图像的 PDF 内容提取
8️⃣ 更新进度条
b_unit.update(1)
📤 返回结果
return resp
- 最终返回整个 PDF 提取后的完整文本字符串
📥 接下来:使用 partition_text
结构化解析
text = pdf2text(self.file_path)
from unstructured.partition.text import partition_text
return partition_text(text=text, **self.unstructured_kwargs)
- 使用
unstructured
库提供的partition_text
函数,对提取出的文本进行语义切分 - 输出是多个结构化的“元素”,如:
Title
NarrativeText
ListItem
- 等等
📌 这些结构化元素可以直接被 LangChain 的下游组件使用(如向量化、检索、QA Chain)
📌 示例运行
if __name__ == "__main__":
loader = RapidOCRPDFLoader(file_path="../tests/samples/ocr_test.pdf")
docs = loader.load()
print(docs)
- 实例化加载器
- 加载 PDF 文件内容
- 输出格式为 LangChain 的
Document
列表
示例输出可能是:
[
Document(page_content='Introduction...', metadata={'source': 'ocr_test.pdf'}),
Document(page_content='Section 1:...', metadata={'source': 'ocr_test.pdf'}),
...
]
✅ 总结一句话:
RapidOCRPDFLoader
是一个增强版的 PDF 加载器,它不仅能提取 PDF 中的文本,还能识别图像并执行 OCR,最后将内容结构化后返回,兼容 LangChain 的标准接口。