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

Agradecimientos: Queremos agradecer al equipo de AI-Core (Data Intelligence, ML, Infra y Platform), cuyos esfuerzos conjuntos en ingesta de datos, mejoras del framework y soporte en producción fueron esenciales para este trabajo.

En Nubank investigamos modelos de representación de transacciones basados en transformers que pueden adaptarse a un conjunto creciente de aplicaciones downstream. En los últimos años, este trabajo pasó de dar soporte a solo un puñado de tareas internas a impulsar un conjunto mucho más amplio, con más de 20 benchmarks distintos. Ese crecimiento trajo un nuevo desafío: ¿cómo asegurar que los cambios en datos, arquitectura y entrenamiento mejoraran los modelos de forma consistente en su conjunto, en lugar de solo elevar el desempeño en tareas aisladas?

Para responder a esa pregunta, construimos un framework de benchmarking enfocado en la investigación horizontal de modelos y datos. Nuestro objetivo era transformar un proceso de experimentación manual y operativamente pesado en un flujo automatizado, reproducible y estadísticamente riguroso. Este framework nos permite probar cambios horizontalmente en múltiples tareas downstream y múltiples repeticiones de forma simultánea. En lugar de evaluar ideas benchmark por benchmark, ahora podemos identificar qué mejoras generalizan realmente entre aplicaciones y cuáles solo funcionan en escenarios específicos. El resultado fue una reducción drástica del overhead operativo de la experimentación. Con el framework, nuestro equipo pasó a ejecutar aproximadamente cinco veces más experimentos por mes, dedicando más tiempo a la investigación en sí y menos a operar pipelines.

El punto de partida: buscar mejoras horizontales

Nuestro equipo estableció un objetivo claro: generar mejoras promedio significativas en un benchmark que representa múltiples tareas internas. Esto implicó dejar atrás optimizaciones excesivamente especializadas dirigidas a una sola aplicación. Cada nueva dirección de investigación (ya fuera una fuente de datos adicional, un cambio arquitectónico o una nueva formulación de entrenamiento) debía demostrar ganancias en múltiples tareas al mismo tiempo.

Organizamos este trabajo en dos grandes frentes:

  • Escalamiento de datos: incorporación de nuevas fuentes de datos transaccionales;
  • Cambios arquitectónicos: desde paradigmas de modelo completamente nuevos hasta ajustes menores, como funciones de activación, batch normalization, learning rates desacoplados, mayor longitud de contexto y arquitecturas alternativas de blending.

Sin embargo, cada nueva hipótesis requería decenas o incluso cientos de ejecuciones de entrenamiento y evaluación distribuidas en múltiples benchmarks. Con un alcance de investigación ambicioso y un presupuesto de cómputo limitado, quedó claro que el cuello de botella ya no era solo el modelado, sino el propio proceso de experimentación.

Descubre las oportunidades

El problema: la experimentación manual no escala

Antes del framework de benchmarking, ejecutar un solo experimento era un proceso manual que podía tomar varios días. Los investigadores debían:

  1. Configurar y ejecutar la preparación de datos;
  2. Tomar la salida, configurar el pre-entrenamiento, enviar el job, monitorearlo y hacer seguimiento de los resultados;
  3. Repetir el proceso para el fine-tuning; 
  4. Ejecutar inferencia sobre el dataset de prueba;
  5. Consolidar manualmente los resultados para compararlos con el baseline.

En la práctica, la mayor parte del tiempo se consumía en tareas operativas: configurar jobs, copiar parámetros entre etapas, hacer seguimiento de salidas y lidiar manualmente con fallas. Incluso repetir un experimento exigía casi el mismo esfuerzo que ejecutarlo por primera vez.

El seguimiento en sí se convirtió en otra fuente de fricción. Los experimentos se documentaban en planillas enormes con miles de celdas, donde pequeños errores podían comprometer grandes porciones de los resultados. Bajo presión de tiempo, los investigadores monitoreaban los jobs con frecuencia e intervenían manualmente cuando ocurrían fallas. Además, el riesgo de diferencias sutiles en configuraciones o cambios de código entre ejecuciones introducía posibles factores de confusión, lo que exigía una organización cuidadosa de los experimentos.

La solución: un framework de benchmarking

