Desenvolvido para empresas

Sistema de análise de dados com IA

ÁreaIA sobre os dados
O que fazAntes, relatório entrava na fila da TI. Agora o gestor pergunta em português e recebe o número.
FunçõesPergunta em português · Acesso por permissão · Indicador padronizado
HabilidadesAnálise de dados · Padronização de indicadores · Design de telas · Controle de acesso
Como foi construídoLevantei como as áreas pediam relatório e quem define cada indicador. Desenhei a tela de perguntas e o dicionário de indicadores, montei 120 perguntas de teste com resposta esperada, construí o sistema e implantei com permissão por usuário.

O que o sistema cobre.

Sistema para diretoria e gestores perguntarem em português e receberem respostas com os dados da empresa, sem depender de relatório ou painel de BI. A IA entende a pergunta; o sistema busca o indicador no dicionário da empresa, executa a consulta com a permissão de quem perguntou, calcula, explica o porquê da variação e guarda cada resposta para auditoria.

Para quem

Diretoria e gestores de empresas de porte médio que pedem número ao analista e esperam dias pela resposta.

O que mudou na empresa

O gestor deixou de pedir número ao analista: pergunta e recebe a resposta com a origem anexa. Cada indicador tem definição única, cada gestor vê só o que pode, e toda resposta fica registrada.

Módulos e funções.

8 partes do sistema, cada uma com o que faz.

Pergunta em português

O gestor escreve como fala; a IA entende a pergunta e encontra o indicador certo.

Dicionário de indicadores

Cada indicador com fórmula única, sinônimos e dado sensível marcado; toda mudança fica registrada.

Acesso por permissão

A consulta roda com a permissão do gestor; se pesada, entra na fila e avisa depois.

Perguntas encadeadas

O gestor pergunta o porquê e o sistema mantém região e período; os filtros ficam visíveis.

Análise da variação

Mostra quais clientes puxaram o número e separa efeito de mix de efeito de taxa.

Resposta verificada

Confere cada número com o resultado, anexa a consulta e avisa quando o dado não existe.

Plano de ação

Gera plano de ação exportável, com cada item ligado à consulta que o originou.

Trilha de auditoria

Cada resposta guarda quem perguntou, a consulta, a versão do dicionário, o tempo e o custo.

Três telas.

O design é meu. Cada legenda diz o que a tela faz.

Resposta à pergunta do gestor, com os filtros aplicados
Tela 1Resposta à pergunta do gestor, com os filtros aplicados
Por que a margem caiu: quanto foi mix e quanto foi preço
Tela 2Por que a margem caiu: quanto foi mix e quanto foi preço
Dicionário de indicadores, com o dado sensível marcado
Tela 3Dicionário de indicadores, com o dado sensível marcado

Como funciona por dentro.

Um analista que responde à pergunta, anexa a consulta que usou e aguenta o follow-up, sem que ninguém precise abrir um dashboard.

  1. PerguntaTexto do executivo somado à pilha de filtros herdada do turno anterior, região, janela, moeda, unidade de negócio.
  2. Recuperação semânticaBusca no dicionário as métricas, dimensões e joins canônicos relevantes. Só esse recorte entra no contexto do modelo.
  3. Plano tipadoO modelo preenche uma IR em JSON Schema: métrica, grão, filtros, janela, comparação. Saída fora do schema é rejeitada ali mesmo.
  4. Compilação e validaçãoO compilador monta o SQL a partir da IR. A AST confere whitelist de tabelas, ausência de DML e presença de LIMIT. Aprovada, a consulta ainda passa por um EXPLAIN na réplica, cuja estimativa de linhas decide entre executar agora ou mandar para a fila.
  5. Execução governadaRéplica read-only com a role do usuário e RLS ativa, timeout no banco e cache particionado por permissão: SQL canônico mais role/policy set mais watermark da carga.
  6. Rotina analíticaDecomposição de variância, ranking de contribuição por cliente e comparação de período rodam em DuckDB sobre o result set.
  7. Narrativa verificadaO modelo escreve o texto. O verificador confere cada número contra o conjunto permitido, células do result set e saídas da rotina analítica, com tolerância de arredondamento e unidade declarada.
  8. Trace e próxima perguntaSQL, tempo, custo, modelo e versão do dicionário vão para o log. A tela sugere os follow-ups já com os filtros herdados.

