导图一览:

| 工具名称 | 功能 | 技术 | 输出格式 | 特点 |
|---|---|---|---|---|
| PyPDF | 提取文本、图像和元数据 | 基于规则 (RB) | TXT | 成熟的纯 Python 库,处理多种 PDF 操作 |
| pdfminer.six | 提取文本、图像、目录、字体大小 | 基于规则 | TXT、HTML、hOCR、JPG | 多功能,支持 CJK 语言和垂直书写 |
| PDFPlumber | 提取文本和表格 | 基于规则 (基于 pdfminer) | TXT、HTML、hOCR、JPG | 提供可视化调试工具,提取过程便捷 |
| PyMuPDF | 提取文本、表格和图像 | 基于规则 (MuPDF),可选 OCR | TXT、HTML、SVG、JSON | Python 绑定,处理复杂文档布局 |
| pypdfium2 | 提取文本 | 基于规则 | TXT | 轻量级库,专注文本提取 |
| Unstructured | 预处理和摄取图像及文本文档 | 基于规则,支持 OCR | TXT | 支持元素级文本和表格提取 |
| Tabula | 提取表格 | 基于规则 | DataFrame、CSV、JSON | Python 包装器,使用 tabula-java |
| Camelot | 提取表格 | 基于规则 | DataFrame、CSV、JSON、HTML | 灵活配置,支持流模式和格子模式 |
| Nougat | 提取文本 | 基于 Transformer | Markdown | 深度学习模型,专为学术文档训练 |
| Table Transformer (TATR) | 检测表格 | 基于 Transformer | 图像 | 对象检测模型,训练于 PubTables-1M 等 |
pdfplumber
pdfplumber库按页处理 pdf ,获取页面文字,提取表格等操作。
学习文档:https://github.com/jsvine/pdfpl
import pdfplumber with pdfplumber.open("E:\新员工\【学员讲义】企业文化.pdf") as pdf: page01 = pdf.pages[9] #指定页码 text = page01.extract_text()#提取文本 print(text) table = page01.extract_tables() # 提取表格 print(table)
优势:
1. pdfplumber能轻松访问有关PDF对象的所有详细信息,且用于提取文本和表格的方法高级可定制,使用者可根据表格的具体形式来调整参数。
2. 最关键的是pdfplumber作者持续在维护该库,而同样受欢迎的PyPDF2已经不再维护了。
劣势:
1. 提取的 英文 中间没有空格
PyPDF2
PyPDF2 是一个纯 Python PDF 库,可以读取文档信息(标题,作者等)、写入、分割、合并PDF文档,它还可以对pdf文档进行添加水印、加密解密等。
官方文档:https://pythonhosted.org/PyPDF2 https://www.w3cschool.cn/pypdf2/
import PyPDF2 def extract_text_from_pdf(pdf_path): with open(pdf_path, 'rb') as file: pdf_reader = PyPDF2.PdfFileReader(file) num_pages = pdf_reader.numPages text = "" for page_num in range(num_pages): page = pdf_reader.getPage(page_num) text += page.extractText() return text pdf_path = 'example.pdf' extracted_text = extract_text_from_pdf(pdf_path) print(extracted_text)
版本 2.6.0
劣势:
1.英文识别不行,识别成单个字母了 S o l a r
2.表格无法识别
pdf2docx
可将 PDF 转换成 docx 文件的 Python 库。
该项目通过 PyMuPDF 库提取 PDF 文件中的数据,然后采用 python-docx 库解析内容的布局、段落、图片、表格等,最后自动生成 docx 文件。
from pdf2docx import parse pdf_file = 'E:\新员工\【学员讲义】企业文化.pdf' docx_file = 'E:\新员工\【学员讲义】企业文化2.docx' # convert pdf to docx parse(pdf_file, docx_file)
PDFminer
PDFMiner内置pdf2txt.py和dumppdf.py。但是pdf2txt.py从PDF文件中提取所有文本内容。但不能识别画成图片的文本,这需要对图片特征进行识别。对于加密的PDF你需要提供一个密码才能解析,对于没有提取权限的PDF文档你得不到任何文本。
https://pdfminersix.readthedocs.io

