Autores:  Arissa Yoshida, Daniel Braithwaite, Marcelo Buga, Taylor Foust

No Nubank, pesquisamos modelos de representação de transações baseados em transformers que podem ser adaptados a um conjunto crescente de aplicações downstream. Nos últimos anos, esse trabalho evoluiu de dar suporte a apenas algumas tarefas internas para alimentar um conjunto muito mais amplo, com mais de 20 benchmarks diferentes. Esse crescimento trouxe um novo desafio: como garantir que mudanças em dados, arquitetura e treinamento melhorassem os modelos de forma consistente como um todo, em vez de apenas elevar o desempenho em tarefas isoladas?

Para responder a essa pergunta, construímos um framework de benchmarking focado em pesquisa horizontal de modelos e dados. Nosso objetivo era transformar um processo de experimentação manual e operacionalmente pesado em um fluxo automatizado, reprodutível e estatisticamente rigoroso. Esse framework nos permite testar mudanças horizontalmente em múltiplas tarefas downstream e em múltiplas repetições simultaneamente. Em vez de avaliar ideias benchmark a benchmark, agora conseguimos identificar quais melhorias realmente generalizam entre aplicações e quais funcionam apenas em cenários específicos. O resultado foi uma redução drástica do overhead operacional da experimentação. Com o framework, nosso time passou a rodar cerca de cinco vezes mais experimentos por mês, dedicando mais tempo à pesquisa em si e menos tempo à operação de pipelines.

O ponto de partida: buscar melhorias horizontais

Nosso time estabeleceu um objetivo claro: gerar melhorias médias relevantes em um benchmark que representa múltiplas tarefas internas. Isso significou abandonar otimizações excessivamente especializadas voltadas a uma única aplicação. Toda nova direção de pesquisa (seja uma fonte de dados adicional, uma mudança arquitetural ou uma nova formulação de treinamento) precisava demonstrar ganhos em múltiplas tarefas ao mesmo tempo.

Organizamos esse trabalho em duas grandes frentes:

  • Escala de dados: incorporação de novas fontes de dados transacionais;
  • Mudanças arquiteturais: indo de paradigmas de modelo inteiramente novos a ajustes menores, como funções de ativação, batch normalization, learning rates desacoplados, maior comprimento de contexto e arquiteturas alternativas de blending.

No entanto, cada nova hipótese exigia dezenas ou até centenas de execuções de treinamento e avaliação distribuídas em múltiplos benchmarks. Com um escopo de pesquisa ambicioso e um orçamento de computação limitado, ficou claro que o gargalo não era mais apenas a modelagem, e sim o próprio processo de experimentação.

Check our job opportunies

O problema: experimentação manual não escala

Antes do framework de benchmarking, rodar um único experimento era um processo manual que podia levar vários dias. Os pesquisadores precisavam:

  1. Configurar e executar a preparação dos dados;
  2. Pegar a saída, configurar o pré-treinamento, submeter o job, monitorá-lo e acompanhar os resultados;
  3. Repetir o processo para o fine-tuning; 
  4. Rodar inferência no dataset de teste;
  5. Consolidar manualmente os resultados para comparação com o baseline.

Na prática, a maior parte do tempo era consumida por tarefas operacionais: configurar jobs, copiar parâmetros entre etapas, acompanhar saídas e lidar manualmente com falhas. Até mesmo repetir um experimento exigia praticamente o mesmo esforço de executá-lo pela primeira vez.

O próprio acompanhamento se tornou outra fonte de atrito. Os experimentos eram documentados em planilhas gigantescas com milhares de células, nas quais pequenos erros podiam comprometer grandes partes dos resultados. Sob pressão de tempo, os pesquisadores monitoravam jobs com frequência e intervinham manualmente quando ocorriam falhas. Além disso, o risco de diferenças sutis em configurações ou mudanças de código entre execuções introduzia potenciais fatores de confusão, exigindo uma organização cuidadosa dos experimentos.

A solução: um framework de benchmarking

