ERP ML Predictor
Pipeline ML que corre sobre el ERP RIBISOFT: predice riesgo de mora en cartera y genera forecast de ventas, sin mover datos fuera del servidor del cliente.
AUC 0.999 · F1 0.91 · Recall 1.0 en 3 empresas con datos sintéticos
Auto-reentrenamiento: el modelo detecta caída de calidad y se re-entrena solo
Un JSON para onboardear un cliente nuevo — sin tocar código
Resumen ejecutivo
Contexto de negocio
Las empresas que usan el ERP RIBISOFT acumulan años de historia transaccional pero toman decisiones de cartera y ventas a ciegas. El área de cartera no sabe qué clientes van a incumplir hasta que ya incumplieron. Gerencia presupuesta ventas por intuición. Los datos ya existen en el ERP RIBISOFT desde el día 1 del cliente — solo falta activarlos.
Mi rol
Construí el pipeline completo: generación de datos sintéticos con la estructura real del ERP RIBISOFT, extractor SQL dual (SQLite dev / SQL Server prod), feature engineering de cartera (RFM, ratio de pago, saldo logarítmico), comparativa LogReg vs XGBoost con auto-selección por AUC, modelo Prophet con auto-reentrenamiento, CLI orquestador con typer y exit codes para SQL Agent Job, y dashboard Streamlit con lenguaje de negocio (sin jerga técnica).
Stakeholders
Sistemas y fuentes
Preguntas de negocio que responde
- ¿Qué clientes tienen alta probabilidad de no pagar el próximo mes?
- ¿Cuánto vamos a vender el próximo trimestre?
- ¿El modelo sigue siendo preciso o necesita re-entrenarse?
Tecnologías
Decisión de arquitectura — por qué no hay API externa
La restricción central: ningún dato sale del servidor del cliente. Esto descartó APIs de ML en la nube y entrenamiento centralizado. Todo el pipeline — extracción, feature engineering, entrenamiento, predicción, escritura de resultados — corre en el mismo SQL Server del cliente.
Para clientes en la nube de RIBISOFT: Python conecta directo, latencia cero. Para clientes on-premise: se despliega un único .exe generado con PyInstaller + un config.json. Sin instalación de Python, sin gestión de dependencias del lado del cliente.
Modelo de mora — por qué el split temporal no funcionó
El split intuitivo — entrenar con datos viejos, testear con datos recientes — falló porque con 24 meses de historia, casi todas las facturas están “vencidas” por fecha de calendario. El set de test quedaba con 0 muestras positivas.
Fix: split estratificado que preserva el 15% de mora en train y test. Trade-off documentado honestamente: el split no es verdaderamente temporal, lo que significa que el modelo no ha sido probado sobre datos del futuro real.
Lógica de auto-reentrenamiento
El pipeline evalúa dos condiciones antes de cada corrida:
- Días desde el último entrenamiento > umbral (configurable por cliente)
- AUC sobre datos recientes < AUC mínimo (configurable por cliente)
Si cualquiera se cumple, el modelo se re-entrena sobre el dataset completo antes de predecir. El SQL Agent Job siempre recibe un modelo fresco sin intervención manual.
Dashboard — lenguaje de negocio, no jerga ML
prob_mora → “Probabilidad de incumplimiento”. alerta → “Requiere atención”. AUC → “Confiabilidad del modelo”. MAPE → “Margen de error promedio”.
La regla: si el área de cartera no puede actuar sobre un número, ese número no debería estar en pantalla.
¿Qué te pareció este proyecto?
Si tienes preguntas sobre cómo lo hice o quieres charlar sobre datos, escríbeme.