Saltar para o conteúdo
megapromotingVamos falar

Soluções · Serviços financeiros

Um agente que classifica movimentos de dinheiro escolhendo de uma lista fechada, e não escrevendo uma frase que depois alguém interpreta.

Numa organização financeira, um agente útil não dá conselhos e não aprova nada: lê documentos e transações, enquadra-os numa categoria de um conjunto fixo, diz quão seguro está e pode responder «não sei». O resto — a decisão, a aprovação, a política — fica com as pessoas.

Oferta, com condiçõesNu scriem „livrat”, pentru că nu avem un agent de acest fel pus în producție la un client din sectorul financiar. Ce avem, și arătăm exact ca atare, e o conductă proprie de ingestie care rulează pe datele noastre: cinci module Python, 1.526 de linii, care citesc notificări bancare din e-mail și extrase în PDF, clasifică fiecare tranzacție prin unelte și o scriu în PostgreSQL cu dedublare, plus patru fluxuri de automatizare pentru webhookuri de la trei procesatori de plăți. Starea reală, spusă în aceeași frază: depozitul nu e sub git, directoarele `tests/` și `webhook-server/` sunt goale, iar potrivirea aproximativă a numelor de contrapartidă folosește o euristică de n-grame marcată în cod ca „de înlocuit cu un serviciu de înglobare înainte de producție”. Partea de platformă financiară în producție — flux de cerere, contract, grafic de plăți, audit — e o lucrare separată, cu dovezile ei, și acolo scriem „livrat”.

Os pedidos de agentes AI em serviços financeiros vêm quase sempre na forma de «responder aos clientes a perguntas sobre os nossos produtos». É um pedido legítimo, mas não é aí que se ganha tempo. O tempo perde-se noutro lado: alguém abre diariamente dezenas de notificações bancárias e de extratos, olha para uma descrição do tipo uma cadeia de maiúsculas com um código e decide se é um recebimento de um cliente, um salário, um imposto, uma prestação a um credor ou uma despesa operacional. Esse trabalho é repetitivo, aborrecido e, precisamente por isso, cheio de erros.

Um modelo linguístico é bom nisso, com uma condição: não lhe ser pedido para escrever uma resposta em texto livre. Se lhe pedir uma frase, você vai fazer o parsing, e o parsing vai sair errado. No nosso pipeline, o modelo não escreve: recebe sete ferramentas e tem de chamar exatamente uma — recebimento de um cliente, salário, imposto, pagamento a um credor, despesa operacional, comissão bancária ou desconhecido. Cada ferramenta pede, além do nome da contraparte ou da categoria, um score de confiança entre 0 e 1. «Desconhecido» pede um motivo escrito. A saída é uma estrutura, não uma opinião.

A segunda regra é que nada entra duas vezes. Cada transação extraída de uma notificação ou de um extrato recebe um identificador externo calculado como um prefixo de 16 caracteres de uma impressão SHA-256 sobre os seus campos, a coluna é única na tabela, e a inserção faz-se com `ON CONFLICT (external_id) DO NOTHING`. A consequência prática: a caixa de correio pode ser lida quantas vezes quiser, e o saldo não duplica. Sem esta regra, qualquer pipeline de ingestão financeira acaba, na terceira semana, a produzir duplicados que alguém limpa manualmente.

O que um agente assim não faz, e por que é importante escrever isso na página: não aprova um pagamento, não toma uma decisão de crédito, não dá recomendações de investimento e não responde ao cliente em nome da instituição. O score de confiança que devolve é a avaliação do modelo sobre si próprio, não uma medição de exatidão feita por nós — essa distinção é a diferença entre uma ferramenta e uma ilusão de controlo.

Qué incluye

O que muda concretamente em serviços financeiros

O documento entra uma única vez, mesmo que o lemos dez vezes

As notificações são lidas da caixa de correio por IMAP, os extratos a partir de PDF. Cada transação recebe um identificador externo da fingerprint SHA-256 sobre os seus campos, a coluna `external_id` é `NOT NULL UNIQUE` na tabela, e a inserção é feita com `ON CONFLICT (external_id) DO NOTHING`, com registo separado para a linha inserida e para a ignorada como duplicado. A releitura da mesma caixa não produz nenhum duplicado.

