API responsável pelo processamento, armazenamento e análise de faturas de energia elétrica.
O sistema recebe PDFs de contas de energia, extrai automaticamente as informações via LLM, persiste os dados estruturados e disponibiliza endpoints para listagem e visualização de indicadores de consumo e economia.
- Upload de PDF de conta de energia
- Extração automática dos dados da fatura via LLM multimodal
- Criação automática de cliente (caso não exista)
- Criação da fatura e seus itens
- Cálculo de consumo total, energia compensada e economia de geração distribuída
- Detecção de duplicidade por número do documento
Permite visualizar faturas já processadas com paginação e filtros.
Filtros disponíveis:
- Número do cliente
- Mês de referência
Informações retornadas:
- Consumo total
- Energia compensada
- Valor sem GD
- Economia GD
- Itens detalhados da fatura
Agrega dados históricos de consumo.
Retorna:
- Consumo total (kWh)
- Energia compensada total (kWh)
- Quantidade de faturas
- Série temporal mensal contendo:
- mês de referência
- consumo
- energia compensada
- quantidade de faturas
Objetivo: análise de comportamento energético do cliente.
Agrega dados financeiros da geração distribuída.
Retorna:
- Total gasto sem GD
- Economia total gerada pela GD
- Quantidade de faturas
- Série temporal mensal contendo:
- mês de referência
- valor sem GD
- economia gerada
- quantidade de faturas
Objetivo: análise de retorno financeiro da geração solar.
O processamento da fatura não utiliza OCR tradicional baseado em coordenadas fixas.
A API utiliza um modelo multimodal (Google Gemini) capaz de interpretar diretamente o PDF como documento visual + textual, permitindo:
- leitura de layouts variáveis de concessionárias
- interpretação semântica dos campos
- identificação de blocos tarifários
- extração robusta mesmo com mudanças de formatação
- O PDF é enviado para a API
- O arquivo é convertido para base64
- O modelo recebe:
- instruções (prompt estruturado)
- documento multimodal
- O modelo retorna JSON estruturado
- O JSON é validado por schema
- Somente dados válidos são persistidos
A resposta da LLM não é confiada diretamente.
Ela passa por um schema validator:
- JSON inválido → rejeitado
- Tipos incorretos → rejeitado
- Campos obrigatórios ausentes → rejeitado
Isso garante previsibilidade no domínio e impede persistência de dados alucinados.
A API separa erros em categorias:
| Tipo | Significado |
|---|---|
| LLM API Error | falha de comunicação / timeout / provider |
| Parse Error | retorno não é JSON |
| Validation Error | retorno não corresponde ao schema |
| Business Error | não é uma fatura válida |
Essa separação permite observabilidade e métricas reais da qualidade do modelo.
POST /invoices
Recebe um PDF e inicia o processamento.
Request: multipart/form-data file: pdf
Response:
- id
- fileName
- status
- message
GET /invoices
Query params:
- page (obrigatório)
- limit (obrigatório)
- customerNumber (opcional)
- referenceMonth (opcional)
GET /dashboard/energy
Query params:
- customerNumber (opcional)
GET /dashboard/finance
Query params:
- customerNumber (opcional)
A arquitetura foi pensada para lidar com três desafios principais do domínio:
- documentos com layout variável
- uso de IA não determinística
- dados financeiros que exigem consistência
O objetivo não foi apenas “fazer funcionar”, mas garantir previsibilidade do sistema mesmo dependendo de um provider externo.
A aplicação segue o padrão Use Cases + Repositories + Gateways.
Motivos:
- separação clara entre domínio e integrações externas
- facilidade de testar sem depender de LLM ou banco
- tratamento padronizado de erros
- estrutura estável para crescer sem virar código acoplado
Como a IA pode falhar, a estrutura do sistema precisa ser totalmente previsível.
Os dados manipulados são financeiros e agregados históricos. Por isso, a camada mais confiável do sistema precisa ser o banco.
Prisma
- tipagem forte nas queries
- migrations versionadas
- menor risco ao evoluir o schema
PostgreSQL
- precisão decimal confiável
- integridade relacional
- bom suporte a agregações mensais e relatórios
A LLM interpreta o documento — o backend valida e calcula.
Faturas não possuem padrão fixo entre concessionárias. Um OCR tradicional exigiria manutenção por layout.
O Gemini foi usado como leitor semântico, capaz de entender tabelas e contexto tarifário independentemente do formato.
Para garantir confiabilidade:
nenhuma resposta da IA é salva sem validação de schema
O sistema assume que a IA pode errar.
A IA não é tratada como fonte de verdade.
Fluxo:
- LLM extrai dados
- resposta é validada
- domínio recalcula valores
- só então persiste
Assim o resultado final permanece determinístico.
Permite subir o projeto completo com um comando e evita diferenças entre ambientes locais.
Chamadas para LLM podem ser lentas ou falhar.
O deploy considera:
- containers stateless
- reinício automático em falhas externas
- escalabilidade horizontal
k3s foi suficiente para um cenário leve sem complexidade operacional.
Crie um arquivo .env:
NODE_ENV="development"
PORT=8000
APP_NAME="lumi"
APP_BASE_URL="http://localhost:8000"
# Database
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5460
DATABASE_USER=lumi
DATABASE_PASS=lumi
DATABASE_NAME=lumi
DATABASE_URL="postgresql://lumi:lumi@localhost:5460/lumi?schema=public"
LLM_API_KEY="<your_gemini_api_key>"
LLM_MODEL="<gemini_model>" #Ex: gemini-2.5-flash
docker compose up -d
pnpm install
pnpm prisma migrate dev
pnpm start:dev
Swagger: https://api.lumi.ilannildo.com.br/docs
- Usuário envia PDF
- LLM interpreta documento multimodal
- Resposta é validada por schema
- Dados estruturados são persistidos
- Sistema disponibiliza relatórios e dashboards
Deploy preparado para Kubernetes (k3s)
Características:
- containers stateless
- banco externo
- variáveis via secrets
- escalável horizontalmente
O sistema foi projetado priorizando:
- separação por camadas (use cases + repositories)
- previsibilidade de domínio
- tolerância a erros de IA
- independência de provider de LLM
- testes unitários e e2e