LangChain实战(十七):构建与PDF/PPT文档对话的AI助手

发布于:2025-09-06 ⋅ 阅读:(19) ⋅ 点赞:(0)

本文是《LangChain实战课》系列的第十七篇,将专篇深入讲解如何构建能够与PDF和PPT文档进行智能对话的AI助手。通过学习本文,您将掌握复杂格式文档的解析技巧、文本与表格处理技术,以及实现精准问答的系统方法。

前言

在日常工作和学习中,PDF和PPT文档是我们最常接触的文档格式之一。这些文档包含了大量有价值的信息,但手动提取和分析这些信息往往耗时耗力。通过结合LangChain和先进的文档解析技术,我们可以构建一个智能的文档问答助手,让用户能够像与人交谈一样与文档进行交互,快速获取所需信息。

面临的挑战与技术方案

PDF/PPT文档解析的挑战

  1. 格式复杂性:PDF和PPT具有复杂的布局和格式

  2. 文本提取困难:特别是扫描版PDF的OCR识别

  3. 表格处理:保持表格结构和数据的完整性

  4. 多模态内容:处理文本、图像、图表混合的内容

  5. 布局保持:保留文档的原始布局和语义结构

技术解决方案

我们将使用以下技术栈来解决这些挑战:

  • PyMuPDF:高效的PDF文本和表格提取

  • python-pptx:PPT文档解析

  • Unstructured:处理复杂文档结构

  • LangChain:构建问答流水线

  • Chroma/FAISS:向量存储和检索

  • OpenAI Embeddings:文本向量化

环境准备与安装

首先安装必要的依赖包:

# 安装核心库
pip install langchain openai python-dotenv

# 安装文档处理库
pip install pymupdf python-pptx unstructured

# 安装额外的文档处理依赖
pip install pdf2image pillow

# 安装表格处理库
pip install tabula-py camelot-py

# 安装向量数据库
pip install chromadb

# 安装其他工具
pip install tiktoken sentence-transformers

构建PDF/PPT文档处理流水线

1. 文档加载与解析

让我们首先创建专门处理PDF和PPT文档的加载器:

import fitz  # PyMuPDF
from pptx import Presentation
import pandas as pd
from langchain.schema import Document
from typing import List, Dict, Any
import io
import os

class AdvancedDocumentLoader:
    def __init__(self):
        self.text_parser = TextParser()
        self.table_parser = TableParser()
    
    def load_pdf_document(self, file_path: str) -> List[Document]:
        """加载并解析PDF文档"""
        documents = []
        try:
            with fitz.open(file_path) as pdf_document:
                for page_num in range(len(pdf_document)):
                    page = pdf_document.load_page(page_num)
                    
                    # 提取文本内容
                    text_content = page.get_text()
                    if text_content.strip():
                        documents.append(Document(
                            page_content=text_content,
                            metadata={
   
   
                                "source": file_path,
                                "page": page_num + 1,
                                "type": "text",
                                "content_type": "text"
                            }
                        ))
                    
                    # 提取表格
                    tables = self._extract_pdf_tables(page)
                    for i, table in enumerate(tables):
                        documents.append(Document(
                            page_content=table,
                            metadata={
   
   
                                "source": file_path,
                                "page": page_num + 1,
                                "table_index": i + 1,
                                "type": "table",
                                "content_type": "table"
                            }
                        ))
            
            return documents
        except Exception as e:
            print(f"PDF解析错误: {
     
     e}")
            return []
    
    def load_ppt_document(self, file_path: str) -> List[Document]:
        """加载并解析PPT文档"""
        documents = []
        try:
            presentation = Presentation(file_path)
            
            for slide_num, slide in enumerate(presentation.slides, 1):
                slide_text = []
                
                # 提取幻灯片文本
                for shape in slide.shapes:
                    if hasattr(shape, "text") and shape.text.strip():
                        slide_text.append(shape.text)
                
                if slide_text:
                    content = "\n".join(slide_text)
                    documents.append(Document(
                        page_content=content,
                        metadata={
   
   
                            "source": file_path,
                            "slide": slide_num,
                            "type": "text",
                            "content_type": "slide_text"
                        }
                    ))
            
            return documents
        except Exception as e:
            print(f"PPT解析错误: {
     
     e}")
            return []
    
    def _extract_pdf_tables(self, page) -> List[str]:
        """提取PDF页面中的表格"""
        tables = []
        try:
            # 使用PyMuPDF提取表格
            tabs = page.find_tables()
            if tabs.tables:
                for table in tabs.tables:
                    table_data = table.extract()
                    if table_data:
                        # 将表格数据转换为字符串表示
                        df = pd.DataFrame(table_data[1:], columns=table_data[0])
                        tables.append(df.to_markdown(index=False))
        except Exception as e:
            print(f"表格提取错误: {
     
     e}")
        
        return tables

class TextParser:
    """文本内容解析器"""
    def preprocess_text(self, text: str) -> str:
        """预处理文本内容"""
        # 移除多余的空格和换行
        text = ' '.join(text.split())
        # 其他清理操作...
        return text
    
    def extract_key_phrases(self, text: str) -> List[str]:
        """提取关键短语"""
        # 实现关键短语提取逻辑
        return []

class TableParser:
    """表格内容解析器"""
    def parse_table_structure(self, table_content: str) -> Dict[str, Any]:
        """解析表格结构"""
        # 实现表格结构解析
        return {
   
   }

2. 高级表格处理与结构化

对于复杂的表格数据,我们需要更精细的处理:

import camelot
import tabula
from langchain.schema import Document

class AdvancedTableProcessor:
    def __init__(self):
        pass
    
    def extract_tables_with_camelot(self, pdf_path: str) -> List[Document]:
        """使用Camelot提取PDF表格"""
        documents = []
        try:
            tables = camelot.read_pdf(pdf_path, pages='all', flavor='stream')
            
            for i, table in enumerate(tables):
                if table.parsing_report['accuracy'] > 80:  # 准确率阈值
                    df = table.df
                    table_content = self._format_table_content(df)
                    
                    documents.append(Document(
                        page_content=table_content,
                        metadata={
   
   
                            "source": pdf_path,
                            "table_index": i 

网站公告

今日签到

点亮在社区的每一天
去签到