Vision
O módulo Vision fornece um cliente para extrair dados estruturados de documentos (PDFs, imagens, etc.) utilizando layouts configurados na plataforma Tech4.ai. Ele encapsula a chamada HTTP para o serviço de extração e retorna um objeto tipado com os dados extraídos e o status da operação.
📋 Método Principal
extract(layout_id, file_url=None, file_id=None, timeout=45)
Realiza a extração de dados de um documento com base em um layout configurado e retorna VisionExtractResponse.
Parâmetros:
layout_id(str): Obrigatório. ID do layout Vision que define os campos a serem extraídosfile_url(str | None): URL pública do arquivo a ser analisado. Mutuamente exclusivo comfile_idfile_id(str | None): ID de um arquivo já enviado para a plataforma. Mutuamente exclusivo comfile_urltimeout(int): Tempo limite da requisição em segundos (padrão:45, máximo:45)
Exatamente um entre file_url e file_id deve ser fornecido. Passar ambos ou nenhum levanta ValueError.
Retorno (VisionExtractResponse):
status(Literal["ok", "partial", "nodata"]): Resultado da extração —"ok"(todos os campos extraídos),"partial"(alguns campos ausentes),"nodata"(nenhum campo pôde ser extraído)extracted_data(dict): Dicionário cujas chaves e tipos de valor dependem do layout configurado
Status de Extração
O campo status indica a qualidade do resultado retornado pelo serviço de extração.
| Status | Significado |
|---|---|
"ok" | Todos os campos do layout foram extraídos com sucesso |
"partial" | Parte dos campos foi extraída; campos ausentes ficam com valor None ou são omitidos |
"nodata" | Nenhum campo pôde ser extraído do documento (documento ilegível, fora do escopo do layout, etc.) |
Sempre verifique o status antes de usar extracted_data. Com "partial" ou "nodata", trate a ausência de campos antes de prosseguir com a lógica de negócio.
📥 Exemplo de Entrada e Saída
Entrada
vision.extract(
layout_id="3f2504e0-4f89-11d3-9a0c-0305e82c3301",
file_url="https://example.com/nota-fiscal.pdf",
)
Saída (exemplo real)
{
"status": "ok",
"extracted_data": {
"numero_nota": "3524",
"data_emissao": "2024-03-15",
"valor_total": 1250.00,
"cnpj_emitente": "12.345.678/0001-99",
"razao_social": "Empresa Exemplo LTDA"
}
}
Saída com extração parcial
{
"status": "partial",
"extracted_data": {
"numero_nota": "3524",
"data_emissao": null,
"valor_total": 1250.00,
"cnpj_emitente": null,
"razao_social": "Empresa Exemplo LTDA"
}
}
📝 Exemplo Prático
Extrair dados de uma nota fiscal a partir de URL
def extrair_dados_nota_fiscal(file_url: str):
"""
Extrai dados estruturados de uma nota fiscal usando Vision
"""
try:
extract_span = action_span.span("extração vision", {"file_url": file_url})
response = vision.extract(
layout_id=secrets["VISION_LAYOUT_ID"],
file_url=file_url,
)
extract_span.end({"status": response.status})
action_span.event("vision_response", {"status": response.status})
if response.status == "nodata":
return ResponseToUser(
message="Não foi possível extrair informações do documento enviado.",
status=ResponseStatus.SUCCESS,
)
dados = response.extracted_data
if response.status == "partial":
action_span.event("partial_extraction", {"dados": dados})
numero = dados.get("numero_nota", "N/D")
valor = dados.get("valor_total", "N/D")
mensagem = f"Nota fiscal {numero} processada com sucesso. Valor total: R$ {valor}."
return ResponseToUser(message=mensagem, status=ResponseStatus.SUCCESS)
except Exception as e:
action_span.event("error", {"error": str(e)})
return ResponseToUser(
message=(
"Peço desculpas, não foi possível processar o documento no momento. "
"Tente novamente em alguns instantes."
),
status=ResponseStatus.ERROR,
metadata={
"error_type": "vision_extraction_error",
"error_message": str(e),
},
)
Extrair dados usando ID de arquivo já enviado
def extrair_dados_por_file_id(file_id: str):
"""
Extrai dados de um arquivo já presente na plataforma
"""
response = vision.extract(
layout_id=secrets["VISION_LAYOUT_ID"],
file_id=file_id,
timeout=45,
)
if response.status != "ok":
return ResponseToUser(
message="Extração incompleta ou sem dados.",
status=ResponseStatus.SUCCESS,
)
return ResponseToUser(
message=str(response.extracted_data),
status=ResponseStatus.SUCCESS,
)
💡 Dicas de Uso
- Status antes dos dados: verifique sempre
response.statusantes de acessarextracted_data file_urlvsfile_id: prefirafile_idquando o arquivo já foi enviado viaFileManagementpara evitar reprocessamento- Timeout: o limite máximo é 45 s; documentos longos que excedam esse tempo resultarão em erro
- Layout ID via secrets: armazene o
layout_idcomo segredo (secrets["VISION_LAYOUT_ID"]) para facilitar troca entre ambientes
📊 Estruturas de Dados
Classes Principais
VisionExtractResponse:status,extracted_datastatus(Literal["ok", "partial", "nodata"]): resultado da extraçãoextracted_data(dict): campos extraídos conforme definido no layout
Erros
Exception: levantado em falhas HTTP (4xx/5xx), erros de rede ou respostas malformadas. Capture-o para tratar erros de extração sem derrubar a action.