Converte documentos corporativos (PDF, DOCX, XLSX, HTML, ZIP) em Markdown estruturado otimizado para LLMs e pipelines RAG.
- Instalação Rápida
- Uso Básico
- Uso no Google Colab (Para Iniciantes)
- API Reference
- Exemplos Avançados
- Benchmarks
- Troubleshooting
- Roadmap
- Contribuindo
- Licença
pip install kazuba-converterdocker pull kazuba/converter:latest
docker run -v $(pwd):/data kazuba/converter /data/input.pdf /data/output/conda install -c kazuba kazuba-converter| Aspecto | PDF Original | Markdown Convertido |
|---|---|---|
| Tamanho | Binário (sem compressão) | Texto puro (~60% menor) |
| Tokens | Ineficiente (fragmentado) | Eficiente (estruturado) |
| RAG | Contexto perdido | Hierarquia preservada |
| Custo | Alto (mais tokens) | Baixo (menos tokens) |
- 60% menos tokens para mesma informação
- 95% accuracy em extração de tabelas (vs. 70% com PDF cru)
- 10-50x speedup com batch processing e worker pool persistente
- $0 custo vs. ~$180K/ano em Cloud APIs para 10K docs/mês
| Dimensão | kazuba-converter | MarkItDown | Pandoc | Cloud APIs |
|---|---|---|---|---|
| OCR | ✅ Cascade (Paddle→Easy→Tesseract) | ❌ Não possui | ✅ Avançado | |
| Tabelas | ✅ ML (Docling 97.9%) | ✅ Avançado | ||
| GPU Opt | ✅ A100/V100/T4 auto | ❌ Não | ❌ Não | |
| Batch | ✅ Checkpoint/resume | ❌ Não | ❌ Não | ✅ Via API |
| Custo (10K/mês) | $0 | $0 | $0 | ~$180K/ano |
| Offline | ✅ 100% | ✅ 100% | ✅ 100% | ❌ Cloud-only |
| Setup | 5 minutos | 2 minutos | 10 minutos | 4 horas |
| Tabelas PT-BR | ✅ Excelente | ✅ Boa |
| Cenário | Recomendação |
|---|---|
| Casual (< 50 docs) | MarkItDown — leve, simples |
| LaTeX/EPUB | Pandoc — 32+ formatos |
| PDFs escaneados PT-BR | kazuba-converter — PaddleOCR nativo |
| Volume alto (> 1K/mês) | kazuba-converter — batch + checkpoint |
| Pipeline RAG | kazuba-converter — estrutura semântica |
| Máx accuracy + budget | Cloud APIs — 95-98% OCR |
# Converter um arquivo
kazuba-converter documento.pdf ./output/
# Converter com OCR (PDFs escaneados)
kazuba-converter documento.pdf ./output/ --ocr
# Converter pasta inteira (paralelo)
kazuba-converter ./pasta_documentos/ ./output/ --workers 8
# Batch com checkpoint (resume automático)
kazuba-converter batch ./input/ ./output/ --workers 8 --checkpoint job.jsonfrom converter import convert_file, batch_convert
# Conversão simples
result = convert_file(
"documento.pdf",
output_dir="./output",
ocr=True,
extract_tables=True
)
# Batch com progresso
for result in batch_convert(
source="./pasta/",
output_dir="./output/",
workers=8,
checkpoint="job.json"
):
print(f"Processado: {result.file_path}")Ideal para: Usuários de computadores organizacionais (sem permissão de admin) ou quem prefere não instalar nada localmente.
O Google Colab é uma ferramenta gratuita do Google que permite executar o kazuba-converter direto no navegador, sem instalar nada no seu computador. Funciona até em computadores corporativos com restrições.
Clique no link abaixo (vai abrir no seu navegador):
👉 Abrir kazuba-converter no Colab

- No menu superior, clique em "Arquivo" → "Salvar uma cópia no Drive"
- Isso cria sua própria versão editável

- Na primeira célula (onde está escrito
!pip install kazuba-converter) - Clique no botão
▶️ Play à esquerda - Aguarde 30-60 segundos

