Jangada AIJangada AI

Documentos (docx, pdf, csv, xlsx)

Anexe arquivos a qualquer chamada com files=. Por padrão a jangada extrai o texto do arquivo localmente em vez de usar vision — é mais barato e funciona em qualquer modelo, inclusive os sem visão.

pip install "jangada-ai[files]"   # pypdf, python-docx, openpyxl
from jangada_ai import LLM, Document

llm = LLM("openai", "gpt-4o-mini")

# caminhos: tipo detectado pela extensão
llm.complete("Resuma:", files=["relatorio.pdf", "contrato.docx"])

# xlsx: TODAS as abas entram, cada uma rotulada (## Aba: ...)
llm.complete("Maior total?", files=[Document("vendas.xlsx", max_rows=200)])

# bytes em memória (upload/fila) — informe o nome para detectar o tipo
llm.parse("Há duplicadas?", Relatorio, files=[Document(blob, name="x.csv")])

# forçar vision (PDF escaneado / quando o layout importa)
llm.complete("Transcreva:", files=[Document("scan.pdf", mode="vision")])

Regra de mode

modeComportamento
"auto"(padrão) extrai texto de csv/xlsx/docx/pdf-com-texto; imagem → vision
"text"força extração de texto (erro se o formato não tiver texto)
"vision"força o caminho de imagem

Por que não usar vision para tudo

  • Mais barato: texto custa muito menos que tokens de imagem.
  • Funciona em qualquer modelo, inclusive sem visão.
  • Preserva tabelas como markdown.

Um PDF sem camada de texto (escaneado) levanta DocumentError sugerindo mode="vision" — nunca devolve um bloco vazio em silêncio.

Detalhes

  • files= existe em complete/parse/stream (sync e async) e convive com images=.
  • A conversão acontece na fronteira do client (files.py → to_part()): cada arquivo vira TextPart ou ImagePart, então os adapters nunca veem formato de documento.
  • Formatos: .csv, .tsv, .xlsx, .xlsm, .docx, .pdf, além de texto puro (.txt, .md, .json, ...).

Relacionado: Vision, Structured output.

O que mudou na 1.9.0

  • PDF escaneado com mode="vision" funciona de verdade: cada página é renderizada em PNG (até Document(..., max_pages=20)) e vai como imagem. Usa o pypdfium2 (agora no extra [files]) ou o pymupdf, se instalado; sem nenhum dos dois, o erro diz o que instalar. A lib nunca manda um PDF como se fosse imagem (isso dava 400 no provider). Para montar as partes você mesmo: jangada_ai.files.to_parts(doc) devolve uma parte por página.
  • Encoding de CSV: tenta UTF-8 (com e sem BOM), depois cp1252 e latin-1 — CSV exportado do Excel brasileiro não vira mais �.
  • CSV/TSV grandes são lidos em streaming até max_rows; .tsv usa o extrator próprio.
  • PDF protegido: tenta abrir com senha vazia; se não der, levanta DocumentError claro (PDF corrompido também).
  • xlsx: célula de fórmula sem valor calculado aparece como [fórmula sem valor calculado: =...] em vez de vazia; | e quebras de linha nas células são escapados na tabela markdown.
  • Bytes sem nome: o formato é detectado pelo conteúdo (PDF, PNG, JPEG, GIF, WEBP, BMP, docx, xlsx).
from jangada_ai import LLM, Document

llm = LLM("gemini", "gemini-3.5-flash")
comp = llm.complete("Transcreva a nota fiscal.",
                    files=[Document("nota_escaneada.pdf", mode="vision", max_pages=3)])

Exemplo

examples/files_example.py — script executável.

On this page