O trabalho manual descrito acima também escala mal à medida que o número de aplicações downstream cresce. Por exemplo, cada experimento frequentemente exige múltiplas repetições para estabelecer confiança estatística e precisa ser avaliado em todo o conjunto de benchmarks downstream, não apenas em uma única tarefa. Sem automação, isso significava multiplicar cada passo manual pelo número de repetições e pelo número de benchmarks. Por isso, projetamos um framework de benchmarking para automatizar o processo de experimentação. Especificamente, definimos quatro objetivos principais:

  • Reduzir a quase zero o custo operacional de repetições;
  • Minimizar o esforço necessário para orquestrar novos experimentos;
  • Reduzir erros de acompanhamento;
  • Permitir que os pesquisadores foquem em ideias, e não em processo.

E o framework foi construído sobre dois pilares principais:

1. A capacidade de representar todo o pipeline de modelagem em código, da preparação de dados ao treinamento, inferência e avaliação (como uma branch do codebase);

2. Branch deployments, que criam ambientes isolados de experimentação.

Como o framework funciona

O fluxo de trabalho mudou drasticamente. Hoje, o processo do pesquisador é essencialmente:

  1. Formular uma hipótese;
  2. Implementar uma mudança de código;
  3. Criar um deployment a partir da branch do git;
  4. Rodar o pipeline.

Todo o resto acontece automaticamente. O sistema:

  • Coleta todos os dados necessários;
  • Gera os datasets de treino, validação e teste;
  • Executa o pré-treinamento;
  • Roda múltiplas repetições de fine-tuning;
  • Executa a inferência;
  • Avalia as métricas;
  • Registra automaticamente resultados e parâmetros em um leaderboard centralizado.

Uma vez implementada a mudança, os jobs rodam de ponta a ponta, e cada etapa começa automaticamente assim que suas dependências são concluídas. Além disso, como cada experimento está vinculado a uma tag específica do git, reproduzir ou estender experimentos anteriores ficou significativamente mais simples: os pesquisadores podem recuperar a tag, criar uma nova branch e iterar a partir dali.

Rigor estatístico: detectando melhorias promissoras

Uma das decisões de design mais importantes por trás do framework foi integrar a triagem de significância estatística diretamente ao sistema. Na pesquisa em machine learning, um dos erros mais comuns é confiar em resultados eventuais que parecem promissores puramente por sorte estatística e, então, construir direções inteiras de pesquisa sobre eles. A triagem existe para nos dizer quais direções valem esse investimento, não para certificar um resultado isolado como uma conclusão definitiva.

Antes de implementar o framework, conduzimos um estudo dedicado para medir a variância do joint fusion [1] em execuções repetidas. Usando 10 execuções idênticas do baseline, observamos que a variância do AUC de teste era relativamente baixa, com desvio padrão próximo de 0,02.

A partir disso, realizamos simulações para definir um protocolo estatístico confiável. Descobrimos que usar:

  • N = 5 execuções de baseline;
  • M = 2 execuções do challenger;
  • Teste t de Welch;

nos permitia detectar de forma confiável melhorias próximas de 0,08 pp em AUC, com 95% de poder estatístico e nível de significância de 0,05. Ganhos menores, próximos de 0,04 pp, são captados em apenas cerca de metade das vezes, o que é suficiente para marcar uma direção como promissora e digna de mais execuções, mas não para tratar uma única comparação como conclusiva.

É importante notar que o protocolo 5 e 2 é um mínimo. Um resultado limítrofe, próximo de 0,04 pp, pode ser confirmado com mais execuções. A maior parte do erro padrão vem do braço challenger de duas execuções, então são essas as execuções a acrescentar: passar de 2 para 5 move o efeito detectável de forma confiável de cerca de 0,08 pp para cerca de 0,055 pp, e 10 execuções de challenger chegam a cerca de 0,045 pp. A ferramenta de reporte reexecuta o teste automaticamente com o novo número de execuções. A maioria dos experimentos permanece na triagem barata, e apenas as direções que valem confirmação recebem os números maiores.

