12 · Capstone: an end-to-end model web app
Everything comes together: ONE trained artifact, exposed TWO ways — a Flask JSON API for machines AND a Streamlit dashboard for humans — both validating input over the same model, both deployable as containers. This is the bootcamp's finish line: from `bc-py-01`'s first `print` to a deployed, monitored, user-facing model.
The capstone wires the whole track together: load ONE trained artifact once, then expose it TWO ways over the SAME model — a Flask `POST /predict` JSON API (machine interface, validates input, returns JSON with status codes) AND a Streamlit dashboard (human interface, widgets + a chart) — and deploy both as containers. Same round-trip underneath: request → validate → `model.predict` → response.
Without this:
Without tying the pieces together, you have isolated lessons instead of a shipped product — and you'd miss the payoff: one model artifact serving both other systems and real people, the actual outcome a deployed ML project delivers.
This is it — the finish line of the entire bootcamp. You started at bc-py-01 with a single print(...). You learned Python, statistics, EDA, supervised and unsupervised ML, NLP, deep learning; you operationalized models with MLOps; and across this Web track you learned to wrap a model in Flask and Streamlit. Now you'll assemble it all into one shipped product: a single trained model, given both a machine interface and a human interface, ready to deploy.
The architecture: one artifact, two front doors. A real ML project rarely needs to choose between an API and a dashboard — it ships both over the same model:
- A Flask JSON API — the machine interface. Other services
POSTfeatures to/predict, the route validates the payload (keys present, numeric, in range — lesson 5), runsmodel.predict, and returnsjsonify({...})with the right status code. This is how the model integrates into the rest of your systems. - A Streamlit dashboard — the human interface. An analyst opens a page, fills in a
st.form, and sees a prediction in anst.metricplus a chart of the scores. Same model, same validation logic, but a UI a person can actually use.
The crucial discipline: one model, one validation path, two surfaces. Both front doors load the same .joblib artifact (once each, at startup / via @st.cache_resource) and apply the same feature-order and validation rules. The API and the dashboard are just two presentations of one prediction function — never two divergent copies of the logic. That's what keeps them consistent: a customer scored through the dashboard gets the identical answer a service would get through the API.
The same round-trip underneath. Whether the caller is curl or a browser, the flow is the one you've seen since lesson 1: request → match a route → validate → model.predict → build a response → return it. The scene below replays that full round-trip one last time — the spine of everything in this track.
Deploying it. Each surface containerizes independently (lesson 11): the Flask API behind gunicorn on port 8000, the Streamlit dashboard via streamlit run on port 8501, each a Dockerfile + requirements.txt, both shipped to the cloud through the MLOps pipeline. Two containers, one model, deployed.
What you've built, end to end. Trace the whole journey: raw data → EDA → a trained scikit-learn model → an MLOps pipeline that versions, serves, and monitors it → and now a Flask API and a Streamlit dashboard that put that model in front of both the systems and the people who need it. That is a complete, production-grade ML product — from print("hello") to a deployed, monitored, user-facing model. The bootcamp is complete.
The read-along cell shows the consolidated app: one loaded model, the validated Flask /predict route, and the Streamlit dashboard — the two interfaces side by side over a single artifact.
The consolidated capstone: one `.joblib` artifact and one shared `validate_and_extract` gate, exposed as both a Flask `POST /predict` JSON API (for machines, with status codes) and a Streamlit `st.form` dashboard (for humans, with a metric + chart) — each deployable as its own container.
The HTTP round-trip: the request travels down to the server (blue), the response back up to the browser (green).
A request hits the capstone's Flask `/predict` route. In the correct order, what does the route do before returning a response?
- The capstone exposes ONE trained artifact TWO ways over the same model: a Flask JSON API for machines and a Streamlit dashboard for humans — never two divergent copies of the logic.
- Both interfaces share the same load-once model and the same validation gate, and both follow the same round-trip: request → validate → `model.predict` → response.
- Each surface deploys as its own container (Flask via gunicorn on 8000, Streamlit on 8501) — completing the path from raw data to a deployed, user-facing ML product.
This two-interface, one-model architecture IS a shipped ML product — the same artifact serving other systems through an API and people through a dashboard is what production ML teams actually deploy.
If you remove it: Without assembling the pieces, the model stays a collection of disconnected demos instead of one deployable product that both systems and people can actually use.