A classificação é feita com ferramentas, com uma lista fechada de resultados

Sete ferramentas, não texto livre: recebimento de um cliente, salário, imposto, pagamento a um credor, despesa operacional, comissão bancária, desconhecido. O modelo tem de chamar apenas uma. As primeiras seis pedem obrigatoriamente, além do nome ou categoria, um score de confiança entre 0,0 e 1,0, declarado no esquema da ferramenta; a sétima pede um motivo. O modelo usado é declarado no código, não escondido na configuração.

«Desconhecido» é uma saída legítima, com motivo

Um classificador que não pode dizer «não sei» vai classificar mal, com alta confiança, precisamente as transações invulgares — ou seja, as que importam. Por isso a ferramenta de desconhecido está tão disponível como as outras e pede um motivo escrito, que vai para a linha. As linhas desconhecidas são a lista de trabalho do humano, não uma falha do sistema.

A correspondência aproximada de nomes de contrapartida, com o seu estado real

A mesma empresa aparece nos extratos com três grafias. Por cima da classificação existe uma correspondência por semelhança cosseno entre vetores. Dizemos exatamente o que são esses vetores hoje: uma heurística de n-gramas de caracteres, escrita no código com o comentário de que para produção deve ser substituída por uma chamada real a um serviço de embeddings. Funciona para variações de escrita; não é uma correspondência semântica.

Os webhooks dos processadores de pagamentos entram na mesma tabela

Quatro fluxos de automatização, um para cada um dos três processadores de pagamentos e um de reconciliação diária, com 7 a 10 nós cada. A ideia de arquitetura é que as fontes diferentes — e-mail, PDF, webhook — não produzem três tabelas que depois têm de ser conciliadas, mas sim linhas na mesma tabela, com a mesma regra de desduplicação.

O consumo do modelo fica abaixo do orçamento por chave, não por fatura

As chamadas passam por um gateway próprio em `api.megapromoting.com/v1`, com 44 modelos configurados, cada um com custo por token e limite de contexto. A chave de projeto tem lista branca de modelos, orçamento e período, pode ser rodada mantendo o histórico, e o consumo é consolidado diariamente por utilizador × chave × modelo. O detalhe que surpreende toda a gente: os modelos de raciocínio produzem passos internos que o sistema de seguimento não vê, mas o fornecedor fatura-os — portanto, o orçamento bruto por chave é definido abaixo do teto desejado.

O que se pode executar sem que os dados saiam da máquina

Para os passos que não exigem um modelo grande — a extração de campos de um formato conhecido, a correspondência de nomes, as verificações de coerência — não é preciso qualquer fornecedor externo; é código normal. O modelo é chamado apenas para a etapa de enquadramento. Quando a tua política proíbe a saída de dados, a questão é o que é enviado ao modelo, não se usa IA: pode enviar-se a descrição da transação sem os identificadores da conta.

O que um agente deste tipo não faz e não vai fazer

Não aprova um pagamento e não executa uma transferência. Não toma a decisão de concessão de crédito — as regras, os limiares e a aprovação são da política da instituição. Não dá recomendações de investimento e não responde ao cliente em teu nome sem um fluxo separado de aprovação. E não te garante a exatidão: o score de confiança é a saída do modelo sobre si próprio, não uma medição independente.

Traseul

Como um pedido passa pelo sistema.

01

Definimos a lista fechada de resultados, antes de qualquer código

A primeira entrega não é um agente, mas sim uma lista: as categorias em que pode enquadrar, que campos obrigatórios pede cada uma, e o que significa «desconhecido» no teu caso. Se a lista não se puder escrever numa página, a tarefa não é adequada para um agente — e é mais barato saber isso agora.

02

Construímos a ingestão e a desduplicação, sem modelo

