Skip to content

JoaoIto/BillLens

Repository files navigation

BillLens API - Leitor de Faturas com IA

Este projeto é uma API RESTful desenvolvida em Node.js com NestJS para processar faturas de energia elétrica em PDF (padrão Cemig). O grande diferencial desta aplicação é a utilização de modelos avançados de IA (Large Language Models - LLMs) com suporte multimodal para extrair dados estruturados diretamente da imagem do documento, dispensando o uso de ferramentas clássicas de OCR (Optical Character Recognition) que costumam falhar diante de variações de layout.

z{69A0E773-4864-411E-963C-F84CF5FBBFC4}

🚀 Ambiente de Produção (Vercel)

A API já está hospedada na nuvem utilizando Serverless Functions e um banco online (Neon/PostgreSQL). Acesse a documentação interativa (Swagger UI) e teste as faturas ao vivo: 👉 Teste a API Online Aqui (Swagger): https://billlens-coral.vercel.app/api/docs

  • Além disso, foi construído um painel de teste para vizualização frontend das informações e upload das faturas, a partir de 👉 BillLens-Front
{22CA7A66-FE76-4A27-B6A7-6636CFC64739}

Sumário

Como Iniciar o Projeto (Quick Start)

Opção 1: Via Docker Embedado (Recomendação DevOps)

A forma mais espetacular de levantar a base inteira em Segundos:

  1. Instale o Docker Desktop.
  2. Na raiz onde fica o docker-compose.yml, rode o comando aglutinador com sua Key:
GEMINI_API_KEY=sua_API_key docker-compose up --build -d

O Docker fará o download do Node.js, empacotará a API (Dockerfile), baixará o PostgreSQL nativo livre, isolará as redes, aplicará os Migrations sozinhos e soltará o back-end em http://localhost:3000.

Opção 2: Start Manual (Hard-Way)

1. Pré-requisitos

  • Node.js (v18+)
  • PostgreSQL (pode rodar via Docker docker run --name billlens-db -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=billlens_db -p 5432:5432 -d postgres)
  • Chave de API da Google Gen AI (Gemini)

2. Passo a Passo

# Clone o repositório
git clone https://github.com/JoaoIto/BillLens.git

# Entre na pasta do projeto
cd billlens-api

# Instale as dependências
npm install

# Crie e configure o arquivo .env
cp .env.example .env

# Rode as migrations do banco de dados relacional
npx prisma migrate dev

# Inicie o servidor
npm run start:dev

3. Testes

A aplicação usa o Jest. Pode validar tudo com:

npm run test

Rotas da API (Endpoints)

A aplicação expõe as seguintes rotas principais para interação e consumo dos dados:

  • POST /faturas/upload: Recebe um arquivo .pdf (fatura real da CEMIG) via form-data (file), executa o serviço de extração de dados através da API LLM, processa todas as regras de negócio para encontrar a economia de energia gerada e consumo total, e persiste o registro no banco de dados.
  • GET /faturas: Retorna uma biblioteca com todas as faturas já salvas. É possível iterar e navegar nas faturas inserindo filtros na query string do navegador ou API: ?clientNumber=123 e/ou ?referenceMonth=JAN/2024.
  • GET /faturas/dashboard: Rota focada em servir frontends de Inteligência de Negócio e desenhar gráficos. Ela não devolve JSONs extensos, ela retorna apenas as Somatórias Consolidadas (Data Aggregation via SUM no Prisma) de meses de consumo e injetadas de GD unificadas, separadas em métricas financeiras (financialMetrics) e consumo (energyMetrics). Para puxar os gráficos exclusivos de um cliente, use ?clientNumber=X.

O Desafio e o Fluxo de Dados

O objetivo central é:

  1. Upload: Receber um arquivo PDF da fatura via endpoint POST /faturas/upload.
  2. Processamento (LLM): Enviar o PDF para uma API de IA capaz de retornar os dados lidos em um formato JSON restrito e previsível (Structured Output).
  3. Regra de Negócio: Calcular novas variáveis a partir dos dados extraídos (ex.: consumo total, economia com energia injetada GD).
  4. Persistência e Consulta: Armazenar os resultados em um banco PostgreSQL usando Prisma e disponibilizá-los em endpoints de listagem e de agregações para o frontend (Dashboard).

Processo Técnico de Extração e Persistência (LLM)

Para que a leitura da fatura se transforme em dados estruturados no banco, a API orquestra o seguinte pipeline no momento em que a rota POST /faturas/upload é acionada:

  1. Recepção em Memória: O NodeJS intercepta o .pdf usando Multer e aloca o Buffer diretamente na memória (sem salvar arquivos temporários no disco).
  2. Conversão Base64: O conteúdo do PDF é convertido em uma string codificada em Base64.
  3. Engenharia de Prompt (LLM): O LlmService cria um payload passando o documento via inlineData junto com um Prompt rigoroso. Este prompt ensina a IA a se comportar como um auditor e a devolver os valores obrigatoriamente num Formato JSON Estrito predefinido. Há inclusive um sistema de fallback (cascata) que tenta diferentes versões de modelo (ex: gemini-1.5-flash, gemini-1.5-pro) caso haja falha ou recusa de API.
  4. Parsing e Sanitização: O texto retornado pela IA é limpo de artefatos (como marcações Markdown) e convertido via JSON.parse().
  5. Cálculos de Regra de Negócio: Na camada InvoicesService, a API pega os valores capturados da Cemig e efetua a lógica matemática do sistema:
    • totalConsumptionKwh: Soma Energia Elétrica + Energia SCEE.
    • totalValueWithoutGd: Remocão dos descontos da Geração Distribuída.
    • gdEconomyValue: Valor da Isenção/Economia na fatura injetada.
  6. Persistência (Prisma ORM): Após os cálculos numéricos forçados (para evitar erros de tipagem), os dados são finalmente gravados na tabela Invoice do PostgreSQL.