El trabajo manual descrito escala mal a medida que crece el número de aplicaciones downstream. Por ejemplo, cada experimento suele requerir múltiples repeticiones para establecer confianza estadística y debe evaluarse sobre todo el conjunto de benchmarks downstream, no solo sobre una tarea. Sin automatización, eso significaba multiplicar cada paso manual por el número de repeticiones y el número de benchmarks. Por eso diseñamos un framework de benchmarking para automatizar el proceso de experimentación. En concreto, definimos cuatro objetivos principales:

  • Reducir a casi cero el costo operativo de las repeticiones;
  • Minimizar el esfuerzo necesario para orquestar nuevos experimentos;
  • Reducir los errores de seguimiento;
  • Permitir que los investigadores se enfoquen en las ideas y no en el proceso.

Y el framework se construyó sobre dos pilares principales:

1. La capacidad de representar todo el pipeline de modelado en código, desde la preparación de datos hasta el entrenamiento, la inferencia y la evaluación (como una branch del codebase);

2. Branch deployments, que crean entornos aislados de experimentación.

Cómo funciona el framework

El flujo de trabajo cambió drásticamente. Hoy, el proceso del investigador es esencialmente:

  1. Formular una hipótesis;
  2. Implementar un cambio de código;
  3. Crear un deployment a partir de la branch de git;
  4. Ejecutar el pipeline.

Todo lo demás ocurre automáticamente. El sistema:

  • Recolecta todos los datos necesarios;
  • Genera los datasets de entrenamiento, validación y prueba;
  • Ejecuta el pre-entrenamiento;
  • Ejecuta múltiples repeticiones de fine-tuning;
  • Ejecuta la inferencia;
  • Evalúa las métricas;
  • Registra automáticamente resultados y parámetros en un leaderboard centralizado.

Una vez implementado el cambio, los jobs se ejecutan de extremo a extremo y cada etapa comienza automáticamente en cuanto se completan sus dependencias. Además, como cada experimento está vinculado a un tag específico de git, reproducir o extender experimentos previos se volvió mucho más simple: los investigadores pueden recuperar el tag, crear una nueva branch e iterar desde ahí.

Rigor estadístico: detectar mejoras prometedoras

Una de las decisiones de diseño más importantes detrás del framework fue integrar el filtro de significancia estadística directamente en el sistema. En la investigación de machine learning, uno de los errores más comunes es confiar en resultados ocasionales que parecen prometedores por pura suerte estadística y construir sobre ellos direcciones de investigación completas. El filtro existe para indicarnos qué direcciones merecen esa inversión, no para certificar un resultado aislado como un hallazgo definitivo.

Antes de implementar el framework, realizamos un estudio dedicado para medir la varianza del joint fusion [1] entre ejecuciones repetidas. Con 10 ejecuciones idénticas del baseline, observamos que la varianza del AUC de prueba era relativamente baja, con una desviación estándar cercana a 0,02.

A partir de ahí, realizamos simulaciones para definir un protocolo estadístico confiable. Encontramos que usar:

  • N = 5 ejecuciones de baseline;
  • M = 2 ejecuciones del challenger;
  • Prueba t de Welch;

nos permitía detectar de forma confiable mejoras cercanas a 0,08 pp en AUC, con un poder estadístico del 95% y un nivel de significancia de 0,05. Las ganancias menores, cercanas a 0,04 pp, se detectan solo alrededor de la mitad de las veces, lo que basta para marcar una dirección como prometedora y digna de más ejecuciones, pero no para tratar una sola comparación como concluyente.

Es importante señalar que el protocolo de 5 y 2 es un mínimo. Un resultado limítrofe cercano a 0,04 pp puede confirmarse con más ejecuciones. La mayor parte del error estándar proviene del brazo challenger de dos ejecuciones, así que esas son las ejecuciones que conviene sumar: pasar de 2 a 5 mueve el efecto detectable de forma confiable de unos 0,08 pp a unos 0,055 pp, y 10 ejecuciones del challenger llegan a unos 0,045 pp. La herramienta de reporte vuelve a correr la prueba automáticamente con el nuevo número de ejecuciones. La mayoría de los experimentos se quedan en el filtro barato, y solo las direcciones que vale la pena confirmar reciben los números mayores.