Clique no ícone de pasta 📁 no menu lateral esquerdo:
Depois clique em "Fazer upload para o armazenamento da sessão":
Selecione os arquivos do seu computador (PDFs, DOCXs, etc.)
Role para baixo até a seção "Conversão". Você verá algo assim:
# CONFIGURAÇÃO SIMPLES
ARQUIVOS = ["documento.pdf"] # Mude para o nome do seu arquivo
PASTA_SAIDA = "./convertidos"
# CONVERTER
!kazuba-converter {ARQUIVOS[0]} {PASTA_SAIDA} --ocrPara converter:
- Substitua
"documento.pdf"pelo nome exato do seu arquivo - Clique no botão
▶️ Play - Aguarde (aparecerá uma barra de progresso)
Após a conversão, seus arquivos aparecerão na pasta convertidos/:
- Clique na pasta 📁 no menu lateral
- Navegue até
convertidos/ - Clique com botão direito no arquivo
- Selecione "Download"

Se quiser converter vários arquivos de uma vez, use este código:
# ==========================================
# CONVERSÃO EM LOTE - COPIE E COLE
# ==========================================
from google.colab import files
import os
# 1. FAZER UPLOAD DOS ARQUIVOS
print("📤 Faça upload dos seus arquivos:")
uploaded = files.upload() # Abre janela de seleção de arquivos
# 2. CRIAR PASTA DE SAÍDA
!mkdir -p convertidos
# 3. CONVERTER TODOS OS ARQUIVOS
for filename in uploaded.keys():
print(f"\n🔍 Convertendo: {filename}")
!kazuba-converter "{filename}" ./convertidos/ --ocr
# 4. MOSTRAR RESULTADOS
print("\n✅ Conversão completa! Arquivos gerados:")
!ls -lh ./convertidos/
# 5. DOWNLOAD AUTOMÁTICO DE TODOS
print("\n📥 Baixando arquivos...")
for filename in os.listdir('./convertidos/'):
files.download(f'./convertidos/{filename}')
print("\n🎉 Pronto! Verifique a pasta de downloads do seu navegador.")Como usar:
- Copie o código acima
- No Colab, clique em + Código (botão no canto superior esquerdo)
- Cole o código na nova célula
- Clique em
▶️ Play
| Situação | Solução |
|---|---|
| Computador bloqueado (sem instalar nada) | ✅ Use o Colab — não precisa instalar nada |
| Arquivos confidenciais | |
| Muitos arquivos (>100) | Use o modo batch no Colab (ver Exemplos Avançados) |
| PDFs escaneados | Sempre use a flag --ocr para melhor resultado |
- Sessão expira: Após 90 minutos de inatividade, os arquivos são apagados
- Memória: Limite de ~12GB RAM (suficiente para 99% dos casos)
- GPU: Opcional, acelera OCR em documentos grandes
Dica: Baixe os arquivos convertidos imediatamente após a conversão!
Converte um único arquivo para Markdown.
convert_file(
file_path: str | Path,
output_dir: str | Path,
*,
ocr: bool = False,
extract_tables: bool = True,
extract_images: bool = False,
frontmatter: bool = True,
page_markers: bool = True,
encoding: str = "utf-8"
) -> ConversionResultParâmetros:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
file_path |
str/Path | obrigatório | Caminho do arquivo de entrada |
output_dir |
str/Path | obrigatório | Diretório de saída |
ocr |
bool | False | Ativar OCR para PDFs escaneados |
extract_tables |
bool | True | Extrair tabelas com ML |
extract_images |
bool | False | Extrair imagens embutidas |
frontmatter |
bool | True | Incluir YAML frontmatter |
page_markers |
bool | True | Incluir marcadores de página |
encoding |
str | "utf-8" | Encoding de saída |
Retorno:
@dataclass
class ConversionResult:
file_path: Path # Caminho do arquivo de entrada
output_path: Path # Caminho do arquivo convertido
success: bool # Sucesso da conversão
format_detected: str # Formato detectado
pages: int # Número de páginas (PDF)
processing_time: float # Tempo em segundos
error_message: str # Mensagem de erro (se falhou)Exemplo:
from converter import convert_file
result = convert_file(
"contrato.pdf",
"./output",
ocr=True,
extract_tables=True
)
if result.success:
print(f"✅ Convertido: {result.output_path}")
print(f"⏱️ Tempo: {result.processing_time:.2f}s")
else:
print(f"❌ Erro: {result.error_message}")Converte múltiplos arquivos com paralelização.
batch_convert(
source: str | Path,
output_dir: str | Path,
*,
workers: int = 4,
checkpoint: str | Path | None = None,
pattern: str = "*",
ocr: bool = False,
extract_tables: bool = True,
progress_callback: Callable | None = None
) -> Iterator[ConversionResult]Parâmetros:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
source |
str/Path | obrigatório | Arquivo ou diretório de entrada |
output_dir |
str/Path | obrigatório | Diretório de saída |
workers |
int | 4 | Número de workers paralelos |
checkpoint |
str/Path/None | None | Arquivo de checkpoint para resume |
pattern |
str | "*" | Padrão glob para filtrar arquivos |
ocr |
bool | False | Ativar OCR |
extract_tables |
bool | True | Extrair tabelas |
progress_callback |
Callable | None | Callback de progresso |
Exemplo:
from converter import batch_convert
# Com checkpoint (resume automático)
for result in batch_convert(
source="./input/",
output_dir="./output/",
workers=8,
checkpoint="conversion_job.json"
):
status = "✅" if result.success else "❌"
print(f"{status} {result.file_path.name}")Orquestrador completo para jobs de conversão.
from converter.batch_processor import BatchProcessor, ConversionJob
processor = BatchProcessor(
workers=8,
checkpoint_file="job.json"
)
# Criar jobs
jobs = [
ConversionJob(file_path="doc1.pdf"),
ConversionJob(file_path="doc2.pdf"),
]
# Processar com callback de progresso
def on_progress(completed, total, current_file):
print(f"Progresso: {completed}/{total}")
results = processor.process(
jobs=jobs,
output_dir="./output",
progress_callback=on_progress
)kazuba-converter convert INPUT [OUTPUT] [OPTIONS]
Arguments:
INPUT Arquivo ou diretório de entrada
OUTPUT Diretório de saída (padrão: ./output)
Options:
--ocr Ativar OCR
--workers N Número de workers (padrão: 4)
--checkpoint FILE Arquivo de checkpoint
--pattern PATTERN Padrão glob (padrão: "*")
--extract-tables Extrair tabelas (padrão: True)
--extract-images Extrair imagens
--no-frontmatter Omitir YAML frontmatter
-v, --verbose Modo verbosekazuba-converter batch INPUT OUTPUT [OPTIONS]
Options específicas de batch:
--workers N Workers paralelos (padrão: 4)
--checkpoint FILE Checkpoint para resume
--reset Resetar checkpoint existente
--pattern "*.pdf" Filtrar por extensãofrom converter import batch_convert
from pathlib import Path
import json
# 1. Converter corpus
corpus_dir = Path("./corpus_pdfs")
output_dir = Path("./corpus_md")
results = list(batch_convert(
source=corpus_dir,
output_dir=output_dir,
workers=8,
ocr=True,
checkpoint="rag_conversion.json"
))
# 2. Estatísticas
successful = sum(1 for r in results if r.success)
failed = len(results) - successful
print(f"✅ Sucesso: {successful}")
print(f"❌ Falhas: {failed}")
# 3. Criar índice para vector store
index = []
for r in results:
if r.success:
index.append({
"source": str(r.file_path),
"markdown": str(r.output_path),
"pages": r.pages,
"format": r.format_detected
})
with open("corpus_index.json", "w") as f:
json.dump(index, f, indent=2)from converter import convert_file
from langchain.document_loaders import TextLoader
from langchain.text_splitter import MarkdownHeaderTextSplitter
# 1. Converter PDF
result = convert_file("contrato.pdf", "./temp/")
# 2. Carregar Markdown
loader = TextLoader(result.output_path)
docs = loader.load()
# 3. Split por headers (preserva contexto)
markdown_splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[
("#", "header_1"),
("##", "header_2"),
("###", "header_3"),
]
)
chunks = markdown_splitter.split_text(docs[0].page_content)
print(f"Documento dividido em {len(chunks)} chunks")
for chunk in chunks[:3]:
print(f"- {chunk.metadata.get('header_1', 'Sem header')}")from converter import convert_file
import pandas as pd
import re
def extract_tables_to_csv(markdown_path, output_dir):
"""Extrai tabelas Markdown para arquivos CSV."""
with open(markdown_path) as f:
content = f.read()
# Encontrar todas as tabelas Markdown
table_pattern = r'\|[^\n]+\|\n\|[-:| ]+\|\n(?:\|[^\n]+\|\n)+'
tables = re.findall(table_pattern, content)
for i, table_md in enumerate(tables):
# Converter para DataFrame
lines = [line.strip() for line in table_md.strip().split('\n')]
headers = [h.strip() for h in lines[0].split('|')[1:-1]]
rows = []
for line in lines[2:]: # Pula header e separator
row = [cell.strip() for cell in line.split('|')[1:-1]]
rows.append(row)
df = pd.DataFrame(rows, columns=headers)
# Salvar CSV
csv_path = Path(output_dir) / f"table_{i+1}.csv"
df.to_csv(csv_path, index=False)
print(f"💾 Tabela {i+1}: {csv_path}")
# Uso
result = convert_file("relatorio.pdf", "./output/", extract_tables=True)
extract_tables_to_csv(result.output_path, "./output/tables/")from converter import batch_convert
import time
class ProgressTracker:
def __init__(self):
self.start_time = time.time()
self.completed = 0
self.failed = 0
def on_progress(self, completed, total, current_file):
self.completed = completed
elapsed = time.time() - self.start_time
rate = completed / elapsed if elapsed > 0 else 0
eta = (total - completed) / rate if rate > 0 else 0
print(f"\r📊 {completed}/{total} | "
f"⚡ {rate:.1f} docs/s | "
f"⏱️ ETA: {eta/60:.1f}min", end="")
tracker = ProgressTracker()
results = list(batch_convert(
source="./input/",
output_dir="./output/",
workers=8,
progress_callback=tracker.on_progress
))
print(f"\n✅ Concluído! Processados {len(results)} documentos")from converter import convert_file
import re
def validate_conversion(result, min_text_ratio=0.5):
"""
Valida qualidade da conversão.
Retorna True se passou em todos os critérios.
"""
checks = {
"success": result.success,
"has_content": False,
"valid_markdown": False,
"no_gibberish": False,
}
if not result.success:
return checks
# Ler conteúdo convertido
with open(result.output_path) as f:
content = f.read()
# Verificar se tem conteúdo significativo
text_length = len(re.sub(r'[#\|\-\*\s]', '', content))
checks["has_content"] = text_length > 100
# Verificar estrutura Markdown válida
has_headers = bool(re.search(r'^#+ ', content, re.MULTILINE))
checks["valid_markdown"] = has_headers or len(content) > 500
# Verificar ausência de caracteres corrompidos (mojibake)
gibberish_patterns = [r'ç', r'ã', r'ô', r'á']
checks["no_gibberish"] = not any(
re.search(p, content) for p in gibberish_patterns
)
return checks
# Uso
result = convert_file("documento.pdf", "./output/")
validation = validate_conversion(result)
print("Validação:")
for check, passed in validation.items():
status = "✅" if passed else "❌"
print(f" {status} {check}")- CPU: Intel i9-14900HX (24 cores)
- GPU: NVIDIA RTX 4060 8GB
- RAM: 64GB DDR5
- SSD: NVMe 1TB
- Python: 3.12.3
- Fonte: 100 documentos regulatórios ANTT
- Mix: 60% PDFs nativos, 40% PDFs escaneados
- Tamanho médio: 45 páginas
- Total de páginas: 4,500
| Métrica | kazuba-converter | MarkItDown | Pandoc |
|---|---|---|---|
| Throughput (págs/min) | 125 | 45 | 30 |
| Accuracy OCR | 92% | 78% | N/A |
| Accuracy Tabelas | 95% | 65% | 60% |
| Preservação de estrutura | Excelente | Boa | Regular |
| Uso de memória (pico) | 3.2GB | 1.8GB | 1.2GB |
| Taxa de erro | 3% | 12% | 18% |
| Workers | Throughput (docs/min) | CPU Usage | Memória |
|---|---|---|---|
| 1 | 2.5 | 15% | 800MB |
| 4 | 8.2 | 45% | 1.8GB |
| 8 | 12.5 | 78% | 3.2GB |
| 12 | 13.8 | 95% | 4.1GB |
| 16 | 14.2 | 100% | 4.8GB |
Ponto de saturação: 8-10 workers (diminuição de retornos após 12)
# Use o script de benchmark incluído
python benchmark.py \
--input ./test_corpus/ \
--output ./results/
# Ou rode via pytest
pytest tests/ -v --benchmark-onlyCausa: Instalação incompleta ou ambiente virtual não ativado.
Solução:
# Verifique instalação
pip list | grep kazuba-converter
# Reinstale
pip uninstall kazuba-converter
pip install kazuba-converter --force-reinstallCausa: Tesseract OCR não instalado no sistema.
Solução:
# Ubuntu/Debian
sudo apt-get install tesseract-ocr tesseract-ocr-por
# macOS
brew install tesseract
# Windows
# Download: https://github.com/UB-Mannheim/tesseract/wiki
# Adicione ao PATH
# Verifique instalação
tesseract --versionCausa: PaddleOCR requer numpy < 2.0, versões conflitantes.
Solução:
# Crie ambiente limpo
python -m venv venv_converter
source venv_converter/bin/activate
# Instale na ordem correta
pip install numpy==1.26.4
pip install paddlepaddle-gpu # ou paddlepaddle para CPU
pip install kazuba-converterCausa: CUDA/cuDNN incompatível ou não instalado.
Solução:
# Verifique versões compatíveis
python -c "import paddle; paddle.utils.run_check()"
# Para GPU NVIDIA, instale versão compatível
pip uninstall paddlepaddle paddlepaddle-gpu
pip install paddlepaddle-gpu==2.6.1 -f \
https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.htmlCausa: PDFs mal-formados ou não-standards.
Solução:
from converter import convert_file
# Tente com modo robusto
result = convert_file(
"documento_corrompido.pdf",
"./output/",
ocr=True, # OCR como fallback
repair_pdf=True # Tenta reparar antes de converter
)
if not result.success:
print(f"PDF não recuperável: {result.error_message}")Causa: PDFs muito grandes (>500MB) ou com muitas imagens.
Solução:
from converter import convert_file
# Processe página por página
result = convert_file(
"documento_grande.pdf",
"./output/",
memory_limit="4GB", # Limite de memória
page_batch_size=10 # Processa 10 páginas por vez
)Causa: Arquivo de checkpoint corrompido.
Solução:
# Reset checkpoint e reinicie
rm checkpoint.json
kazuba-converter batch ./input/ ./output/ --workers 8# Execute com verbose máximo
kazuba-converter documento.pdf ./output/ -vvv
# Log para arquivo
kazuba-converter batch ./input/ ./output/ --log-level DEBUG 2>&1 | tee conversion.log- Extração PDF → Markdown (pymupdf4llm)
- OCR cascata (Tesseract fallback)
- Extração de tabelas (4 engines)
- Suporte a DOCX, XLSX, HTML, ZIP
- Worker pool persistente
- Checkpoint/resume
- Batch processor com progresso
- CLI completo
- Publicação PyPI
- CI/CD pipeline (GitHub Actions)
- Testes automatizados (pytest)
-
Documentação técnica completa
- API reference detalhado (100% coverage)
- Guia de contribuição (CONTRIBUTING.md)
- Documentação de arquitetura
-
Testes adicionais
- Unit tests (target: 90%+ coverage)
- Integration tests
- Benchmarks automatizados
-
Simplificação de setup
- Docker image oficial
- Conda package
- One-line install script
- Troubleshooting wizard
-
Versionamento semântico rigoroso
- CHANGELOG detalhado
- Migration guides
- Deprecation warnings
-
Roadmap público com ETAs
- GitHub Projects
- Milestones definidos
- Feature requests via issues
-
API REST
- FastAPI backend
- Async processing
- Webhook callbacks
- OpenAPI/Swagger docs
-
Redução de dependências
- Dependências opcionais (extras)
- Lazy loading
- Plugin architecture
- Interface web
- Integração SEI (download direto)
- Suporte a PPTX aprimorado
- OCR GPU multi-backend
- Streaming para arquivos grandes
- Distributed processing
Quer contribuir? Ótimo! Veja CONTRIBUTING.md para guidelines.
- Testes — Aumentar cobertura para 90%+
- Documentação — Tutoriais, cookbooks, exemplos
- Performance — Otimizações de OCR e batch
- Plataformas — Suporte Windows/macOS melhorado
MIT License — veja LICENSE para detalhes.