Exemplo do Objeto Salvo (JSON Response)

Depois que a fatura PDF sofre todo o pipeline acima (upload -> IA -> Parse -> Cálculos), o banco de dados armazena e retorna no GET /faturas o seguinte objeto documentado:

[
  {
    "id": "67dd773f-3ff2-4660-ad88-fc02e8cd06d0",
    "clientNumber": "7204076116",
    "referenceMonth": "JAN/2024",
    "electricalEnergyKwh": 50,
    "electricalEnergyValue": 47.75,
    "sceeEnergyKwh": 456,
    "sceeEnergyValue": 232.42,
    "compensatedEnergyKwh": 456,
    "compensatedEnergyValue": 222.22,
    "municipalLightingValue": 49.43,
    "totalConsumptionKwh": 506,
    "totalCompensatedKwh": 456,
    "totalValueWithoutGd": 329.6,
    "gdEconomyValue": 222.22,
    "createdAt": "2026-02-24T21:17:24.376Z"
  }
]

Stack Tecnológico Utilizado e Justificativas

A escolha da stack foi voltada para garantir um código limpo, tipado, testável e escalável, refletindo um ambiente de produção moderno.

  • Framework: NestJS (Node.js)
    • Por que? Ao contrário do Express (que é não-opinativo), o NestJS impõe uma arquitetura baseada em Clean Architecture e Angular. A separação nativa em Módulos, Controllers, Services e a Injeção de Dependência nativa facilitam imensamente a criação de testes unitários isolando dependências externas (mockando a API do LLM e o Banco de Dados).
  • Banco de Dados & ORM: PostgreSQL + Prisma
    • Por que? O PostgreSQL é o padrão de mercado para banco relacional. O Prisma ORM é adotado pela sua tipagem fenomenal (type-safety) que se integra perfeitamente ao TypeScript. Ele permite consultar agregações de forma performática para o dashboard sem escrever SQL cru.
  • Testes & CI/CD: Jest e GitHub Actions
    • Por que? A Suíte 100% Mockada com Jest está entrelaçada a um Worker contínuo do Github. Todos os Commits devem passar pelo gargalo virtual do Teste antes de virarem versão de produção.
  • Infra-as-Code & Nuvem: Docker Compose e Render (PaaS)
    • Por que? Empacotamento Multi-Stage gerando contêiners minúsculos (Alpine Node). Facilitam o Deploy Cloud de 1-Clique na provedora Render (render.yaml gerencia o Cloud PostgreSQL e a Web API automaticamente).
  • Integração IA: SDK do @google/genai para o Gemini

Estrutura da Aplicação

O ecossistema é dividido em módulos para isolamento de contexto dinâmico:

  • AppModule: Inicialização do roteamento.
  • LlmModule: Um wrapper de infraestrutura em torno da API de IA para isolar os SDKs terceiros e centralizar validação do Output da IA (com schema estrito via Zod/etc) e lógicas de "retry on failure".
  • InvoicesModule: Coração das regras de contabilidade e endpoints de upload e leitura.

Documentação Adicional (Docs)

Para guias extremamente aprofundados dos motores e regras de arquitetura desta API, acesse a pasta oficial de documentação /docs:

  • 🤖 Técnica de Engenharia de Prompt: Uma dissecação da estrutura psicológica do prompt escrito para forçar restrições (Output Constraint e Role Prompting) no Gemini, neutralizando alucinações de saída da IA.
  • 🧪 A Estratégia de Testes (Jest Isolado e Mocks LLM): Como cobrimos 100% da lógica matemática, regras de negócio e bloqueios da API (UnprocessableEntity e Conflict) sem gastar 1 único token do pacote pago da inteligência artificial através das funções Injetáveis do NestJS.
  • ⚙️ Automação de CI/CD (GitHub Actions): Explicação da pipeline que garante a integridade de commits com as matrizes LTS do Node.js.
  • 🧠 A Estratégia do LLM e Fallbacks: Como a Visão Computacional extrai os dados do PDF de fatura superando o OCR antigo, Engenharia de Prompt restrita e mecanismo de Cascata de Modelos Gemini.
  • 📊 O Motor do Dashboard de Faturas: Uma aula técnica demonstrando como a nossa API lida matematicamente com agregações sem travar a memória do Node.js, com trechos de código mostrando a delegação de somas (SUM()) ao PostgreSQL via Prisma, e explicação do escopo dos resultados financeiros.
  • 💎 Otimizações Extremas com Prisma ORM: Aprofundamento no combate a Memory Leaks com paralelismo I/O na Engine transacional do banco ($transaction), aniquilação de Full-Table Scans em listagens usando estrita de metadados exatos para indexação B-Tree (saltos assintóticos de $O(N)$ para $O(1)$) e implementações do Repository Pattern contra Hard-Coding na Controller.
  • Arquitetura de DB e Otimizações de Consultas: Um registro profundo de Engenharia de Software demonstrando as refatorações do back-end, destravando a V8 de arrays imensos.

About

Billlens, microssegiço para avaliação por meio de inteligência artificial, em Nestjs, de faturas de energia elétrica.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors