Por que a IA do meu app de finanças não faz nenhuma conta
Estou construindo a Melvi, um app de controle financeiro que puxa contas e cartões pelo Open Finance e mostra o que ainda vai cair nos próximos meses.
Logo no começo eu fechei uma regra: todo número que aparece na tela sai do código, e a IA só explica. Queria contar o porquê e como ficou na prática, porque acho que muita gente que coloca LLM em produto passa pela mesma dúvida.
IA erra conta e não avisa
Pede pra um modelo somar vinte lançamentos e ele acerta quase sempre. O problema é esse "quase". Em app de finanças, um total errado em R$ 37 já basta pra pessoa desconfiar de tudo na primeira vez que bate com o extrato. E o modelo erra com a mesma confiança de quando acerta.
Então separei as coisas. A conta fica em funções puras, sem banco, sem rede e sem modelo: entram os lançamentos, sai o resultado, e os mesmos dados dão sempre o mesmo número. O modelo só entra depois, recebendo o resultado pronto e o mínimo de contexto que a pergunta pede. A resposta dele vem num formato estruturado e passa por um schema. Se vier quebrada, o app mostra uma resposta fixa e segue a vida, sem ficar tentando de novo.
Dinheiro em centavos, como inteiro
Todo valor fica em centavos, como inteiro. No TypeScript eu uso bigint:
0.1 + 0.2; // 0.30000000000000004
10n + 20n; // 30n
Com bigint, se alguém tentar somar centavos com um number comum o compilador reclama, e divisão nunca vira fração. Onde mais pega é na divisão: R$ 100,00 em três parcelas não dá três de R$ 33,33, porque some um centavo. A função de dividir joga o centavo que sobra nas primeiras parcelas:
export function split(amount: Money, parts: number): Money[] {
const count = BigInt(parts);
const base = amount.cents / count;
const leftover = amount.cents % count;
return Array.from({ length: parts }, (_, index) =>
money(BigInt(index) < leftover ? base + 1n : base, amount.currency),
);
}
// R$ 100,00 em 3 → 33,34 + 33,33 + 33,33
A soma das parcelas sempre fecha com o total, e tem teste garantindo isso.
O mês é o mês em que o dinheiro sai
Quando alguém pergunta "quanto sobra esse mês", o que importa é quando o dinheiro sai da conta, e não quando a compra foi feita. Compra no cartão cai no mês da fatura. Compra parcelada entra parcela por parcela, cada uma no seu mês, sem somar o total de novo. Pagar a fatura não conta de novo o que já estava nela. E transferência entre as suas próprias contas não é nem renda nem gasto.
É aqui que muita planilha se perde, e é o tipo de regra que um modelo aplica de um jeito numa resposta e de outro na seguinte. No código ela mora num lugar só e tem teste.
E a IA faz o quê, então?
Explica o número, responde coisas tipo "por que sobrou menos que no mês passado?" e sugere o que fazer em seguida. Quando a resposta tem número, ela mostra o período, de onde vieram os dados e como o valor foi montado, pra pessoa conseguir conferir. E as ferramentas que o modelo usa só leem ou sugerem: pra mudar qualquer coisa, a pessoa tem que confirmar.
Só leitura
Por último, nenhum código do app mexe em dinheiro. O Open Finance é usado só pra ler, e quem autoriza e encerra a conexão é a própria pessoa, no app do banco dela.
Deixei a regra completa do cálculo publicada no site, com os termos e os casos chatos. Se você trabalha com finanças pessoais ou usa LLM em produto, conta aí nos comentários como resolveu isso.