O problema e a saída.

O problema

Todo comitê tem BI e ninguém abre: o painel diz o que aconteceu e emudece no porquê. Plugar um LLM no banco parece a saída, mas um join um-para-muitos duplica receita sem avisar e o modelo enxerga linha que o usuário não pode ver.

A saída

O LLM só toca nas pontas: interpreta a pergunta e narra o resultado. O meio é determinístico, retrieval no dicionário em YAML versionado, plano em JSON Schema, SQL compilado, execução com a RLS do usuário e trace por resposta para reproduzir tudo depois.

Arquitetura.

Como as partes se encaixam.

O sistema tem três camadas e o LLM só toca nas pontas. Na entrada, ele interpreta a pergunta. Na saída, ele narra o resultado. O meio, escolher métrica, montar consulta, executar, calcular, é determinístico. Essa fronteira é a decisão estruturante: tudo que precisa ser reprodutível ficou fora do modelo.

No centro está um dicionário semântico versionado em Git: cada métrica com fórmula, grão, dimensões permitidas, joins canônicos, sinônimos e marcação de coluna sensível. A pergunta passa por um retrieval sobre esse dicionário, embeddings de tabelas, colunas e valores de baixa cardinalidade, para que Sul case com a dimensão de região sem que o schema inteiro entre no contexto. Só o subconjunto relevante vai para o prompt; o bloco fixo de instruções fica em cache, o que segura o custo de token por turno.

Na execução, o limite mora no banco, não no prompt. Réplica read-only, role do usuário com RLS, statement_timeout e LIMIT injetado pelo compilador. Aprovada na validação estática, a consulta ainda passa por um EXPLAIN na réplica: se a estimativa de linhas do planejador estourar o orçamento, ela não é bloqueada, vira job em fila e volta por notificação. O cache de resultado é particionado por permissão: a chave é o hash do SQL canonicalizado mais o conjunto de roles e policies do usuário mais o watermark da última carga. Sem identidade na chave, cache e RLS se anulam, o mesmo SQL devolveria a um usuário as linhas materializadas com a permissão de outro. O porquê não é outra pergunta ao modelo: é uma rotina de decomposição de variância em DuckDB sobre o result set, separando efeito de mix e efeito de taxa. No fim, um verificador confere cada número do texto contra o conjunto de valores permitidos, células do result set mais as saídas da rotina analítica, com tolerância de arredondamento e unidade declarada. Número fora desse conjunto trava a resposta antes de ela chegar à tela.

Diário de construção.

Por onde comecei, onde travou e o que mudou no caminho.

A primeira coisa construída não foi o prompt: foram 120 perguntas de teste escritas à mão sobre um modelo de dados fictício de varejo, cada uma com o SQL gold correspondente, e uma suíte que compara result sets, não strings. Sem régua, mexer em prompt vira troca de opinião. Depois veio o dicionário semântico, tabela por tabela. Ele existe justamente para obrigar que a definição de receita líquida seja decidida por quem é dono da métrica; no protótipo, essa decisão foi modelada explicitamente em YAML, fórmula, grão, exclusões, sinônimos. O prompt foi a última peça a nascer.

O protótipo inicial fazia o óbvio: mandava o schema e pedia SQL. Funcionava na demonstração e falhava fora do roteiro dela. Fan-out em join um-para-muitos inflava receita sem erro visível, e a mesma pergunta reformulada produzia SQL diferente com número diferente. Trocar SQL livre por IR tipada foi a virada do projeto. A partir dali, join errado deixou de ser problema de prompt e virou bug de compilador, com teste de regressão, correção e diff.