A leitura de e-mail, PDF ou webhook, a extração de campos, o cálculo do identificador externo e a escrita na base são feitos e verificados sem qualquer chamada a um modelo. Entregamos um pipeline que ingere corretamente e não duplica. Se esta etapa não for sólida, um modelo por cima dela apenas produz erros mais convincentes.

03

Adicionamos o enquadramento e medimo-lo nos teus casos

Por cima do pipeline que funciona, colocamos as ferramentas de classificação e executamos num conjunto de transações reais tuas, com o resultado correto definido pela pessoa que hoje faz o trabalho. Entregamos a tabela com os acordos e desacordos, não uma afirmação sobre a exatidão. O limiar a partir do qual a linha vai para uma pessoa é escolhido a partir dessa tabela.

04

Colocamos o orçamento, o registo e os gates

Chave de projeto com lista branca de modelos e orçamento, consolidação diária do consumo, registo com a ferramenta chamada e a pontuação, e um gate que envia para uma pessoa tudo o que está abaixo do limiar ou é desconhecido. Entregamos os acessos, o documento de entrada em funcionamento e a lista escrita do que o agente faz sozinho e do que não faz.

1E-mail, PDF sauwebhook2extragerea câmpurilor3amprentă SHA-2564scriere cu ONCONFLICT DO NOTHING5încadrare prin unadin șapte unelte, cuscorrândurile„necunoscut” către om
Traseul, în 6 pași

Os dados

Qué tocamos, dónde están y cuánto se quedan

As regras diferem de setor para setor. Estas são as que se aplicam nos serviços financeiros.

Que tipo de dados toca, concretamente
Movimentos de dinheiro, com data, montante, moeda, descrição e contrapartida. Parte das contrapartidas são pessoas singulares — um salário leva o nome do empregado — por isso a tabela contém dados pessoais dos empregados, não apenas dados comerciais. Isso altera quem pode abrir a tabela.
O que chega ao modelo e o que fica em casa
No modelo, chega o texto da descrição da transação e o montante. Os identificadores de conta, os IBAN e os restantes campos não têm lugar no pedido para que o enquadramento funcione, por isso podem ser deixados de fora. A regra que aplicamos em geral: o que não é necessário para a etapa respetiva não é enviado, porque o que não sai não pode ser retido por ninguém.
Onde ficam os dados extraídos
PostgreSQL, com `external_id` único e índice sobre ele. A base continua a ser sua, na sua infraestrutura ou numa que nós operamos para si. Não existe um repositório comum entre clientes, porque não existe motivo técnico para que exista.
O rasto da decisão automática
Cada linha guarda qual ferramenta foi chamada, com que pontuação e, quando é o caso, o motivo de «desconhecido». É o mínimo necessário para que, daqui a seis meses, alguém possa responder à pergunta «por que é que esta transação foi colocada em despesas operacionais» — com uma resposta, não com um encolher de ombros.
O prazo de retenção, que aqui você não escolhe sozinho
Os documentos financeiros têm prazos de retenção estabelecidos pela legislação contabilística e fiscal, não pela nossa preferência ou pela sua. Num projeto financeiro, o prazo é retirado dessas regras, é escrito no registo de tratamentos e só depois se implementa a eliminação. A ordem inversa — implementar primeiro, verificar depois — produz sistemas que eliminam o que devia ser mantido.

Un caso

Um pipeline de ingestão que pode ser reiniciado sem medo

A situação

As notificações bancárias e os extratos mensais chegavam a uma caixa de correio e eram lidos por uma pessoa, que os classificava por categorias. A primeira versão evidente — um script que lê a caixa e escreve na base — tem um problema que só se vê na terceira semana: em qualquer reinício ou releitura, as mesmas transações entram de novo.

Qué construimos

Escrevi cinco módulos, 1.526 linhas de Python: dois analisadores de notificações via IMAP, um extrator de extratos PDF, o classificador por ferramentas e a escrita em PostgreSQL. A regra central é o identificador externo — um prefixo de 16 caracteres de uma impressão SHA-256 sobre os campos da transação — com a coluna única na tabela e inserção `ON CONFLICT DO NOTHING`. A classificação não devolve texto: o modelo chama uma das sete ferramentas, com pontuação de confiança obrigatória, e «desconhecido» exige motivo.