Essa metodologia foi incorporada diretamente ao framework. Hoje, a ferramenta de reporte executa automaticamente testes estatísticos entre as múltiplas repetições de cada experimento, entregando resultados estatisticamente validados por padrão. Abaixo, uma interface típica exibindo esses resultados de testes de significância em um conjunto de tarefas downstream.

Configuração do benchmark

A avaliação do benchmark segue um processo estruturado, baseado em:

  • Baselines padronizados com cinco execuções;
  • Benchmarks multitarefa compartilhados;
  • Avaliação consistente entre múltiplas repetições.

O framework também foi projetado para crescer continuamente. Adicionar novas tarefas de benchmark não exige nada além de abrir um pull request.

Resultados: avaliando variantes de experimentos

Com o framework de benchmarking, passamos a explorar sistematicamente melhorias tanto arquiteturais quanto de dados em relação ao nosso baseline original: um transformer decoder-only em nível de token que usa fine-tuning com LoRA e um módulo de blending DCNv2.

No lado arquitetural, avaliamos mudanças em challengers como:

  • Maior comprimento de contexto;
  • Otimizações de treinamento;
  • Novas arquiteturas construídas do zero.

No lado dos dados, testamos quatro novas fontes de dados transacionais, tanto individualmente quanto em combinação.

Os resultados mostraram que algumas mudanças melhoravam apenas benchmarks específicos, enquanto outras traziam pouco ganho em escalas menores, mas se tornavam altamente relevantes em experimentos maiores. Sem um framework estruturado, comparar todas essas direções simultaneamente seria inviável. Como parte da fase inicial de pesquisa do nuFormer, combinamos as mudanças arquiteturais mais promissoras com fontes de dados adicionais e produzimos um baseline significativamente melhor, com ganhos estatisticamente validados em múltiplos benchmarks internos.

Impacto

O framework trouxe melhorias mensuráveis em várias dimensões:

  • Velocidade de experimentação cerca de 5x maior;
  • Eliminação do acompanhamento manual baseado em planilhas;
  • Automação do pipeline de ponta a ponta;
  • Menor necessidade de monitoramento manual de jobs durante a madrugada;
  • Onboarding mais simples para novos pesquisadores;
  • Reprodutibilidade completa dos experimentos por meio de tags do git.

Na prática, um trabalho que antes exigia cerca de um mês de experimentação manual pode agora ser concluído em menos de uma semana, com menos erros e maior confiança estatística.

Próximos passos

Seguimos expandindo o framework com novas capacidades, incluindo resumos de experimentos gerados por IA, interfaces de desenvolvimento mais limpas e melhor compartilhamento de dados entre experimentos. À medida que o número de aplicações downstream cresce, o framework continua servindo como uma camada consistente de validação horizontal entre tarefas, ajudando a transformar avanços de pesquisa em impacto em produção em escala.

De forma mais ampla, este trabalho reflete um princípio central do Nubank: combater a complexidade não apenas nos produtos financeiros, mas também na infraestrutura que os sustenta. O framework cria um ambiente projetado não só para humanos, mas também para agentes automatizados. Quando o ciclo de experimentação se tornar totalmente fechado, os agentes poderão ajudar continuamente a testar, executar, monitorar e avaliar hipóteses de pesquisa, viabilizando iteração contínua 24/7 e automelhoria.

Já estamos vendo resultados iniciais promissores com essa configuração, especialmente em áreas como:

  • Otimização de GPU, em que o Model FLOPs Utilization (MFU) subiu de 10–15% para 30-40%;
  • Atenção linear, em que igualamos o desempenho de AUC reduzindo custos de treinamento e viabilizando treinos com sequências mais longas.

Nosso objetivo continua sendo reduzir ainda mais o custo operacional da experimentação, permitindo que os pesquisadores foquem na parte de maior alavancagem do trabalho: identificar as perguntas certas, interpretar resultados e decidir o que explorar em seguida. Se bem-sucedido, isso pode representar mais um salto na velocidade de experimentação e na evolução dos modelos.

Referências

[1] Fine-Tuning Transaction User Models

[2] Andrej Karpathy – auto-research (https://github.com/karpathy/autoresearch)

Check our job opportunies