Pular para o conteúdo

planejamento

Estrutura técnica do pipeline de orçamento

  • obras
  • ia
  • dados

As duas notas anteriores cobrem o quê: o roteiro das oito etapas, com o que entra e sai de cada uma, e os arquivos e o lugar da IA. Esta cobre o como — repositório, pastas, banco, orquestração e geração dos artefatos finais. É a parte que faz o pipeline virar projeto de verdade, em vez de um documento explicando a intenção.

Duas camadas de repositório, não uma

Separar isso desde o início evita um problema comum: dado sensível de cliente — salário, cotação, projeto — misturado no histórico git do código.

O motor é um pacote Python instalável, com toda a lógica reutilizável: parsers, cálculo determinístico, prompts de IA. Versionado e testado como qualquer biblioteca.

A obra é um workspace por projeto, instanciado de um template com cookiecutter ou copier, contendo só o dado daquela obra: config, dado bruto, notebook de exploração. Importa o motor como dependência, não duplica código dele.

A separação resolve de cara a questão de manter código longe de artefato de entrada e saída: o motor nunca tem dado de obra dentro; a obra nunca tem lógica de cálculo dentro, só config e dado.

Pastas por nível de confiança

Vale emprestar o vocabulário de engenharia de dados — a arquitetura em camadas, às vezes chamada de bronze, prata e ouro. Cada pasta carrega uma garantia diferente sobre o que está dentro dela.

obra-nome/
├── config/
│   ├── eap_sinapi_crosswalk.yaml
│   ├── eap_ifc_crosswalk.yaml
│   └── aliquotas.yaml
├── data/
│   ├── 00_raw/          exatamente como chegou — nunca editar, só ler
│   │   ├── projetos/    dwg, ifc, pdf
│   │   ├── edital/
│   │   └── cotacoes/
│   ├── 10_interim/      convertido, ainda não validado
│   ├── 20_processed/    canônico e validado — eap.json, quantitativos.csv
│   └── 90_external/     sinapi_2026-09.xlsx, legislação — data no nome
├── db/
│   └── obra.sqlite
├── notebooks/           exploração — nunca lógica de produção
└── reports/
    └── 2026-09-18/
        ├── orcamento_final.xlsx
        ├── orcamento_final.pdf
        └── dashboard.html

00_raw é intocável por convenção: qualquer script que escreva nela é bug. Isso garante um ponto de restauração sempre disponível — se um parser tiver erro, o reprocessamento parte do bruto, sem nunca perder a fonte original.

No motor, o src/ reflete a arquitetura conceitual da nota anterior:

src/orcamento/
├── extract/     ifc.py, dxf.py, pdf.py, xlsx.py
├── canonical/   schema pydantic da EAP
├── calc/        cronograma (CPM), custos, BDI, curva ABC — determinístico
├── ai/          prompts, RAG, sugestão de classificação
├── validate/    regras pandera — separado de ai/ de propósito
└── report/      geração de xlsx, pdf e html

Ter ai/ e calc/ fisicamente separados força, na própria arquitetura, a regra central da nota anterior: código de IA nunca escreve direto num campo de dinheiro. Ele produz sugestão, que passa por validate/ antes de entrar em calc/.

SQLite e DuckDB fazem trabalhos diferentes

SQLite DuckDB
Papel fonte da verdade transacional — EAP, status por etapa, vínculos entre documentos motor analítico — curva ABC, agregações, cronograma físico-financeiro
Ponto forte escreve incrementalmente, fácil de versionar lê CSV e Parquet direto, sem ETL, rápido em agregação
Quando durante o pipeline, obra por obra na etapa 8, para consolidar e explorar

Não é escolha excludente: dá para manter o SQLite como fonte e gerar uma view em Parquet para o DuckDB consultar no fechamento.

As oito etapas já são um DAG

Cada etapa do roteiro consome a saída da anterior — isso é a definição de um grafo de dependência. O que abre espaço para uma ferramenta de orquestração em vez de pasta e script soltos.

DVC é o ponto de partida natural para quem roda obra por obra. Cada etapa vira um stage no dvc.yaml, com deps e outs explícitos, e dvc repro só reprocessa o que mudou — atualizou a base SINAPI, roda da etapa 5 em diante. Ele também versiona os binários (DWG, IFC, XLSX) fora do git: no repositório fica só um ponteiro pequeno, e o byte real vai para um armazenamento à parte. É, na prática, um git pensado para pipeline de dado.

Dagster, com seu modelo de assets, compensa se o projeto crescer para várias obras em paralelo com equipe em cima. Cada etapa vira um asset com histórico de dependência automático e uma interface mostrando o que está desatualizado. É infraestrutura maior, e só se paga em escala.

O humano no loop

Em vez de construir uma interface de aprovação sob medida para validar sugestão de IA — o crosswalk EAP↔SINAPI, por exemplo —, deixe a IA propor a mudança como um diff: um branch alterando o eap_sinapi_crosswalk.yaml, aberto como pull request.

Revisão de diff em YAML é exatamente para isso que serve, e o registro de quem aprovou o quê sai de graça. Para quem precisa revisar sem conforto com git, uma tela fina em Streamlit sobre o mesmo arquivo resolve — mas o mecanismo de fundo continua o mesmo: mudança proposta, aprovação, merge.

Para validação de schema — quantidade maior que zero, unidade dentro de um conjunto esperado —, pandera ou pydantic rodando como parte do pipeline capturam erro de conversão antes que ele vire número na planilha.

Gerando os artefatos finais

XLSX com openpyxl preenchendo um template existente, em vez de recriar a planilha do zero em código — mantém a fórmula e a formatação que a empresa já usa.

PDF com WeasyPrint, que converte HTML e CSS e vai bem em relatório tabular, ou ReportLab quando for preciso mais controle de layout. Vale olhar também o Quarto: de uma fonte só ele gera HTML, PDF e DOCX juntos, com tabela e gráfico reprodutíveis — útil se o painel e o relatório impresso devem sair do mesmo lugar.

HTML com Jinja2 para relatório estático por obra. Se o objetivo for algo navegável, uma tela fina em Streamlit sobre o SQLite ou o DuckDB.

Convenções do motor

Layout src/, pyproject.toml, uv ou poetry para dependência, tests/ espelhando src/, pre-commit com ruff, e integração contínua rodando teste e validação de schema a cada push.

O versionamento semântico importa aqui de um jeito específico: uma obra em andamento não deveria sofrer mudança incompatível no meio do orçamento. Então a obra trava a versão do motor que está usando.

Um Makefile ou justfile com comando padronizado — make etapa4, make relatorio — poupa quem não quer decorar a sintaxe do orquestrador escolhido.

A pasta de entrega

reports/<data-revisão>/ reunindo o orçamento final, a curva ABC e o cronograma físico-financeiro — mais uma cópia congelada do manual e do checklist preenchido daquela obra.

É essa cópia que garante que, um ano depois, quem abrir a pasta entenda exatamente o que era dado real, o que foi gerado por IA, e com que fonte.

Sobre este texto

Documento vivo, v1 como os dois anteriores. A escolha entre DVC e Dagster, em especial, depende da escala real de uso — vale revisar depois de rodar algumas obras pelo pipeline.