Capítulo 3: Lidando com Diferentes Tipos de Arquivo
Introdução
Documentos do mundo real vêm em muitos formatos, cada um com desafios únicos. Este capítulo aborda estratégias para lidar com PDFs, imagens, tabelas e dados estruturados.
Desafios com PDFs
PDFs são o formato de documento mais comum, mas também o mais desafiador:
Áreas Problemáticas
| Desafio | Descrição | Solução |
|---|---|---|
| PDFs escaneados | Imagens, não texto | Processamento OCR |
| Tabelas | Estrutura perdida | Extratores especializados |
| Multi-coluna | Ordem de leitura incorreta | Análise de layout |
| Cabeçalhos/Rodapés | Ruído repetido | Filtragem |
Opções de Extração de PDF
# Opção 1: Básica (PyPDF2/PyPDFLoader)
from langchain.document_loaders import PyPDFLoader
loader = PyPDFLoader("document.pdf")
# Prós: Rápido, simples
# Contras: Ruim com layouts complexos
# Opção 2: Melhor para tabelas (PDFPlumber)
from langchain.document_loaders import PDFPlumberLoader
loader = PDFPlumberLoader("document.pdf")
# Prós: Melhor extração de tabelas
# Contras: Mais lento
# Opção 3: Melhor qualidade (Unstructured)
from langchain.document_loaders import UnstructuredPDFLoader
loader = UnstructuredPDFLoader(
"document.pdf",
mode="elements", # Preserva a estrutura
strategy="hi_res" # Melhor qualidade
)
# Prós: Melhor qualidade geral
# Contras: Requer dependências adicionais
OCR para Documentos Escaneados
Para PDFs escaneados e imagens:
# Usando Tesseract OCR
from langchain.document_loaders import UnstructuredPDFLoader
loader = UnstructuredPDFLoader(
"scanned_document.pdf",
strategy="ocr_only",
ocr_languages="eng"
)
documents = loader.load()
# Usando Amazon Textract
from langchain.document_loaders import AmazonTextractPDFLoader
loader = AmazonTextractPDFLoader(
"scanned.pdf",
client=textract_client
)
Boas Práticas de OCR
- Pré-processar imagens - Corrigir inclinação, melhorar contraste
- Especificar idioma - Melhora a precisão
- Pós-processar texto - Corrigir erros comuns de OCR
- Pontuação de confiança - Marcar extrações com baixa confiança
Lidando com Tabelas
Tabelas exigem tratamento especial para preservar a estrutura:
# Método 1: Converter para Markdown
from langchain.document_loaders import UnstructuredPDFLoader
loader = UnstructuredPDFLoader(
"report.pdf",
mode="elements"
)
docs = loader.load()
# Tabelas vêm como elementos estruturados
for doc in docs:
if doc.metadata.get("category") == "Table":
# Processar tabela de forma especial
table_markdown = convert_table_to_markdown(doc)
# Método 2: Usando Camelot para PDFs
import camelot
tables = camelot.read_pdf("document.pdf", pages="all")
for table in tables:
df = table.df
markdown = df.to_markdown()
Estratégia de Divisão de Tabelas
def chunk_with_tables(documents):
chunks = []
for doc in documents:
if is_table(doc):
# Manter tabelas como blocos únicos
chunks.append(doc)
else:
# Divisão normal para texto
text_chunks = splitter.split_documents([doc])
chunks.extend(text_chunks)
return chunks
Imagens em Documentos
Extraia e processe imagens:
# Extrair imagens de PDF
import fitz # PyMuPDF
doc = fitz.open("document.pdf")
for page_num, page in enumerate(doc):
images = page.get_images()
for img_index, img in enumerate(images):
# Extrair imagem
xref = img[0]
base_image = doc.extract_image(xref)
image_bytes = base_image["image"]
# Processar com modelo de visão
description = vision_model.describe(image_bytes)
# Adicionar descrição ao documento
Integração com Modelo de Visão
from langchain.chat_models import ChatOpenAI
# Usar GPT-4 Vision para compreensão de imagens
vision_llm = ChatOpenAI(model="gpt-4-vision-preview")
def describe_image(image_path):
response = vision_llm.invoke([
{
"type": "image_url",
"image_url": f"data:image/jpeg;base64,{base64_image}"
},
{
"type": "text",
"text": "Descreva esta imagem em detalhes para busca de documentos."
}
])
return response.content
Dados Estruturados
JSON/JSONL
from langchain.document_loaders import JSONLoader
loader = JSONLoader(
file_path="data.json",
jq_schema=".data[].content",
text_content=False
)
CSV
from langchain.document_loaders import CSVLoader
loader = CSVLoader(
file_path="data.csv",
csv_args={"delimiter": ","},
source_column="source"
)
# Para CSVs grandes, processe em lotes
import pandas as pd
def load_csv_in_batches(file_path, batch_size=1000):
for chunk in pd.read_csv(file_path, chunksize=batch_size):
yield from chunk.to_dict('records')
Bancos de Dados SQL
from langchain.document_loaders import SQLDatabaseLoader
from langchain.utilities import SQLDatabase
db = SQLDatabase.from_uri("postgresql://user:pass@localhost/db")
loader = SQLDatabaseLoader(
db=db,
query="SELECT id, content, metadata FROM documents WHERE active = true"
)
Pipeline Completo de Processamento
from pathlib import Path
def process_document(file_path: str):
"""Processador universal de documentos"""
path = Path(file_path)
extension = path.suffix.lower()
loaders = {
".pdf": lambda p: UnstructuredPDFLoader(p, strategy="hi_res"),
".docx": lambda p: Docx2txtLoader(p),
".txt": lambda p: TextLoader(p, encoding="utf-8"),
".html": lambda p: UnstructuredHTMLLoader(p),
".md": lambda p: UnstructuredMarkdownLoader(p),
".csv": lambda p: CSVLoader(p),
".json": lambda p: JSONLoader(p, jq_schema=".[]")
}
if extension not in loaders:
raise ValueError(f"Unsupported file type: {extension}")
loader = loaders[extension](str(path))
documents = loader.load()
# Adicionar metadados do arquivo
for doc in documents:
doc.metadata["file_name"] = path.name
doc.metadata["file_type"] = extension
doc.metadata["file_size"] = path.stat().st_size
return documents
Resumo
| Tipo de Arquivo | Melhor Loader | Observações |
|---|---|---|
| PDF (texto) | PDFPlumberLoader | Suporte avançado a tabelas |
| PDF (escaneado) | UnstructuredPDFLoader + OCR | Use a estratégia hi_res |
| Word | Docx2txtLoader | Rápido e confiável |
| HTML | UnstructuredHTMLLoader | Remove tags |
| CSV | CSVLoader | Lote para arquivos grandes |
| Imagens | Modelos de visão | Para imagens embutidas |
Principais Pontos
- PDFs são complexos - Use o loader adequado para sua necessidade
- OCR para documentos escaneados - Essencial para PDFs baseados em imagem
- Tabelas exigem tratamento especial - Não divida blocos entre linhas
- Imagens precisam de descrição - Use modelos de visão
- Teste seu pipeline - Com amostras representativas
Próximos Passos
Teste seu conhecimento com o Quiz do Módulo 2!