AI系统中PDF表格内容提取与向量数据库检索实战指南

1次阅读
没有评论

共计 3050 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

背景痛点

在 AI 系统中处理 PDF 表格时,经常会遇到以下问题:

AI 系统中 PDF 表格内容提取与向量数据库检索实战指南

  • 表格格式复杂,包含合并单元格、嵌套表格等情况
  • 内容提取不完整,尤其是跨页表格
  • 提取后的数据结构混乱,难以直接使用
  • 检索效率低下,无法快速找到相关内容

这些问题导致后续的分析和应用变得困难,因此需要一套完整的解决方案。

技术选型

在处理 PDF 表格内容时,常用的 Python 库有以下几种:

  • PyPDF2:轻量级,但表格处理能力有限
  • pdfplumber:专注于文本和表格提取,支持复杂表格结构
  • Camelot:专门用于表格提取,但依赖较重

对于初学者来说,pdfplumber 是一个不错的选择,它提供了直观的 API 和良好的错误处理机制。

核心实现

1. 使用 pdfplumber 提取表格内容

首先安装必要的库:

pip install pdfplumber sentence-transformers faiss-cpu

然后使用 pdfplumber 提取表格:

import pdfplumber

with pdfplumber.open("example.pdf") as pdf:
    for page in pdf.pages:
        tables = page.extract_tables()
        for table in tables:
            for row in table:
                print(row)

2. 将表格数据转换为结构化格式

提取的表格数据通常是二维列表,我们可以将其转换为字典列表:

def convert_to_dicts(table_data, headers=None):
    if headers is None:
        headers = table_data[0]
        table_data = table_data[1:]

    result = []
    for row in table_data:
        row_dict = {}
        for i, cell in enumerate(row):
            row_dict[headers[i]] = cell
        result.append(row_dict)
    return result

3. 使用 Sentence Transformers 生成向量

安装 Sentence Transformers 并生成向量:

from sentence_transformers import SentenceTransformer

model = SentenceTransformer('all-MiniLM-L6-v2')

def generate_embeddings(texts):
    return model.encode(texts)

4. 存入 FAISS 向量数据库

FAISS 是 Facebook 开源的向量相似度搜索库:

import faiss
import numpy as np

dimension = 384  # all-MiniLM-L6-v2 的向量维度
index = faiss.IndexFlatL2(dimension)

# 假设我们已经有了向量数据
vectors = np.array([...]).astype('float32')
index.add(vectors)

检索优化

设置相似度阈值

在检索时,可以设置相似度阈值来过滤结果:

def search(query, index, threshold=0.7):
    query_vector = generate_embeddings([query])[0]
    D, I = index.search(np.array([query_vector]), k=5)

    results = []
    for distance, idx in zip(D[0], I[0]):
        if 1 - distance > threshold:  # 余弦相似度
            results.append((idx, 1 - distance))
    return results

处理多列检索

对于多列表格,可以将多列内容拼接后进行向量化:

def combine_columns(row_dict, columns):
    return " ".join([str(row_dict[col]) for col in columns])

避坑指南

  1. 表格跨页问题
  2. 检查表格是否跨页,如果是,可能需要手动合并
  3. 使用 pdfplumber 的 page.bboxtable.bbox属性判断表格边界

  4. 特殊字符处理

  5. 使用正则表达式清理特殊字符
  6. 处理 Unicode 编码问题

  7. 空单元格处理

  8. 为空的单元格填充默认值
  9. 或者在生成向量时跳过这些行

性能考量

对于大批量 PDF 文件处理,可以考虑以下优化:

  1. 使用多进程并行处理
  2. 预处理 PDF 文件,提取所有表格后再统一向量化
  3. 使用 GPU 加速向量生成
  4. 分批写入向量数据库

完整示例代码

import pdfplumber
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

# 1. 提取表格
def extract_tables_from_pdf(pdf_path):
    all_tables = []
    with pdfplumber.open(pdf_path) as pdf:
        for page in pdf.pages:
            tables = page.extract_tables()
            for table in tables:
                all_tables.append(table)
    return all_tables

# 2. 转换为结构化数据
def convert_to_dicts(tables, headers=None):
    all_dicts = []
    for table in tables:
        if headers is None:
            current_headers = table[0]
            rows = table[1:]
        else:
            current_headers = headers
            rows = table

        for row in rows:
            row_dict = {}
            for i, cell in enumerate(row):
                if i < len(current_headers):
                    row_dict[current_headers[i]] = cell
            all_dicts.append(row_dict)
    return all_dicts

# 3. 生成向量
def setup_model():
    return SentenceTransformer('all-MiniLM-L6-v2')

# 4. 构建索引
def build_index(vectors):
    dimension = vectors.shape[1]
    index = faiss.IndexFlatL2(dimension)
    index.add(vectors)
    return index

# 主流程
if __name__ == "__main__":
    # 提取表格
    tables = extract_tables_from_pdf("example.pdf")

    # 转换为结构化数据
    data = convert_to_dicts(tables)

    # 生成文本表示
    texts = [" ".join([str(v) for v in row.values()]) for row in data]

    # 生成向量
    model = setup_model()
    vectors = model.encode(texts)

    # 构建索引
    index = build_index(vectors)

    # 保存索引
    faiss.write_index(index, "pdf_table.index")

思考题

  1. 如何处理 PDF 中既有表格又有文本的情况?如何区分它们?
  2. 当表格非常大时,如何优化内存使用?
  3. 如何评估检索结果的质量?可以设计哪些指标?

希望这篇指南能帮助你快速上手 PDF 表格内容的提取和检索。如果有任何问题,欢迎在评论区留言讨论。

正文完
 0
评论(没有评论)