3 · Una API de predicción JSON
Convierte el modelo en un servicio que otros programas pueden llamar: una ruta `POST /predict` lee un cuerpo JSON con `request.get_json()`, ensambla un vector de características, corre `model.predict`, y devuelve `jsonify({...})` — con el código de estado HTTP correcto para éxito vs entrada mala vs error de servidor.
Una API de predicción es una ruta `POST /predict`: lee el cuerpo JSON con `request.get_json()`, convierte el dict de características en un vector ordenado, llama a `model.predict`, y devuelve `jsonify({...})`. El CÓDIGO DE ESTADO HTTP es parte del contrato — `200` para una buena predicción, `400/422` cuando la entrada del CLIENTE está mal, `500` cuando algo en el SERVIDOR se rompe.
Sin esto:
Sin un endpoint JSON, ningún otro sistema puede pedir una predicción; y sin códigos de estado correctos, quienes llaman no pueden distinguir una predicción exitosa de una petición rechazada o un servidor caído.
El Capítulo 1 te dio rutas que retornan strings y dicts. Ahora construimos lo de verdad: una API de predicción JSON que otros programas llaman para obtener la respuesta de un modelo.
La ruta es POST /predict. Es POST (no GET) porque quien llama está enviando datos — los valores de las características — en el cuerpo de la petición. En Flask lo declaras con @app.route("/predict", methods=["POST"]).
Lee el cuerpo con request.get_json(). El objeto request de Flask contiene la petición entrante. request.get_json() parsea el cuerpo JSON a un dict de Python. Así que un cuerpo de petición {"tenure": 12, "monthly_charges": 80, ...} se vuelve un dict que puedes indexar.
Ensambla el vector de características — el orden importa. El modelo fue entrenado con las características en un orden específico. Debes construir el vector en ese mismo orden exacto, o alimentarás "monthly_charges" en la posición que el modelo cree que es "tenure" — un bug silencioso y peligroso. Así que tomas cada característica por nombre en el orden de entrenamiento: [payload[name] for name in FEATURES].
Predice, luego jsonify. Corre model.predict (o predict_proba), empaqueta el resultado en un dict, y retorna jsonify({"prediction": 1, "probability": 0.83}). jsonify serializa el dict a una respuesta JSON con la cabecera correcta Content-Type: application/json — la forma estándar de devolver JSON desde Flask.
Los códigos de estado son el contrato. Una API JSON no es solo un cuerpo — es un cuerpo más un código de estado, y quienes llaman dependen del código para saber qué pasó:
200 OK— la predicción tuvo éxito; el cuerpo es el resultado.400 Bad Request— la petición en sí está malformada: no es JSON válido, o no hay cuerpo en absoluto. Flask ni siquiera puede parsearla.422 Unprocessable Entity— el JSON parseó bien, pero su contenido es inválido para tu endpoint: una característica falta, no es numérica, o está fuera de rango. La sintaxis está bien; la semántica está mal. Este es el código que devolverás para valores de característica malos (construyes esa compuerta en la lección 5).500 Internal Server Error— algo se rompió de tu lado (un bug, el archivo del modelo ausente). Nunca culpa del cliente.
La distinción que confunde a la gente: 400 = "no puedo leer tu petición" vs 422 = "la leí, pero los valores no tienen sentido". Devolver el correcto le permite a quien llama reaccionar bien — arreglar su JSON en un 400, arreglar sus valores de característica en un 422, reintentar luego en un 500.
La celda de solo-lectura muestra la ruta de Flask; la celda ejecutable debajo es la lógica pura de predicción que la ruta envuelve — dict de payload → vector ordenado → model.predict → dict de resultado — corriendo sobre un modelo pequeño entrenado.
Una ruta `POST /predict` de Flask: `request.get_json()` para leer el cuerpo, un `400` para JSON malformado, un `422` para contenido de características malo, luego `jsonify(...)` con un `200` en éxito.
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Un cliente hace POST de JSON perfectamente válido a `/predict`, pero falta una característica requerida y otra es el string `"high"` en vez de un número. ¿Qué código de estado HTTP encaja mejor con esta respuesta?
- Una API de predicción es una ruta `POST /predict`: `request.get_json()` lee el cuerpo, construyes el vector de características en el orden de entrenamiento, corres `model.predict`, y retornas `jsonify({...})`.
- Ensambla las características en el orden EXACTO en que se entrenó el modelo — tomar cada una por nombre evita el bug silencioso de meter valores en las posiciones equivocadas.
- El código de estado es parte del contrato: `200` éxito, `400` petición no parseable, `422` JSON válido con contenido inválido, `500` un fallo genuino del lado del servidor.
Esta forma `POST /predict` — leer JSON, construir el vector, predecir, devolver JSON con un código de estado — es como prácticamente todo modelo en producción es consumido por otros servicios.
Si lo quitas: Sin un endpoint JSON y sin disciplina de códigos de estado, quienes llaman no pueden integrar el modelo programáticamente ni siquiera distinguir una buena predicción de una petición rechazada.