Qué salió

A caixa de correio pode ser relida a qualquer momento, e as linhas já processadas são ignoradas e assinaladas como duplicado no registo. As transações que o modelo não consegue enquadrar surgem como lista de trabalho, com o motivo ao lado, em vez de serem empurradas para uma categoria para parecer que tudo correu bem.

Qué no dice el caso

É um pipeline interno, não um sistema entregue a um cliente financeiro: não está sob git, os diretórios de teste estão vazios, e o correspondência aproximada de nomes usa uma heurística de n-gramas que o código marca explicitamente como provisória. Descrevi-o aqui porque mostra o método, não porque seja um produto.

Perguntas

O que alguém dos serviços financeiros pergunta

O agente aprova pagamentos ou créditos?

Não, e isso não é uma limitação técnica que iremos ultrapassar na próxima versão. A aprovação é uma decisão com consequências jurídicas, que pertence a uma pessoa autorizada da instituição. O agente prepara: enquadra, preenche, assinala o que não corresponde. Um sistema que aprova sozinho teria de poder responder perante um controlador, e uma pontuação de confiança não é uma resposta.

Como sei que enquadrou corretamente?

Não pela pontuação de confiança — essa é a avaliação que o modelo faz de si próprio, não uma medição. Sabe-se pela comparação com as decisões da pessoa que faz o trabalho hoje, num conjunto de transações reais, feita antes de pôr algo em regime automático. O resultado dessa comparação é uma tabela que entregamos, incluindo as linhas em que o agente errou.

O que acontece quando não tem a certeza?

Chame a ferramenta de «desconhecido» e escreva o motivo. A linha vai para a lista de trabalho do operador, não para uma categoria escolhida ao acaso só para parecer que o sistema funcionou. Um classificador sem saída de «não sei» erra exatamente onde o erro custa: nas transações invulgares.

Se lermos duas vezes a mesma notificação, o montante duplica-se?

Não. Cada transação tem um identificador externo calculado como fingerprint sobre os seus campos, a coluna é única, e a inserção usa `ON CONFLICT (external_id) DO NOTHING`. A linha ignorada é registada no log como duplicada, portanto vê-se que foi relida.

Os nossos dados vão para um fornecedor de modelo?

Para a etapa de enquadramento, sim: a descrição da transação e o montante vão para o modelo escolhido, através do nosso gateway, com chave de projeto, lista branca de modelos e orçamento. Os restantes passos — leitura, extração, deduplicação, correspondência de nomes — são código comum e não saem para lado nenhum. O que pode sair é definido por escrito antes, não se descobre pelos logs depois.

Podem ler extratos em PDF, não apenas notificações por e-mail?

Sim, é um dos módulos da pipeline. O que importa saber é que um extrato em PDF é um formato frágil: lê-se de acordo com a estrutura que o respetivo banco produz, e quando o banco altera o modelo, o módulo tem de ser ajustado. Por isso, escreve-se com verificações que falham de forma ruidosa, não que adivinham.

Porque está escrito nesta página «oferta» e não «entregue»?

Porque a nossa regra exige pelo menos duas implementações próprias para escrever «entregue», e a pipeline descrita aqui corre com os nossos dados, não em produção אצל um cliente do setor financeiro. Também tem lacunas que nomeamos: não está em git, não tem testes, e a correspondência de nomes usa uma heurística marcada no código como provisória. Quando pudermos citar duas implementações em clientes, mudamos a palavra.

O que precisamos da nossa parte para começar o trabalho?

Três coisas: a lista fechada das categorias em que pode classificar, um conjunto de transações reais com a resposta correta dada pela pessoa que faz hoje o trabalho, e a decisão escrita sobre que campos podem sair da vossa rede. Sem o terceiro ponto não começamos, porque é o único que não se pode corrigir depois.

O que gostaria que funcionasse melhor?

Conte-nos o seu processo. Em conjunto decidimos o que vale a pena construir, o que podemos ligar e como verificamos o resultado.

Vamos falar