Setup: Colab, a GPU if You Want One, Model Providers, Libraries and Prices
This takes about ten minutes. You do it once.
Almost every lesson needs no key at all: the maths, the classical models, the networks, the pipelines, the registry, the service and the monitoring all run inside the notebook. Only these places call a hosted language model:
| Module | Lessons that call a hosted model |
|---|---|
| 12 | Lesson 3 (the LLM judge) and the lab; lesson 2 makes one optional call |
| 13 | Lesson 1 makes one optional call (a zero-shot comparison) |
1. Colab
All code runs in Google Colab on the free CPU. Open a new notebook, paste each code block into a cell in order, and run it.
The course targets the Python version Colab runs, which was 3.12 at the last check recorded for this series (13 October 2026); the course's own test environment is Python 3.12.15. Print it once in your first notebook, with the versions of the libraries Colab already ships:
import sys
import numpy, pandas, sklearn, torch
print(sys.version.split()[0], "| numpy", numpy.__version__, "| pandas", pandas.__version__,
"| scikit-learn", sklearn.__version__, "| torch", torch.__version__)Code walkthrough
sys.versionis the version of Python running your notebook. If it does not start with3.12(or a later 3.x), some pinned libraries may refuse to install; the run-locally page says which.- The four imports are libraries Colab already has. The course keeps Colab's own versions of these, because forcing a different version can make Colab ask you to restart. The print tells you which versions you have, so you can compare them with the table in section 8.
Keep the repository in your Drive (the labs)
Colab's own folder, /content, empties when the session ends. Lessons do not mind: each writes the files it needs. The labs build one repository, kestrel, that has to outlive the session, so every lab opens with this cell (it is the Module 1 lab's Step 1, copied exactly). It is safe to run twice.
import os
import sys
if os.path.basename(os.getcwd()) != "kestrel": # not in the repository yet
if "google.colab" in sys.modules: # in Colab: the repository lives in your Drive
from google.colab import drive
drive.mount("/content/drive")
os.chdir("/content/drive/MyDrive")
os.makedirs("kestrel", exist_ok=True)
os.chdir("kestrel")
print("working in", os.path.basename(os.getcwd()))Code walkthrough
- If the current folder is already called
kestrel, nothing happens, so a second run never nests folders. "google.colab" in sys.modulesisTrueonly in Colab. Theredrive.mountasks for access to your Google account and your Drive appears as/content/drive/MyDrive.os.makedirs(..., exist_ok=True)makes the folder if it is missing andos.chdirmoves into it. Every path after this cell is inside the repository. On your own computer the folder is made where the notebook started.
You should see working in kestrel, after a line Mounted at /content/drive in Colab.
2. A GPU, if you want one (optional)
No lesson needs a GPU. Five lessons (Module 4 lessons 3 and 4, Module 7 lessons 1 and 3, Module 12 lesson 1) show a faster or fuller path on one. To get a free one: Runtime, then Change runtime type, then choose T4 GPU, then Save. Free GPU time in Colab is limited and not guaranteed; if none is available, the CPU path in each lesson still works.
import torch
print("GPU available:", torch.cuda.is_available())
if torch.cuda.is_available():
print(torch.cuda.get_device_name(0), round(torch.cuda.get_device_properties(0).total_memory / 2**30, 1), "GiB")Code walkthrough
torch.cuda.is_available()isTrueonly when the notebook has a GPU attached.get_device_name(0)names the first GPU;total_memoryis its memory in bytes, divided by 2 to the power 30 to give gibibytes. Module 7 lesson 1 budgets that memory before training.
3. Choose a model provider (Modules 12 and 13 only)
You only need one provider. You switch by changing one word in the setup cell.
| Provider | What it is | Where you run it | Cost |
|---|---|---|---|
| Groq | A cloud service that runs open-weight models very fast | Google Colab, or your own computer | Free plan with limits |
| Google Gemini | Google's own models, through the Gemini API | Google Colab, or your own computer | Free tier with limits |
| Ollama | A program that runs a model on your own machine | Your own computer (07-run-locally.md) | Free; you supply the computer |
In Colab, choose Groq or Gemini. They need a free key and nothing else. Ollama runs the model on your machine, so no key is needed and no text leaves your computer, which matters in Module 12 when Hannah asks where customer messages may be sent.
Free plans limit requests per minute and per day. If you hit a limit you get an error with the number 429. Wait a minute and try again, or switch provider.
4. Get a key and store it safely
Groq: go to console.groq.com, sign in, open API Keys, create a key and copy it (you will not see it again). Model list: console.groq.com/docs/models.
Google Gemini: go to aistudio.google.com, sign in, choose Get API key, create a key and copy it. Model list: ai.google.dev/gemini-api/docs/models.
Never paste a key into a code cell. Notebooks get shared, and a key in a shared notebook is a key someone else can spend. In Colab:
- In the left sidebar, click the key icon (Secrets).
- Add a secret named exactly
GROQ_API_KEY(for Groq) orGOOGLE_API_KEY(for Gemini), with your key as the value. - Turn on Notebook access for it.
5. The setup cell
Every lesson that calls a hosted model begins with these cells, verbatim. Paste them, set PROVIDER, and run.
The course uses LangChain, a widely used Python library that gives every model provider the same interface, so the rest of your code does not care which one you chose.
%pip install -q -U langchain langgraph langchain-groq langchain-google-genai langchain-ollamaimport os
from langchain.chat_models import init_chat_model
PROVIDER = "groq" # "groq" or "gemini" in Colab; "ollama" on your own computer
MODELS = {"groq": "groq:openai/gpt-oss-20b", "gemini": "google_genai:gemini-3.5-flash-lite", "ollama": "ollama:llama3.2:3b"}
KEY = {"groq": "GROQ_API_KEY", "gemini": "GOOGLE_API_KEY", "ollama": None}[PROVIDER]
if KEY and KEY not in os.environ:
from google.colab import userdata # keys live in Colab's Secrets panel
os.environ[KEY] = userdata.get(KEY)
llm = init_chat_model(MODELS[PROVIDER], temperature=0, max_retries=6)Code walkthrough
%pip install ...installs the libraries once per notebook:langchain(the framework),langgraph(its companion for multi-step workflows) and one connector per provider. This line is the same in every course in the series.PROVIDER = "groq"is the one word you change to switch provider.MODELSnames the model for each provider asprovider:model-name. This is the only place model names appear, so when a name changes you edit one line.KEYis the name of the secret the provider needs. Ollama needs none.- The
ifblock runs only in Colab when the key is not already set: it copies your key from the Secrets panel into an environment variable, which is where LangChain looks for it. init_chat_model(...)creates the model object,llm.temperature=0asks for the most consistent output.max_retries=6makes the client wait and try again when the provider says "too many requests" (a 429).
When the provider rejects a request or a reply
Sometimes a provider returns an error instead of a reply: a malformed answer, a model name that no longer exists, a brief outage. max_retries does not help when the request itself is the problem. The course handles it the same way everywhere: try once more, and if that also fails, say so plainly instead of crashing.
def ask(model, messages):
"""Returns (reply, None), or (None, reason) after two refusals."""
for attempt in range(2): # one retry: the next reply is usually fine
try:
return model.invoke(messages), None
except Exception as err:
last = err
return None, f"provider_error: {type(last).__name__}"Code walkthrough
asksends the messages and returns the reply with no reason, or no reply with a reason.- On an error it tries once more; after a second error it gives up and names the error type.
Lessons use this shape: a request the model could not answer gets the result "provider_error" and is counted as a failure in every score, so one bad reply never stops a notebook and never quietly improves a result. In Module 12 the judge's logic is also checked with a scripted fake: a small object with the same invoke method that returns fixed, labelled replies. A fake's replies are never presented as what a model said. The course does not quote any number from a hosted model unless the lesson ran it and says when.
6. Prices and limits (checked 24 October 2026)
This is the course's one table of model prices. Lessons that count cost say "prices from course-guide/02" and use these numbers. When a provider changes them, this table changes and the lessons follow. US dollars per 1,000,000 tokens, standard paid tier.
| Model (as written in the setup cell) | Input | Cached input | Output | Notes |
|---|---|---|---|---|
groq:openai/gpt-oss-20b | $0.075 | unchecked (not on the models page) | $0.30 | Production model; 131,072-token context, up to 65,536 output tokens |
groq:openai/gpt-oss-120b | $0.15 | unchecked | $0.60 | Same context; the larger option |
google_genai:gemini-3.5-flash-lite | $0.30 | $0.03, plus $1.00 per million tokens per hour of cache storage | $2.50 | Stable. Batch: $0.15 input, $1.25 output. A free tier exists |
google_genai:gemini-3.8-flash | $0.75 | $0.075 | $3.75 | Stable, marked new. Until 31 December 2026; from 1 January 2027 $1.50, $0.15 and $7.50. Batch: $0.375 and $1.875, doubling on the same date |
ollama:llama3.2:3b | $0 | $0 | No fee per token; you pay for the machine. A 2.0 GB download, 128K context. The library page states no licence | |
google_genai:gemini-embedding-2 (shown, not used) | $0.20 | Hosted embeddings (batch $0.10); the course embeds locally |
The Gemini 3.8 Flash price doubles in week 9 of the project weeks. Module 12 lesson 2 uses it as the example of a dated price in a self-hosting decision.
Limits. Groq's rate-limits page lists 30 requests a minute, 1,000 a day, 8,000 tokens a minute and 200,000 tokens a day for both gpt-oss models, and says these are "the base limits for the Developer plan"; your own limits are on your console's limits page. Google's pricing page lists a free tier for both Gemini models above; the free-tier limits are shown in Google AI Studio, not in this course.
Deprecations. Groq's deprecations page lists llama-3.1-8b-instant and llama-3.3-70b-versatile as shut down on 16 August 2026 (the models page still lists them with "Contact Sales" pricing; do not use them), qwen/qwen3.6-27b on 14 September 2026, and groq/compound and groq/compound-mini on 21 September 2026. Google's models page marks Gemini 2.0 Flash, Gemini 2.0 Flash-Lite, Gemini 3.1 Flash-Lite Preview and Gemini 3 Pro Preview as shut down.
Sources (all read 24 October 2026): Groq, Supported models (no date on the page), Rate limits, Deprecations; Google, Gemini models and Gemini Developer API pricing (both "last updated 2026-10-22 UTC"); Ollama, llama3.2. These are the numbers in this course most likely to go out of date.
7. Closed and managed options, shown but not run
Lessons show how the same step looks on closed or managed platforms (OpenAI and Anthropic models, SageMaker, Vertex AI, Databricks, Weights & Biases, Snowflake, BigQuery), using the official SDK snippet from current documentation, labelled not run here and dated. The course does not call them, so no account is needed and no number in the course comes from them. Package versions on PyPI on 24 October 2026, recorded so a snippet names a real version: openai 3.37.0, anthropic 2.3.0, boto3 1.43.118, sagemaker 3.27.0, google-cloud-aiplatform 2.6.0, wandb 0.31.0. Product names on the cloud platforms change; each lesson uses the name on the official page on the day it is written.
8. The libraries
Colab already ships numpy, pandas, scikit-learn, torch and transformers. Each lesson installs only what it imports, in one cell near the top, with the version pinned so your run matches the course's. Those five stay at Colab's own versions unless a lesson fails without a pin.
Versions are the latest releases on PyPI, read on 24 October 2026, except where a conflict forced an older one (marked).
| Library | Pin | First used | What it is for |
|---|---|---|---|
| pytest, hypothesis | pytest==9.1.1, hypothesis==6.170.9 | Modules 1 (lab) and 2 | Tests, and property tests on features |
| line-profiler | line-profiler==5.1.0 | Module 2 | Time per line of a function |
| pyarrow | pyarrow==25.0.1 | Module 2 | Parquet and Arrow. The newest is 26.0.0, but MLflow 3.17.2 requires a version below 26 |
| fastavro, protobuf | fastavro==1.13.1, protobuf==7.36.2 | Module 2 | Other file formats, compared with Parquet |
| lightgbm, xgboost | lightgbm==4.7.0, xgboost==3.4.1 | Module 3 | Gradient-boosted trees |
| statsmodels | statsmodels==0.15.0 | Module 3 | ARIMA for daily volumes |
| imbalanced-learn, umap-learn | imbalanced-learn==0.14.2, umap-learn==0.5.12 | Module 3 | Resampling; UMAP |
| optuna | optuna==5.0.0 | Modules 3 and 6 | Hyperparameter search (a new major version, released 7 September 2026) |
| lightning | lightning==2.6.6 | Module 4 | Training loops with less boilerplate |
| torchvision | Colab's own | Module 4 | The image dataset for the CNN |
| prefect | prefect==3.9.0 | Module 5 | Pipelines as code |
| duckdb | duckdb==2.0.0 | Module 5 | SQL over Parquet (a new major version, released 21 October 2026) |
| deltalake | deltalake==1.6.6 | Module 5 | Delta Lake tables from Python, no Spark (one write in lesson 2). Note: DuckDB 2.0 removed relation.fetchone(); use .fetchall() |
| pandera | pandera==0.34.1 | Module 5 | The data contract |
| dvc | dvc==3.67.1 | Module 5 | Data versioning with a local remote |
| feast | feast==0.67.0 | Module 5 (described only) | A feature store. Requires pandas below 3, so the course describes it and builds the point-in-time join by hand (owner decision, 24 October 2026). To try it yourself, use a separate environment with pandas==2.3.3 |
| mlflow | mlflow==3.17.2 | Module 6 | Experiment tracking and the model registry |
| onnx, onnxruntime, onnxmltools, skl2onnx | 1.23.2, 1.31.0, 1.16.0, 1.20.0 | Module 8 | Exporting and running models in ONNX |
| onnxscript | 0.7.2 | Module 8 | Needed by the dynamo ONNX exporter (the default since PyTorch 2.9) |
| rank-bm25 | 0.2.2 | Module 13 | Keyword search over the customer messages (Apache 2.0) |
| fastapi, httpx | fastapi==0.150.0, httpx==0.28.1 | Module 9 | The scoring service and its TestClient. The newest FastAPI is 0.162.0, but Prefect 3.9.0 requires a version below 0.151 |
| redis, fakeredis | redis==8.1.0, fakeredis==2.40.0 | Module 9 | A prediction cache; fakeredis stands in for a Redis server in Colab |
| evidently | evidently==0.7.23 | Module 11 | Drift reports and tests |
| peft, accelerate, datasets | peft==0.21.2, accelerate==1.15.0, datasets==5.1.0 | Module 12 | LoRA on a small open model |
| huggingface-hub | huggingface-hub==2.3.0 | Module 12 | Downloads from the Hugging Face Hub; transformers 5.20.2 and datasets 5.1.0 accept 2.x |
| bitsandbytes | bitsandbytes==0.50.2 | Module 12 (GPU optional) | QLoRA |
| shap, fairlearn | shap==0.54.1, fairlearn==0.15.0 | Module 14 | Explanations and fairness metrics |
Libraries used only on your own computer (uvicorn, Docker, a Kubernetes cluster, an Airflow server, vLLM, Ollama) are on 07-run-locally.md.
Checked on paper, not yet in Colab. On 24 October 2026 a pip install --dry-run of these pins for Python 3.12 on Linux, wheels only, resolved with no conflict (260 packages), apart from Feast (resolved on its own with pandas 2.3.3) and dvc (one dependency ships only as source code, so a wheels-only check cannot include it). That proves the pins fit together; the first lesson pilot installs and imports them in Colab and records the result here.
9. Open models and datasets (no key)
Each lesson names any model or dataset it downloads, with its licence read from its own page on the day the lesson is written; licences can change, so check before you ship one. Candidates, not yet checked for this course: HuggingFaceTB/SmolLM2-135M-Instruct (LoRA in Module 12; recorded as Apache 2.0 in this series on 18 October 2026) and Fashion-MNIST through torchvision (the CNN in Module 4).
10. When something goes wrong
| What you see | What it means | What to do |
|---|---|---|
SecretNotFoundError | The secret is missing or misnamed | Check the name is exactly GROQ_API_KEY or GOOGLE_API_KEY |
NotebookAccessError | The secret exists but this notebook cannot read it | Turn on Notebook access for the secret |
ModuleNotFoundError: google.colab | Running locally with no key set | See 07-run-locally.md: create the .env file |
AuthenticationError (401) | The key is wrong or was deleted | Create a new key and update the secret |
provider_error: NotFoundError | The model name is out of date | Put a current model name in MODELS |
RateLimitError (429) | You hit the free plan's limit | Wait a minute, or switch PROVIDER |
pip says a package requires pyarrow<26 or fastapi<0.151 | A newer version was installed | Reinstall with the pin from the table above in the same cell, then restart the runtime |
pip says Feast requires pandas<3 | Colab's pandas is 3.x | The course does not run Feast; try it in a separate environment with pandas==2.3.3 |
torch.cuda.is_available() is False | No GPU attached | Either change the runtime type (section 2) or use the CPU path in the lesson |
| A connection error with Ollama | Ollama is not running | Ollama runs on your own computer only: see 07-run-locally.md |