
Sistema de análise de dados com IA
| Área | IA sobre os dados |
|---|---|
| O que faz | Antes, relatório entrava na fila da TI. Agora o gestor pergunta em português e recebe o número. |
| Funções | Pergunta em português · Acesso por permissão · Indicador padronizado |
| Habilidades | Análise de dados · Padronização de indicadores · Design de telas · Controle de acesso |
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.



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.
- PerguntaTexto do executivo somado à pilha de filtros herdada do turno anterior, região, janela, moeda, unidade de negócio.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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ê.
| Camada | Escolha | Por quê |
|---|---|---|
| Dicionário semântico | YAML versionado em Git com compilador próprio | Mé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ção | LLM com saída estruturada em JSON Schema | O modelo preenche campos de um plano, não redige SQL. Resposta fora do schema morre antes de custar uma consulta ao banco. |
| Validação | sqlglot sobre a AST da consulta compilada | O 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ção | Réplica read-only, RLS por role, statement_timeout e fila para consulta longa | O 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álise | DuckDB e Python sobre o result set | Decomposição de variância é aritmética, não linguagem. Roda em milissegundos e devolve o mesmo número toda vez. |
| Observabilidade | OpenTelemetry com trace por resposta e custo de token por sessão | Toda 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.

