Made With ML: the laptop track, the Anyscale track, and what gets pinned
Learn how to develop, deploy and iterate on production-grade ML applications.
At a glance
- What is it?
- Made With ML is a course that carries you from experimentation to a deployed model, and its repository is a full teaching environment built on Ray with the pins, tooling and defaults that implies. The details worth knowing before you start are which track is open by default, which files coverage ignores, and what running the cleaner also reformats.
- Who is it for?
- Work through Made With ML if you want a guided path from data versioning to a served model and you are willing to follow a pinned 2023 era environment rather than your own stack. Do not adopt the repository as a template for a new project without reading the tooling first, because the coverage configuration excludes `madewithml/evaluate.py` and `madewithml/serve.py` and the Makefile has no test target at all.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The setup section makes you toggle a track before it gives you a command
Read the setup page as three different documents, because the markup only differs by which dropdown is open. The Anyscale track is expanded by default, the Local track is collapsed, and a third option covers cloud platforms, Kubernetes and on-premises. Choosing Anyscale means creating a workspace whose name, project, cluster environment and compute config are all spelled out: `madewithml`, `madewithml`, `madewithml-cluster-env` and `madewithml-cluster-compute-g5.4xlarge`, or the equivalent with `anyscale workspace create ...` from the CLI. The third option is a pointer list rather than a recipe: AWS and GCP through the Ray documentation, community-supported Azure and Aliyun integrations, Kubernetes through the officially supported KubeRay project, and manual deployment for anything else. Consequence for a reader: if you skim the README without expanding the Local section you will follow instructions for a workspace you do not have, and the compute config name is Anyscale specific rather than a portable description of hardware.
The Anyscale track never runs pip install, so the two environments can diverge
This is the sharpest edge in the setup. On a laptop you run the full sequence:
export PYTHONPATH=$PYTHONPATH:$PWD
python3 -m venv venv # recommend using Python 3.10
source venv/bin/activate # on Windows: venv\Scripts\activate
python3 -m pip install --upgrade pip setuptools wheel
python3 -m pip install -r requirements.txt
pre-commit install
pre-commit autoupdateOn Anyscale the environment is described as already prepared through the cluster environment, so the commands reduce to the same `export PYTHONPATH` plus the two pre-commit commands. That is convenient and it is also an uncontrolled variable: your libraries now come from a workspace image whose contents the repository does not pin, while your laptop gets exactly what `requirements.txt` says. `export PYTHONPATH=$PYTHONPATH:$PWD` in both tracks is the other detail to notice, because it means the `madewithml/` package is imported straight from the working tree rather than installed, so an edit takes effect without a reinstall and a broken checkout breaks the import. Python 3.10 is the recommended version and the setup points at pyenv or pyenv-win for managing it.
requirements.txt pins a 2023 stack with == on every runtime dependency
The environment is fully specified, which makes a lesson reproducible and makes it old. The default group is `hyperopt==0.2.7`, `ipywidgets>=8`, `matplotlib==3.7.1`, `mlflow==2.3.1`, `nltk==3.8.1`, `numpy==1.24.3`, `numpyencoder==0.3.0`, `pandas==2.0.1`, `python-dotenv==1.0.0`, `ray[air]==2.7.0`, `scikit-learn==1.2.2`, `snorkel==0.9.9`, `SQLAlchemy==1.4.48`, `torch==2.0.0` and `transformers==4.28.1`. Notebook extras add `cleanlab==2.3.1`, `jupyterlab==3.6.3`, `lime==0.2.0.1`, `seaborn==0.12.2` and `wordcloud==1.9.2`, and the deployment group pins `anyscale==0.5.131`. Two things follow. Your training and serving stack is the 2023 generation, so lessons about tracking and serving reflect the APIs of `mlflow==2.3.1` and `ray[air]==2.7.0` rather than today's. And the one part of the toolchain that is deliberately allowed to move is the pre-commit hooks, because the setup runs `pre-commit autoupdate` right after installing them, so hook versions float while every library version is nailed down.
Coverage is configured to omit evaluate.py and serve.py
The coverage configuration is short and worth reading before you trust any number it produces:
omit=["madewithml/evaluate.py", "madewithml/serve.py"]Those are the evaluation and serving modules, which in a machine learning system are the two files where a silent mistake turns into a wrong number reported to someone or a model that will not answer. They are excluded, and pytest is configured with `testpaths = ["tests"]` and `python_files = "test_*.py"`, so the suite runs over that directory. The Makefile compounds it: its targets are `style` and `clean`, with no test target, so `make test` does not exist and running the suite is a manual `pytest`. Coverage here is a teaching aid for the data and training layers rather than a claim about the whole system, which is a reasonable choice for a course and a poor one to inherit into a project. If you use this repository as a starting point, re-include those two files before you believe a coverage percentage.
make clean depends on style, so cleaning your checkout reformats it
The Makefile is eight targets of behaviour in a very small file, and one dependency is a trap. `style` runs `black .`, `flake8`, `python3 -m isort .` and `pyupgrade`, in that order. `clean` depends on `style`, and only after reformatting your code does it run `python notebooks/clear_cell_nums.py`, delete `.DS_Store` files, remove `__pycache__`, `.pyc` and `.pyo`, remove `.pytest_cache` and `.ipynb_checkpoints`, and delete `.coverage*`. So `make clean` is not a read only operation, and wiring it into a script or a git hook will produce a diff full of formatting changes next to the deletions you wanted. The notebook script has a legitimate reason to be there: the primary entry point is `notebooks/madewithml.ipynb`, and stripping cell execution numbers keeps committed notebooks free of output state.
isort wraps imports at 79 while black allows 150
The style configuration contains a disagreement, and because `make style` runs the tools in sequence, the last one wins on imports. Black is configured with `line-length = 150` and a long exclude list covering `venv`, `build` and `dist` among others. iSort is set to the black profile but with `line_length = 79`, `multi_line_output = 3` and `include_trailing_comma = true`. Flake8 then ignores `E501`, the line too long rule, with the reason given in a comment, so no linter objects to a 150 character line while iSort still wraps import blocks at 79. Nobody is harmed by this, and it is the kind of detail that only matters until it is yours: run `make style` twice and a diff can appear on the second pass because iSort rewraps what black had already joined. The other setting to know is `pyupgrade` with `py39plus = true`, which is looser than the Python 3.10 the course recommends.
One release, a free repository, and a course site that is the product
The repository is MIT licensed, the default branch is `main`, and the release history is a single tag, v1.1.0, published on 2026-03-04, the same day as the last push. That is a course snapshot rather than a library with a support policy, and the README invites 40K+ developers into the course while pointing at madewithml.com for the lessons themselves. The layout matches a teaching project: `notebooks/` for the walkthrough, `madewithml/` for the package the lessons build, `datasets/`, `deploy/`, `tests/`, and `mkdocs.yml` with `docs/` for the site. The Git setup step is deliberately simple, `git clone https://github.com/GokuMohandas/Made-With-ML.git .` into a repository you created yourself with the README toggle that produces a `main` branch, and credentials go in a `.env` you create with `touch .env` and `source`, holding a `GITHUB_USERNAME` placeholder you have to change. The paid layer sits elsewhere: the README pitches a live cohort where Anyscale supplies the structure, the GPUs and the community, so the free path is the laptop track and the supported path is that cohort.
Editorial conclusion
Work through Made With ML if you want a guided path from data versioning to a served model and you are willing to follow a pinned 2023 era environment rather than your own stack. Do not adopt the repository as a template for a new project without reading the tooling first, because the coverage configuration excludes `madewithml/evaluate.py` and `madewithml/serve.py` and the Makefile has no test target at all. Before you start, decide which track you are on: the Anyscale instructions are open by default and skip the pip install entirely, so the cluster environment and your laptop are not guaranteed to hold the same libraries. And check the dates, because the only release is v1.1.0 from 2026-03-04 and the last push to `main` was on 2026-03-04, while `requirements.txt` still pins `torch==2.0.0` and `ray[air]==2.7.0`.
Frequently asked questions
What is MLOps, as Made With ML teaches it?
The course frames MLOps as connecting the components, specifically tracking, testing, serving and orchestration, into one end to end system, and moving from experimentation in design and development to production in deployment and iteration. It also sets a goal of getting there without changes to your code or infrastructure management, using CI/CD workflows to train and deploy models in a modular way.
What does Made With ML ask me to install locally?
A virtual environment with Python 3.10, then `python3 -m pip install -r requirements.txt`, then `pre-commit install` and `pre-commit autoupdate`. The setup also exports `PYTHONPATH` to the working directory so the `madewithml/` package is imported from the checkout rather than installed, and recommends pyenv or pyenv-win to manage the interpreter.
Can I work through Made With ML without a GPU cluster?
Yes. The Local track uses your personal laptop as the cluster, with one CPU as the head node and the remaining CPUs as workers, and the README states that all of the code works on a personal laptop, only slower than a larger cluster. The Anyscale track is the one that supplies GPUs, through a compute config named `madewithml-cluster-compute-g5.4xlarge`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gokumohandas-made-with-ml)