O segundo ponto difícil foi o multi-turno. O porquê precisa herdar região e trimestre da pergunta anterior sem arrastar o resto do contexto junto. O estado virou uma pilha de filtros explícita, renderizada na tela, que o usuário pode soltar item a item. Segurança e auditoria entraram antes de qualquer apresentação, porque retrofitar RLS depois é reescrever a camada de execução, e a chave de cache só ganhou a role do usuário quando um teste com dois perfis fictícios de escopos diferentes recebeu o mesmo número: bug de cache, não de RLS. O plano de ação ficou por último; é o único lugar onde o modelo escreve texto longo, e mesmo lá cada item carrega a consulta que o sustenta.

Tecnologias e o porquê.

CamadaEscolhaPor quê
Dicionário semânticoYAML versionado em Git com compilador próprioMétrica precisa de definição única e diff revisável em pull request. Receita líquida para de ter três versões dependendo de quem pergunta.
GeraçãoLLM com saída estruturada em JSON SchemaO modelo preenche campos de um plano, não redige SQL. Resposta fora do schema morre antes de custar uma consulta ao banco.
Validaçãosqlglot sobre a AST da consulta compiladaO compilador é código meu e pode ter bug: a checagem na AST é a segunda barreira contra a minha própria falha. E é a barreira principal no modo de SQL livre em sandbox, onde a consulta chega sem ter passado pelo compilador. Regex sobre string não serve para nenhum dos dois casos.
ExecuçãoRéplica read-only, RLS por role, statement_timeout e fila para consulta longaO limite tem que morar no banco. Se toda a camada de IA falhar, a permissão do usuário continua valendo, inclusive no cache, que é chaveado por role.
AnáliseDuckDB e Python sobre o result setDecomposição de variância é aritmética, não linguagem. Roda em milissegundos e devolve o mesmo número toda vez.
ObservabilidadeOpenTelemetry com trace por resposta e custo de token por sessãoToda resposta precisa ser reproduzível seis meses depois: SQL, versão do dicionário, modelo, latência e gasto.

Decisões de projeto.

IR tipada, SQL livre só em sandbox

O modelo preenche um plano em JSON; o compilador gera o SQL e a AST confere whitelist e LIMIT. Perde a cauda longa, que sobra num sandbox sem cache, marcada como não verificada.

Cache por permissão e watermark, não TTL

Dois perfis com escopos diferentes viram o mesmo número: bug de cache, não de RLS. A chave virou SQL canônico + roles + watermark do ETL. Custa acerto, garante mesmo escopo, mesmo número.

O modelo narra, a máquina calcula

Toda aritmética sai de SQL ou DuckDB e o verificador barra número fora do result set; não sei é resposta válida. Fecha a porta para análise espontânea. Nenhum número do texto foi inventado.

Escopo.

O que o sistema cobre

  • Resposta em português com o SQL, o grão e a contagem de linhas anexados, dá para conferir sem pedir para ninguém.
  • Encadeamento de perguntas com pilha de filtros visível: o porquê herda o recorte da pergunta anterior e o usuário vê o que foi herdado.
  • Decomposição de contribuição: quem puxou o número para baixo, separando efeito de mix de efeito de taxa.
  • Plano de ação exportável, com cada item amarrado à consulta que o originou.
  • Trilha de auditoria por resposta: trace, versão do dicionário, modelo, latência, custo e autor da pergunta.
  • Recusa explícita quando o dado não existe ou a métrica não está definida, não sei é resposta válida, número inventado não é.

O que não está publicado

  • Nome da empresa e números de operação não são divulgados aqui.
  • O código não é público. O que dá para ver: o processo, as telas e as decisões.

Da mesma faixa.

IA sobre os dados

Quer ver este sistema de perto?

Mostro o processo que mudou, os módulos, as telas e como foi construído.

Contato

Quer ver isso de perto?

Diegorafacarvalho@gmail.com +55 47 98801-8335

Santa Catarina, Brasil, remoto. Costumo responder no mesmo dia.

Sem formulário

  • Recrutador não preenche formulário, copia o e-mail. Ele está aí em cima.
  • A versão rápida é uma página só, imprime em A4 e serve para encaminhar ao tech lead.
  • Qualquer sistema daqui eu mostro em chamada: o processo que mudou, os módulos, as telas e como foi construído.
  • Os sistemas foram desenvolvidos para empresas e o código não é público. Este site também é meu, do motor de scroll ao design: veja como funciona.