本文是《LangChain實戰課》系列的第十七篇,將專篇深入講解如何構建能夠與PDF和PPT文檔進行智能對話的AI助手。通過學習本文,您將掌握復雜格式文檔的解析技巧、文本與表格處理技術,以及實現精準問答的系統方法。
前言
在日常工作和學習中,PDF和PPT文檔是我們最常接觸的文檔格式之一。這些文檔包含了大量有價值的信息,但手動提取和分析這些信息往往耗時耗力。通過結合LangChain和先進的文檔解析技術,我們可以構建一個智能的文檔問答助手,讓用戶能夠像與人交談一樣與文檔進行交互,快速獲取所需信息。
面臨的挑戰與技術方案
PDF/PPT文檔解析的挑戰
-
格式復雜性:PDF和PPT具有復雜的布局和格式
-
文本提取困難:特別是掃描版PDF的OCR識別
-
表格處理:保持表格結構和數據的完整性
-
多模態內容:處理文本、圖像、圖表混合的內容
-
布局保持:保留文檔的原始布局和語義結構
技術解決方案
我們將使用以下技術棧來解決這些挑戰:
-
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 osclass 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 documentsexcept 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 documentsexcept 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 tablesclass TextParser:"""文本內容解析器"""def preprocess_text(self, text: str) -> str:"""預處理文本內容"""# 移除多余的空格和換行text = ' '.join(text.split())# 其他清理操作...return textdef 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 Documentclass AdvancedTableProcessor:def __init__(self):passdef 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.dftable_content = self._format_table_content(df)documents.append(Document(page_content=table_content,metadata={"source": pdf_path,"table_index": i