12 · Capstone: una app web de modelo de extremo a extremo
Todo se junta: UN artefacto entrenado, expuesto de DOS formas — una API JSON de Flask para máquinas Y un panel de Streamlit para humanos — ambos validando la entrada sobre el mismo modelo, ambos desplegables como contenedores. Esta es la meta del bootcamp: desde el primer `print` de `bc-py-01` hasta un modelo desplegado, monitoreado, y de cara al usuario.
El capstone conecta toda la pista: carga UN artefacto entrenado una vez, luego exponlo de DOS formas sobre el MISMO modelo — una API JSON `POST /predict` de Flask (interfaz de máquina, valida la entrada, devuelve JSON con códigos de estado) Y un panel de Streamlit (interfaz humana, widgets + un gráfico) — y despliega ambos como contenedores. El mismo ciclo por debajo: petición → validar → `model.predict` → respuesta.
Sin esto:
Sin atar las piezas, tienes lecciones aisladas en vez de un producto enviado — y te perderías la recompensa: un artefacto de modelo sirviendo tanto a otros sistemas como a personas reales, el resultado concreto que entrega un proyecto de ML desplegado.
Esto es — la meta de todo el bootcamp. Empezaste en bc-py-01 con un solo print(...). Aprendiste Python, estadística, EDA, ML supervisado y no supervisado, NLP, deep learning; operacionalizaste modelos con MLOps; y a lo largo de esta pista Web aprendiste a envolver un modelo en Flask y Streamlit. Ahora lo ensamblarás todo en un producto enviado: un único modelo entrenado, dotado de ambas una interfaz de máquina y una interfaz humana, listo para desplegar.
La arquitectura: un artefacto, dos puertas de entrada. Un proyecto de ML real rara vez necesita elegir entre una API y un panel — envía ambos sobre el mismo modelo:
- Una API JSON de Flask — la interfaz de máquina. Otros servicios hacen
POSTde características a/predict, la ruta valida el payload (claves presentes, numéricas, en rango — lección 5), corremodel.predict, y devuelvejsonify({...})con el código de estado correcto. Así es como el modelo se integra en el resto de tus sistemas. - Un panel de Streamlit — la interfaz humana. Un analista abre una página, llena un
st.form, y ve una predicción en unst.metricmás un gráfico de los scores. Mismo modelo, misma lógica de validación, pero una UI que una persona puede usar de verdad.
La disciplina crucial: un modelo, un camino de validación, dos superficies. Ambas puertas cargan el mismo artefacto .joblib (una vez cada una, al arrancar / vía @st.cache_resource) y aplican las mismas reglas de orden de características y validación. La API y el panel son solo dos presentaciones de una función de predicción — nunca dos copias divergentes de la lógica. Eso es lo que las mantiene consistentes: un cliente puntuado por el panel obtiene la respuesta idéntica que un servicio obtendría por la API.
El mismo ciclo por debajo. Sea que quien llama es curl o un navegador, el flujo es el que has visto desde la lección 1: petición → emparejar una ruta → validar → model.predict → construir una respuesta → devolverla. La escena de abajo reproduce ese ciclo completo una última vez — la columna vertebral de todo en esta pista.
Desplegarlo. Cada superficie se conteneriza por separado (lección 11): la API de Flask detrás de gunicorn en el puerto 8000, el panel de Streamlit vía streamlit run en el puerto 8501, cada uno un Dockerfile + requirements.txt, ambos enviados a la nube por el pipeline de MLOps. Dos contenedores, un modelo, desplegados.
Lo que has construido, de extremo a extremo. Rastrea todo el viaje: datos crudos → EDA → un modelo de scikit-learn entrenado → un pipeline de MLOps que lo versiona, sirve, y monitorea → y ahora una API de Flask y un panel de Streamlit que ponen ese modelo frente a tanto los sistemas como las personas que lo necesitan. Eso es un producto de ML completo y de grado producción — desde print("hola") hasta un modelo desplegado, monitoreado, y de cara al usuario. El bootcamp está completo.
La celda de solo-lectura muestra la app consolidada: un modelo cargado, la ruta /predict validada de Flask, y el panel de Streamlit — las dos interfaces lado a lado sobre un único artefacto.
El capstone consolidado: un artefacto `.joblib` y una compuerta `validate_and_extract` compartida, expuestos como una API JSON `POST /predict` de Flask (para máquinas, con códigos de estado) y un panel de Streamlit con `st.form` (para humanos, con un metric + gráfico) — cada uno desplegable como su propio contenedor.
El viaje de ida y vuelta HTTP: la petición baja al servidor (azul), la respuesta sube al navegador (verde).
Una petición llega a la ruta `/predict` de Flask del capstone. En el orden correcto, ¿qué hace la ruta antes de devolver una respuesta?
- El capstone expone UN artefacto entrenado de DOS formas sobre el mismo modelo: una API JSON de Flask para máquinas y un panel de Streamlit para humanos — nunca dos copias divergentes de la lógica.
- Ambas interfaces comparten el mismo modelo cargado-una-vez y la misma compuerta de validación, y ambas siguen el mismo ciclo: petición → validar → `model.predict` → respuesta.
- Cada superficie se despliega como su propio contenedor (Flask vía gunicorn en 8000, Streamlit en 8501) — completando el camino de datos crudos a un producto de ML desplegado y de cara al usuario.
Esta arquitectura de dos-interfaces-un-modelo ES un producto de ML enviado — el mismo artefacto sirviendo a otros sistemas por una API y a personas por un panel es lo que los equipos de ML de producción despliegan de verdad.
Si lo quitas: Sin ensamblar las piezas, el modelo se queda en una colección de demos desconectados en vez de un producto desplegable que tanto sistemas como personas pueden usar de verdad.