对于每个LTPage对象,它从上到下遍历每个元素,并尝试将适当的组件识别为:
- LTFigure:表示PDF中页面上的图形或图像的区域。
- LTTextContainer:代表一个矩形区域(段落)中的一组文本行(line),然后进一步分析成LTTextLine对象的列表。它们中的每一个都表示一个LTChar对象列表,这些对象存储文本的单个字符及其元数据。
- LTRect表示一个二维矩形,可用于在LTPage对象中占位区或者Panel,图形或创建表。
因此,使用Python对页面进行重构之后,将页面元素分类为LTFigure(图像或图形)、LTTextContainer(文本信息)或LTRect(表格)
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.converter import TextConverter from pdfminer.layout import LAParams from pdfminer.pdfpage import PDFPage from io import StringIO # 打开PDF文件 with open('example.pdf', 'rb') as file: # 创建一个PDFResourceManager对象 resource_manager = PDFResourceManager() # 创建一个StringIO对象,用于存储提取的文本内容 output = StringIO() # 创建一个TextConverter对象 converter = TextConverter(resource_manager, output, laparams=LAParams()) # 创建一个PDFPageInterpreter对象 interpreter = PDFPageInterpreter(resource_manager, converter) # 逐页解析文档 for page in PDFPage.get_pages(file): interpreter.process_page(page) # 获取提取的文本内容 text = output.getvalue() print(text)
from pdfminer.high_level import extract_text extracted_text = extract_text(pdf) print(extracted_text)
Pdfminer.six
Pdfminer.six 是PDFMiner的一个分支。
它是一种从PDF中解析、提取信息的工具文件,侧重于获取和分析文本数据、元数据和图片,还可用于获取文本的确切位置、字体或颜色。Pdfminer.six 直接从页面中提取文本 PDF 的源代码。以模块化的方式构建,因此pdfminer.six的每个组件都可以轻松更换。
官方文档:https://pdfminersix.readthedocs.io/en/latest/index.html
代码参考:https://mp.weixin.qq.com/s/5OQGOT1rllEAE8_L-v4L9A
大概试了下,功能没那么强大
pymupdf
import fitz def MuPDF_extract_text_from_pdf(path): doc = fitz.open(path) all_content = [] page_nums = 0 for i in doc.pages(): page_nums += 1 all_content.append(i.get_text()) text = '\n'.join(all_content) # text = ''.join(text.split('\n')) return text
papermerge
from papermage.recipes import CoreRecipe recipe = CoreRecipe() doc = recipe.run("example.pdf") for page in doc.pages: for row in page.rows: print(row.text)
xpdf
这个文本介绍了Xpdf,一个免费的PDF浏览器和工具包。它包括文本提取器、图片转换器、HTML转换器等工具,大部分工具都是开源的。
http://www.xpdfreader.com/
img2table
https://mp.weixin.qq.com/s/kPxiw4sgrr8Z3dHUt60dyw
综合运用上述模块
https://mp.weixin.qq.com/s/4mg59Sb7TzaoXVctEMJVWw 使用python提取PDF中的文本信息(包括表格和图片OCR)
# 读取PDF import PyPDF2 # 分析PDF的layout,提取文本 from pdfminer.high_level import extract_pages, extract_text from pdfminer.layout import LTTextContainer, LTChar, LTRect, LTFigure # 从PDF的表格中提取文本 import pdfplumber # 从PDF中提取图片 from PIL import Image from pdf2image import convert_from_path # 运行OCR从图片中提取文本 import pytesseract # 清除过程中的各种过程文件 import os # 创建一个从pdf中裁剪图像元素的函数 def crop_image(element, pageObj): # 获取从PDF中裁剪图像的坐标 [image_left, image_top, image_right, image_bottom] = [element.x0,element.y0,element.x1,element.y1] # 使用坐标(left, bottom, right, top)裁剪页面 pageObj.mediabox.lower_left = (image_left, image_bottom) pageObj.mediabox.upper_right = (image_right, image_top) # 将裁剪后的页面保存为新的PDF cropped_pdf_writer = PyPDF2.PdfWriter() cropped_pdf_writer.add_page(pageObj) # 将裁剪好的PDF保存到一个新文件 with open('cropped_image.pdf', 'wb') as cropped_pdf_file: cropped_pdf_writer.write(cropped_pdf_file) # 创建一个将PDF内容转换为image的函数 def convert_to_images(input_file,): images = convert_from_path(input_file) image = images[0] output_file = "PDF_image.png" image.save(output_file, "PNG") # 创建从图片中提取文本的函数 def image_to_text(image_path): # 读取图片 img = Image.open(image_path) # 从图片中抽取文本 text = pytesseract.image_to_string(img) return text # 从页面中提取表格内容 def extract_table(pdf_path, page_num, table_num): # 打开PDF文件 pdf = pdfplumber.open(pdf_path) # 查找已检查的页面 table_page = pdf.pages[page_num] # 提取适当的表格 table = table_page.extract_tables()[table_num] return table # 将表格转换为适当的格式 def table_converter(table): table_string = '' # 遍历表格的每一行 for row_num in range(len(table)): row = table[row_num] # 从warp的文字删除线路断路器 cleaned_row = [item.replace('\n', ' ') if item is not None and '\n' in item else 'None' if item is None else item for item in row] # 将表格转换为字符串,注意'|'、'\n' table_string+=('|'+'|'.join(cleaned_row)+'|'+'\n') # 删除最后一个换行符 table_string = table_string[:-1] return table_string # 创建一个文本提取函数 def text_extraction(element): # 从行元素中提取文本 line_text = element.get_text() # 探析文本的格式 # 用文本行中出现的所有格式初始化列表 line_formats = [] for text_line in element: if isinstance(text_line, LTTextContainer): # 遍历文本行中的每个字符 for character in text_line: if isinstance(character, LTChar): # 追加字符的font-family line_formats.append(character.fontname) # 追加字符的font-size line_formats.append(character.size) # 找到行中唯一的字体大小和名称 format_per_line = list(set(line_formats)) # 返回包含每行文本及其格式的元组 return (line_text, format_per_line) # 查找PDF路径 pdf_path = r'E:\5.pdf' # 创建一个PDF文件对象 pdfFileObj = open(pdf_path, 'rb') # 创建一个PDF阅读器对象 pdfReaded = PyPDF2.PdfReader(pdfFileObj) # 创建字典以从每个图像中提取文本 text_per_page = {} # 我们从PDF中提取页面 for pagenum, page in enumerate(extract_pages(pdf_path)): # 初始化从页面中提取文本所需的变量 pageObj = pdfReaded.pages[pagenum] page_text = [] line_format = [] text_from_images = [] text_from_tables = [] page_content = [] # 初始化检查表的数量 table_num = 0 first_element = True table_extraction_flag = False # 打开pdf文件 pdf = pdfplumber.open(pdf_path) # 查找已检查的页面 page_tables = pdf.pages[pagenum] # 找出本页上的表格数目 tables = page_tables.find_tables() # 找到所有的元素 page_elements = [(element.y1, element) for element in page._objs] # 对页面中出现的所有元素进行排序 page_elements.sort(key=lambda a: a[0], reverse=True) # 查找组成页面的元素 for i, component in enumerate(page_elements): # 提取PDF中元素顶部的位置 pos = component[0] # 提取页面布局的元素 element = component[1] # 检查该元素是否为文本元素 if isinstance(element, LTTextContainer): print(i, 'LTTextContainer') # 检查文本是否出现在表中 if table_extraction_flag == False: # 使用该函数提取每个文本元素的文本和格式 (line_text, format_per_line) = text_extraction(element) # 将每行的文本追加到页文本 page_text.append(line_text) # 附加每一行包含文本的格式 line_format.append(format_per_line) page_content.append(line_text) else: # 省略表中出现的文本 pass # 检查元素中的图像 if isinstance(element, LTFigure): print(i, 'LTFigure') # 从PDF中裁剪图像 crop_image(element, pageObj) # 将裁剪后的pdf转换为图像 convert_to_images('cropped_image.pdf') # 从图像中提取文本 image_text = image_to_text('PDF_image.png') text_from_images.append(image_text) page_content.append(image_text) # 在文本和格式列表中添加占位符 page_text.append('image') line_format.append('image') # 检查表的元素 if isinstance(element, LTRect): print(i, 'LTRect') # 如果第一个矩形元素 if first_element == True and (table_num + 1) <= len(tables): # 找到表格的边界框 lower_side = page.bbox[3] - tables[table_num].bbox[3] upper_side = element.y1 # 从表中提取信息 table = extract_table(pdf_path, pagenum, table_num) # 将表信息转换为结构化字符串格式 table_string = table_converter(table) # 将表字符串追加到列表中 text_from_tables.append(table_string) page_content.append(table_string) # 将标志设置为True以再次避免该内容 table_extraction_flag = True # 让它成为另一个元素 first_element = False # 在文本和格式列表中添加占位符 page_text.append('table') line_format.append('table') # 检查我们是否已经从页面中提取了表 # if element.y0 >= lower_side and element.y1 <= upper_side: # pass # elif not isinstance(page_elements[i + 1][1], LTRect): if not isinstance(page_elements[i + 1][1], LTRect): table_extraction_flag = False first_element = True table_num += 1 # 创建字典的键 dctkey = 'Page_' + str(pagenum) # 将list的列表添加为页键的值 text_per_page[dctkey] = [page_text, line_format, text_from_images, text_from_tables, page_content] # 关闭pdf文件对象 pdfFileObj.close() # 删除已创建的过程文件 os.remove('cropped_image.pdf') os.remove('PDF_image.png') # 显示页面内容 result = ''.join(text_per_page['Page_2'][3]) # text_per_page 看下数据格式 print(result)
doc docx
Python-dox:优点:能够解析docx格式文档;缺点:doc格式文档无法直接解析,需要进行转换为docx格式间接解析
# pip install python-docx from docx import Document doc = Document(file_path) # 遍历文档中的所有段落 text = [] for paragraph in doc.paragraphs: text.append(paragraph.text) print('*' * 200) # 遍历文档中的所有表格 for table in doc.tables: for row in table.rows: for cell in row.cells: print(cell.text) print('&' * 50) # 遍历文档中的所有图片 for image in doc.inline_shapes: print(image.filename)
docx2pdf
from docx2pdf import convert file = r'xx.docx' convert(file, "output.pdf")
版面分析
文本分割模型在文档解析中的角色
单双栏区分
汇总 Marker、MinerU、olmOCR、Surya、GOT-OCR 2.0、Mistral OCR等十几个开源/闭源模型
olmOCR
本地部署最强OCR大模型olmOCR!支持结构化精准提取复杂PDF文件内容!完美识别中英文文档、模糊扫描件与复杂表格!本地部署与实际测试全过程!医疗法律行业必备_哔哩哔哩_bilibili
Docling
Docling:统一的多文档解析框架 支持多种文档类型的处理与转换 内置OCR性能有限,中文开源OCR模型需要自行支持
ParseStudio
想提取文字,要用 PyMuPDF;想识别表格,还得上 pdfplumber 或 Docling;结果提出来的数据格式还不统一,处理麻烦……
现在有了更优雅的选择:ParseStudio。专为PDF解析量身打造,它集成了Docling、PyMuPDF、LlamaParse三种解析引擎,API设计简洁,模块化架构让你随心切换解析器,轻松搞定多模态解析任务。
一站式PDF解析神器!统一封装Docling、PyMuPDF、LlamaParse,批量处理无压力!
Umi-OCR:开源、免费、离线、多功能的 OCR 图片文字识别软件 (qq.com)
MMDocIR:多模态文档检索新基准,提升长文档的智能检索能力
基于多模态大语言模型的 PDF 转 Markdown 工具MarkPDFDown
256M参数多模态OCR神器,0.35秒解锁全文档奥秘! CPU/低配 GPU
PDF文档解剖术!OCR神器+1,这个开源工具把复杂排版秒变结构化数据! PDF Document Layout Analysis
MinerU
https://github.com/opendatalab/MinerU
9.MinerU——RAG知识库预处理,PDF转Markdown文件(对数学公式友好)_哔哩哔哩_bilibili
PDF转markdown,AI知识库绝配,科研文献整理必备,MinerU将PDF转化为机器可读格式的工具_哔哩哔哩_bilibili
MinerU 是一个一站式开源高质量数据提取工具,支持 PDF、网页和多格式电子书的提取。 该项目解决了从各种文档中高效准确地提取数据的问题。
- 支持多种文件格式,包括 PDF、网页和电子书。
- 提供强大的表格识别功能,提升数据解析的准确性。
- 多语言 OCR 支持,可检测和识别 84 种语言。
- 优化内存使用,大幅降低硬件要求,提高性能表现。
- 便于快速部署,并提供在线演示以展示功能。
未开源
从复杂文档到AI秒懂的高质量数据:EasyDoc解析实战指南
新出来的还没研究
利用LLM从非结构化PDF中提取结构化知识 PymuPDF4llm
PDF 文档提取和解析 API:使用最先进的 OCR 和 Ollama 支持的模型
>>>> 在线文档解析服务横评:TextIn、MinerU、MonkeyOCR 谁最适合企业知识库? (qq.com)
由于样本文档、参数配置的局限性,本次测试可能存在一定的随机性。 相对而言,TextIn 在线解析服务在表格识别、文档结构、跨页表格场景下比较优秀。
>>>> RAG:PDF解析难在哪,主流方案是什么 (qq.com)
目前常见的PDF 解析工具可以分为:
1. 轻量文本提取库:PyMuPDF、pdfplumber、pypdf, 原生文本提取路线,速度极快
2. AI 增强开源框架:Docling、MinerU、Marker-PDF , 集成布局分析模型,面向 RAG 场景
3. 收费 API:各大云厂商都有提供API ,托管服务,开箱即用
4. VLM 直接调用:GPT-4o、Gemini 2.5、Qwen3-VL ,最高理解能力,成本最高
VLM 将 PDF 页面光栅化为图像后直接输入多模态模型,由模型输出结构化文本。直接就绕过了复杂的坐标提取、字体解码、阅读顺序重建的所有中间步骤,对多栏、嵌套表格、合并单元格、手写内容的处理能力是应该是最强的了。
| 场景 | 模型 |
|---|---|
| 综合最强(闭源) | Gemini 2.5 Pro |
| 综合最强(开源) | Qwen2.5-VL-72B、InternVL3 |
| 文档 OCR | Gemma 3、LLaMA 3.2 Vision、DeepSeek-OCR |
| 轻量部署 | Phi-4、Pixtral 12B、DeepSeek-VL2 |
| 中文场景 | Qwen2.5-VL、GLM-4.5V |
常见解析问题
RAG应用在生产环境中的PDF解析问题主要在解析层和内容层。
多栏混排导致阅读顺序错乱
问题描述
多栏布局是 RAG 解析中影响最大的单一问题。PDF 的物理存储顺序不保证阅读顺序,左栏和右栏的文字在内容流中可能交错排列。轻量解析库按存储顺序提取字符,不关心区域归属,导致左右栏文字被交织拼接,形成语义完全断裂的混合文本。
正确阅读顺序:
[左栏] Introduction [右栏] Abstract
[左栏] We propose... [右栏] Recent work...
PyMuPDF 默认提取结果(部分文档):
Introduction
Abstract ← 从左栏跳到右栏第一行
We propose...
Recent work... ← 又跳回左栏
LLM 处理这种交错文本时,看到的是两段完全无关内容的混合,无法推断语义关系,上下文理解质量大幅下降。
处理方案
按坐标排序是最基础的改善,对提取出的文字块按 y 坐标(从上到下)和 x 坐标(从左到右)重新排序,可以部分解决简单双栏问题,但对三栏以上、图文混排或非标准版式可能还是会出问题。
最好的解决方案是进行版面分析,比如先用布局检测模型(DocLayNet 或 PP-StructureV2 等)将页面划分为独立的文本区域,标记每个区域的类型和阅读顺序,然后按区域顺序拼接文字。
对于无法通过版面分析解决的极复杂版式(杂志排版、广告页面、非标准布局),那就得试试VLM了。
字体编码缺失导致乱码
问题描述
当 PDF 生成工具未嵌入完整的 ToUnicode CMap,或使用了自定义字体编码时,解析器无法将字形 ID 映射回 Unicode 字符,输出结果为乱码、方框(□□□□)或空白。比如:使用 Type 3 自定义字体、字体子集嵌入不完整、中文字体 Unicode 映射缺失、文档经过 PDF 优化压缩工具处理后编码表被裁剪。(可以用编辑器,比如cursor的,打开pdf,底部可以修改调整编码,然后就可以看到下面的内容~)
PDF 中显示:Attention Is All You Need
PyPDF2 提取:偛整匯數整數搔搔数搔數
处理方案
不同解析库对字体编码的处理能力存在差异,同一份出现乱码的 PDF,换用 PyMuPDF(MuPDF 引擎)可能正常提取,反之亦然。所以有时候可以先试试别的解析器。
如果多个解析器都无法正常提取,说明可能是字体映射信息在 PDF 层面确实缺失。此时绕过文本层、直接对页面图像做 OCR 是可行的替代方案,OCR 从像素识别字符,完全不依赖 PDF 内部的字体编码。
对于"视觉显示正常但文本提取乱码"的 PDF,最常见的就是字体编码缺失的情况,OCR 通常能比较好的解决。极少数情况下(例如 Type 3 字体 + 完全自定义字形形状),可能OCR 也无法正确识别,那就只能回到文档源头重新生成或寻找原始可编辑版本。
跨页内容断裂
问题描述
物理分页(基于纸张尺寸的固定分割)与逻辑分段(基于语义的可变分割)两者天然无法对齐。解析器按页面处理文档时,每个页面作为独立单元,跨越页面边界的内容被物理截断。
| 跨页类型 | 出现频次 | 可能导致的问题 |
|---|---|---|
| 段落跨页 | 常见 | 段落语义断裂,上下文不完整 |
| 句子跨页 | 一般 | 句子在页面边界处被截断,语义无法理解 |
| 表格跨页 | 一般 | 表头在一页,数据在下一页,行列关系丢失 |
| 图表与说明跨页 | 一般 | 图片和其对应说明文字被分离 |
| 列表跨页 | 一般 | 编号或项目符号列表被切断,后续条目失去上下文 |
| 代码块跨页 | 少见 | 代码缩进结构和上下文丢失 |
表格跨页影响比较大,比如表头行留在第1页末尾(有些复杂的可能注脚都占了很多内容~),数据行从第2页开始,解析器分别处理两页,输出的两段文字都缺乏完整语义。RAG 检索时若只命中其中一段,LLM 无法还原行列对应关系。
处理方案
段落和句子跨页的最常见的方案是分块阶段设置 overlap(相邻 chunk 之间保留若干 token 的重叠),可以确保跨页处的句子在某个 chunk 中是完整的。另外,就是语义分块(基于 embedding 检测语义边界后切割)效果更好。
表格跨页就不能依赖通用的 overlap 方法。可行方案是在解析阶段检测当前页是否以未结束的表格收尾(最后一个检测到的结构是表格行,但没有表格边框的结束信号),并将下一页开头的表格行与当前页合并后再处理。Docling 对这种场景有内置处理逻辑,MinerU 同样支持跨页表格连接。
版面分析也是解决跨页的比较好的方案。
页眉页脚污染索引
问题描述
页眉页脚在每一页重复出现,内容通常是文档标题、公司名称、页码、日期等。比如,一份100页的文档,相同或高度相似的页眉文字会出现 100次。这些内容一方面会产生大量近似重复的 chunk,另外一方面就是不同页的 chunk 因共享相同页眉而向量相似度偏高,影响检索的区分能力。
处理方案
位置过滤和跨页重复检测。
因为页眉页脚通常出现在页面顶部和底部固定区,所以过滤 y 坐标落在页面顶部 8%(这个具体数值具体调试着看看) 和底部 8% 区域内的文字块。这个方法对布局规整的文档效果稳定,对将页脚放在页面中下部的特殊排版可能过滤不足或过滤过度。
跨页重复检测就简单粗暴了。统计每行文字在全文档各页中出现的频率,将出现比例超过阈值(这个具体数值也得具体调试着看看)的行标记为重复内容并过滤。比如,可以遍历所有页面的文本,以行为单位统计跨页出现频次,频次 / 总页数超过阈值的行视为页眉或页脚候选,从所有 chunk 中移除。
图表信息丢失
问题描述
纯文本解析对嵌入 PDF 的图片、图表、流程图的处理结果是完全丢失的,在提取后不留任何内容,相关的引用文字在 RAG 中也就成了空引用。
处理方案
纯文本提取 + OCR 可以恢复图表中的文字内容(如表格、标注文字),但无法理解图表的视觉语义(趋势方向、比较关系、空间布局等等),这个时候唯一能解决就只有VLM。
先用文本解析构建索引并完成检索(一般来说文本内容足以定位相关页面),检索到相关页面后,将页面光栅化为图像再输入 VLM 进行深度理解,最后将文本内容与 VLM 输出结合生成回答。
参考文献与脚注处理
问题描述
参考文献和脚注在 PDF 中的物理位置与其被引用的位置相距较远,跟页脚还不一样的,解析器按页面顺序处理文档时,引用标记(比如,[1]、上标数字)所在的 chunk 和对应的参考文献/脚注内容所在的 chunk 会被分离到向量索引的不同位置。
脚注文字要么混入正文末尾,要么在页面分割时被截断丢失。比如,在法律和金融场景中,一般文档脚注常包含免责声明、例外条款丢失这些内容会导致 LLM 基于不完整信息生成误导性回答。
处理方案
版面分析模型能够区分正文区域和脚注区域,Docling 和 MinerU 的输出文档树中,脚注作为独立类型节点存在,可以选择将脚注内容附加到引用它的正文段落之后,或单独存储并在检索时通过元数据关联。
对于参考文献,完整的处理方案是在索引时解析引用链,将 [1] 对应的参考文献内容嵌入到引用它的 chunk 元数据中,检索时一并返回。这个方案在学术论文场景下效果最为明显,但实现复杂度高,需要先提取完整的参考文献列表并建立引用号到文献内容的映射。稍微简单点的方案是在检索后扩展上下文,也就是命中某个引用了 [1] 的 chunk 后,同时返回文档尾部参考文献章节的对应条目,由 LLM 综合两段内容生成回答。
标题层级在分块后丢失
问题描述
传统按 token 数固定分块的方式不感知文档层级结构,切割结果中每个 chunk 只包含该节的内容文字,不携带它在文档层级中的位置信息。
文档树的优势了吧?
处理方案
最简单的方法是在分块时,为每个 chunk 构建其在文档层级中的完整路径,然后作为元数据附加在 chunk 内容前。
复杂一点的方法是不按 token 数切割,而是按文档的语义边界(章节、小节)切割,确保每个 chunk 对应一个完整的语义单元,不跨越标题边界,但这需要解析器输出保留层级结构信息。
好像也有人使用父子 chunk 策略,用小 chunk(128-256 token)做 embedding 和检索,命中后返回其父节点(完整小节,512-1024 token)给 LLM 生成回答。检索基于小 chunk 的语义精度,生成基于大 chunk 的上下文完整性,两个目标分别优化。
参考资料 还有很多方法,自行查看
参考资料:
https://mp.weixin.qq.com/s/9L_LwJvwn_F9C89J-yYezA 大模型下开源文档解析工具总结及技术思考 各种类型 代码很详尽
https://zhuanlan.zhihu.com/p/344384506 Python操作PDF全总结|pdfplumber&PyPDF2
https://mp.weixin.qq.com/s/gCU1hYmmHpqiV9APHotrYA 只需2行代码,轻松将PDF转换成Word
https://mp.weixin.qq.com/s/W1TciuOp4FTBU09LHQYptQ AI文档智能助理都是如何处理pdf的?
浙公网安备 33010602011771号