Esta metodología quedó incorporada directamente en el framework. Hoy, la herramienta de reporte realiza automáticamente pruebas estadísticas entre las múltiples repeticiones de cada experimento, entregando resultados estadísticamente validados por defecto. A continuación se muestra una interfaz típica con estos resultados de pruebas de significancia sobre un conjunto de tareas downstream.

Configuración del benchmark

La evaluación del benchmark sigue un proceso estructurado, basado en:

  • Baselines estandarizados con cinco ejecuciones;
  • Benchmarks multitarea compartidos;
  • Evaluación consistente entre múltiples repeticiones.

El framework también se diseñó para crecer de forma continua. Agregar nuevas tareas de benchmark no requiere más que abrir un pull request.

Resultados: evaluación de variantes de experimentos

Con el framework de benchmarking, empezamos a explorar sistemáticamente mejoras tanto arquitectónicas como de datos respecto de nuestro baseline original: un transformer decoder-only a nivel de token que usa fine-tuning con LoRA y un módulo de blending DCNv2.

En el plano arquitectónico, evaluamos cambios en challengers como:

  • Mayor longitud de contexto;
  • Optimizaciones de entrenamiento;
  • Nuevas arquitecturas construidas desde cero.

En el plano de los datos, probamos cuatro nuevas fuentes de datos transaccionales, tanto individualmente como en combinación.

Los resultados mostraron que algunos cambios mejoraban solo benchmarks específicos, mientras que otros aportaban poca ganancia a escalas menores pero se volvían muy relevantes en experimentos mayores. Sin un framework estructurado, comparar todas estas direcciones simultáneamente sería inviable. Como parte de la fase inicial de investigación de nuFormer, combinamos los cambios arquitectónicos más prometedores con fuentes de datos adicionales y produjimos un baseline significativamente mejor, con ganancias estadísticamente validadas en múltiples benchmarks internos.

Impacto

El framework generó mejoras medibles en varias dimensiones:

  • Velocidad de experimentación aproximadamente 5x mayor;
  • Eliminación del seguimiento manual basado en planillas;
  • Automatización del pipeline de extremo a extremo;
  • Menor necesidad de monitoreo manual de jobs durante la noche;
  • Onboarding más simple para nuevos investigadores;
  • Reproducibilidad completa de los experimentos mediante tags de git.

En la práctica, un trabajo que antes requería alrededor de un mes de experimentación manual hoy puede completarse en menos de una semana, con menos errores y mayor confianza estadística.

Próximos pasos

Seguimos ampliando el framework con nuevas capacidades, incluyendo resúmenes de experimentos generados por IA, interfaces de desarrollo más limpias y un mejor intercambio de datos entre experimentos. A medida que crece el número de aplicaciones downstream, el framework sigue funcionando como una capa consistente de validación horizontal entre tareas, ayudando a convertir los avances de investigación en impacto productivo a escala.

De forma más amplia, este trabajo refleja un principio central de Nubank: combatir la complejidad no solo en los productos financieros, sino también en la infraestructura que los sostiene. El framework crea un entorno diseñado no solo para humanos, sino también para agentes automatizados. Cuando el ciclo de experimentación sea totalmente cerrado, los agentes podrán ayudar continuamente a probar, ejecutar, monitorear y evaluar hipótesis de investigación, habilitando una iteración continua 24/7 y la automejora.

Ya estamos viendo resultados iniciales prometedores con esta configuración, especialmente en áreas como:

  • Optimización de GPU, donde el Model FLOPs Utilization (MFU) aumentó de 10–15% a 30-40%;
  • Atención lineal, donde igualamos el desempeño de AUC reduciendo los costos de entrenamiento y habilitando el entrenamiento con secuencias más largas.

Nuestro objetivo sigue siendo reducir aún más el costo operativo de la experimentación, permitiendo que los investigadores se concentren en la parte de mayor apalancamiento del trabajo: identificar las preguntas correctas, interpretar resultados y decidir qué explorar a continuación. Si tiene éxito, esto podría representar otro salto en la velocidad de experimentación y en la evolución de los modelos.

Referencias

[1] Fine-Tuning Transaction User Models

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

Descubre las oportunidades