Thomas Piacentini
← Workshop

Cheat sheet

Python Dev Environment for AI

Original text · English

Install uv, make one venv per project, pin with lockfiles, check the route, set up VS Code and avoid silent Python bugs.

The four-layer stack

install first1. System FoundationOS, shell, git, editor,GPU driversprocess2. Package Managersuv, pnpm, cargo, juliaupstore3. Language RuntimesPython 3.11+, Node 20+,Rust, Juliaprocess4. AI/ML LibrariesPyTorch, JAX,transformersmodel
Nodes and connections
NodeRoleKind
1. System FoundationOS, shell, git, editor, GPU driversprocess
2. Package Managersuv, pnpm, cargo, juliaupstore
3. Language RuntimesPython 3.11+, Node 20+, Rust, Juliaprocess
4. AI/ML LibrariesPyTorch, JAX, transformersmodel
FromToConnection
1. System Foundation2. Package Managersinstall first
2. Package Managers3. Language Runtimes
3. Language Runtimes4. AI/ML Libraries
Sources

Install the toolchain

CommandWhat it does
xcode-select --installmacOS build tools and git
sudo apt install -y build-essential git curl wget unzipUbuntu or Debian base tools
wsl --install -d Ubuntu-24.04Windows: use WSL2
curl -LsSf https://astral.sh/uv/install.sh | shInstall uv
uv python install 3.12Install Python 3.12
fnm install 22 then fnm use 22Node.js 22 for TypeScript lessons
npm install -g pnpmInstall pnpm
Sources

Make an environment

TaskCode
uv venv (recommended)uv venv then source .venv/bin/activate
New project with pyproject.tomluv init my-ai-project then uv add torch numpy matplotlib
Built-in venvpython3 -m venv .venv
Activate on Windows.venv\Scripts\activate
Conda envconda create -n myproject python=3.12 then conda activate myproject
Install an extra groupuv pip install -e ".[torch,llm]"
Make a lockfileuv pip compile pyproject.toml -o requirements.lock
Install from the lockfileuv pip install -r requirements.lock
Sources

pyproject.toml with extras

[project]
name = "ai-engineering-from-scratch"
version = "0.1.0"
requires-python = ">=3.11"course minimum
dependencies = [
"numpy>=1.26",
"matplotlib>=3.8",
"jupyter>=1.0",
"scikit-learn>=1.4",
]
[project.optional-dependencies]
torch = ["torch>=2.3", "torchvision>=0.18"]uv pip install -e ".[torch]"
llm = ["anthropic>=0.39", "openai>=1.50"]uv pip install -e ".[llm]"
Sources

Check the route

CommandWhat it does
verify.py --route beginnerDefault route. Requires python and git
--route ml-foundationsAlso requires numpy
--route agent-skillsRequires python, git, node and npx
--route llm-engineering, agents, mcp, certificationRequire python and git
--show-laterAlso checks optional and later tools
[PASS], [FAIL], [LATER]Status of each probe. Exit code 1 on a FAIL
bash .../code/env_setup.shMakes .venv at the repo root and verifies it
Sources

Install PyTorch and check the GPU

nvidia-smidriver CUDA version
uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
uv pip install torch torchvision torchaudiomacOS: plain build with MPS
python -c "import torch; print(torch.version.cuda)"PyTorch CUDA version
python -c "import torch; print(torch.__version__)"install worked
which pythonmust show .venv/bin/python
Sources

VS Code settings

SettingDefaultNote
python.analysis.typeCheckingMode"basic"Catches wrong argument types before a run
editor.formatOnSavetrueBlack formats each save
black-formatter.args["--line-length", "88"]Black wraps at 88
editor.rulers[88, 120]120 marks long docstrings
notebook.output.scrollingtrueLong training output stays small
files.autoSave"afterDelay"files.autoSaveDelay is 1000
terminal.integrated.scrollback10000Lines kept in the terminal
ruff.lint.run"onSave"Ruff lints each save
Sources

Troubleshooting

SymptomCauseFix
Packages missing at runVenv not activesource .venv/bin/activate
which python shows /usr/bin/pythonGlobal installActivate, then install again
Conda env breakspip install mixed into condaConda first, pip packages last
GPU not usedPyTorch CUDA above driver CUDAPyTorch CUDA must be <= driver CUDA
Torch install fails on a Mac--index-url .../cuXXX wheelsInstall the plain build
Not installing fnm due to missing dependencies.No unzipsudo apt install -y unzip
Cannot install under Rosetta 2Terminal runs as i386arch -arm64 brew install fnm
code not found on macOSShell command not in PATH"Install 'code' command in PATH"
Sources

Silent Python bugs

independent = list(weights)assignment does not copy
grid = [[0] * 3 for _ in range(2)]not [[0] * 3] * 2
def add_good(item, bucket=None): ...never bucket=[]
hidden: list[int] = field(default_factory=lambda: [64, 32])
random.Random(seed).shuffle(order)private generator
sum(x * y for x, y in zip(a, b, strict=True))ValueError on a length mismatch
for epoch in range(2):
sizes = [len(b) for b in batches(range(10), 4)]new generator each epoch
raise ValueError(f"label must be an integer, got {text!r}") from None
if __name__ == "__main__":tests import without the demo
Sources

Questions

One env for the whole course?
No. Phases need conflicting dependencies. Use a per-phase strategy.
When conda?
For a CUDA toolkit without a system install, or on a shared cluster.
Commit .venv?
No. Add .venv/ to .gitignore. Commit pyproject.toml and the lockfile.
No CUDA on a Mac?
That is expected. MPS is the Apple GPU backend.
Why does (3, 2) with (3,) fail?
The trailing 2 and 3 differ. Use keepdims=True.
Sources

Tips

  • Run every lesson command from the repository root.
  • Fix the first failed preflight line before you read the next one.
  • Install later tools when a lesson asks for them.
  • Give encoding="utf-8" to each file open. Open CSV files with newline="".
  • Split the data before standardization. Fit statistics on the train split only.
Sources

Editor and SSH commands

CommandWhat it does
code --install-extension <id>Install one extension by ID
code --list-extensionsList installed extension IDs
ssh-keygen -t ed25519 -C "<email>"Make an SSH key
ssh-copy-id user@your-gpu-box-ipPasswordless login to the GPU box
Remote-SSH: Connect to HostOpen the remote folder as local
watch -n 1 nvidia-smiWatch the GPU in a split terminal
Sources
Original source
---
id: python-dev-environment
title: Python Dev Environment for AI
code: PD
subtitle: Install uv, make one venv per project, pin with lockfiles, check the route, set up VS Code and avoid silent Python bugs.
hue: 210
sources: phases/00-setup-and-tooling/01-dev-environment, phases/00-setup-and-tooling/06-python-environments, phases/00-setup-and-tooling/08-editor-setup, phases/00-setup-and-tooling/13-python-for-ai-engineering
source_hash: c1902990e64b40be
---

## The four-layer stack
type: architecture
from: phases/00-setup-and-tooling/01-dev-environment/docs/en.md

```arch
node | sys | 1,1 | 1. System Foundation | OS, shell, git, editor, GPU drivers | process
node | pkg | 2,1 | 2. Package Managers | uv, pnpm, cargo, juliaup | store
node | run | 3,1 | 3. Language Runtimes | Python 3.11+, Node 20+, Rust, Julia | process
node | lib | 4,1 | 4. AI/ML Libraries | PyTorch, JAX, transformers | model
edge | sys | pkg | install first
edge | pkg | run |
edge | run | lib |
```

## Install the toolchain
type: command-table
from: phases/00-setup-and-tooling/01-dev-environment/docs/en.md
span: 2

| Command | What it does |
|---|---|
| `xcode-select --install` | macOS build tools and git |
| `sudo apt install -y build-essential git curl wget unzip` | Ubuntu or Debian base tools |
| `wsl --install -d Ubuntu-24.04` | Windows: use WSL2 |
| `curl -LsSf https://astral.sh/uv/install.sh \| sh` | Install uv |
| `uv python install 3.12` | Install Python 3.12 |
| `fnm install 22` then `fnm use 22` | Node.js 22 for TypeScript lessons |
| `npm install -g pnpm` | Install pnpm |

## Make an environment
type: task-table
from: phases/00-setup-and-tooling/06-python-environments/docs/en.md
span: 2

| Task | Code |
|---|---|
| uv venv (recommended) | `uv venv` then `source .venv/bin/activate` |
| New project with pyproject.toml | `uv init my-ai-project` then `uv add torch numpy matplotlib` |
| Built-in venv | `python3 -m venv .venv` |
| Activate on Windows | `.venv\Scripts\activate` |
| Conda env | `conda create -n myproject python=3.12` then `conda activate myproject` |
| Install an extra group | `uv pip install -e ".[torch,llm]"` |
| Make a lockfile | `uv pip compile pyproject.toml -o requirements.lock` |
| Install from the lockfile | `uv pip install -r requirements.lock` |

## pyproject.toml with extras
type: annotated-code
lang: toml
from: phases/00-setup-and-tooling/06-python-environments/docs/en.md

```toml
[project]
name = "ai-engineering-from-scratch"
version = "0.1.0"
requires-python = ">=3.11"            # course minimum
dependencies = [
    "numpy>=1.26",
    "matplotlib>=3.8",
    "jupyter>=1.0",
    "scikit-learn>=1.4",
]
[project.optional-dependencies]
torch = ["torch>=2.3", "torchvision>=0.18"]   # uv pip install -e ".[torch]"
llm = ["anthropic>=0.39", "openai>=1.50"]     # uv pip install -e ".[llm]"
```

## Check the route
type: command-table
from: phases/00-setup-and-tooling/01-dev-environment/docs/en.md, phases/00-setup-and-tooling/01-dev-environment/code/verify.py, phases/00-setup-and-tooling/06-python-environments/docs/en.md, phases/00-setup-and-tooling/06-python-environments/code/env_setup.sh

| Command | What it does |
|---|---|
| `verify.py --route beginner` | Default route. Requires python and git |
| `--route ml-foundations` | Also requires numpy |
| `--route agent-skills` | Requires python, git, node and npx |
| `--route llm-engineering`, `agents`, `mcp`, `certification` | Require python and git |
| `--show-later` | Also checks optional and later tools |
| `[PASS]`, `[FAIL]`, `[LATER]` | Status of each probe. Exit code 1 on a FAIL |
| `bash .../code/env_setup.sh` | Makes `.venv` at the repo root and verifies it |

## Install PyTorch and check the GPU
type: annotated-code
lang: bash
from: phases/00-setup-and-tooling/01-dev-environment/docs/en.md, phases/00-setup-and-tooling/06-python-environments/docs/en.md

```bash
nvidia-smi                                    # driver CUDA version
uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
uv pip install torch torchvision torchaudio   # macOS: plain build with MPS
python -c "import torch; print(torch.version.cuda)"   # PyTorch CUDA version
python -c "import torch; print(torch.__version__)"    # install worked
which python                                  # must show .venv/bin/python
```

## VS Code settings
type: defaults
from: phases/00-setup-and-tooling/08-editor-setup/docs/en.md, phases/00-setup-and-tooling/08-editor-setup/code/vscode/settings.json

| Setting | Default | Note |
|---|---|---|
| `python.analysis.typeCheckingMode` | `"basic"` | Catches wrong argument types before a run |
| `editor.formatOnSave` | `true` | Black formats each save |
| `black-formatter.args` | `["--line-length", "88"]` | Black wraps at 88 |
| `editor.rulers` | `[88, 120]` | 120 marks long docstrings |
| `notebook.output.scrolling` | `true` | Long training output stays small |
| `files.autoSave` | `"afterDelay"` | `files.autoSaveDelay` is 1000 |
| `terminal.integrated.scrollback` | 10000 | Lines kept in the terminal |
| `ruff.lint.run` | `"onSave"` | Ruff lints each save |

## Troubleshooting
type: troubleshooting
from: phases/00-setup-and-tooling/01-dev-environment/docs/en.md, phases/00-setup-and-tooling/06-python-environments/docs/en.md, phases/00-setup-and-tooling/08-editor-setup/docs/en.md

| Symptom | Cause | Fix |
|---|---|---|
| Packages missing at run | Venv not active | `source .venv/bin/activate` |
| `which python` shows `/usr/bin/python` | Global install | Activate, then install again |
| Conda env breaks | `pip install` mixed into conda | Conda first, pip packages last |
| GPU not used | PyTorch CUDA above driver CUDA | PyTorch CUDA must be <= driver CUDA |
| Torch install fails on a Mac | `--index-url .../cuXXX` wheels | Install the plain build |
| `Not installing fnm due to missing dependencies.` | No `unzip` | `sudo apt install -y unzip` |
| `Cannot install under Rosetta 2` | Terminal runs as `i386` | `arch -arm64 brew install fnm` |
| `code` not found on macOS | Shell command not in PATH | "Install 'code' command in PATH" |

## Silent Python bugs
type: annotated-code
lang: python
from: phases/00-setup-and-tooling/13-python-for-ai-engineering/docs/en.md, phases/00-setup-and-tooling/13-python-for-ai-engineering/code/main.py

```python
independent = list(weights)                  # assignment does not copy
grid = [[0] * 3 for _ in range(2)]           # not [[0] * 3] * 2
def add_good(item, bucket=None): ...         # never bucket=[]
hidden: list[int] = field(default_factory=lambda: [64, 32])
random.Random(seed).shuffle(order)           # private generator
sum(x * y for x, y in zip(a, b, strict=True))  # ValueError on a length mismatch
for epoch in range(2):
    sizes = [len(b) for b in batches(range(10), 4)]  # new generator each epoch
raise ValueError(f"label must be an integer, got {text!r}") from None
if __name__ == "__main__":                   # tests import without the demo
```

## Questions
type: qa
from: phases/00-setup-and-tooling/06-python-environments/docs/en.md, phases/00-setup-and-tooling/13-python-for-ai-engineering/docs/en.md, phases/00-setup-and-tooling/01-dev-environment/docs/en.md

- **One env for the whole course?** No. Phases need conflicting dependencies. Use a per-phase strategy.
- **When conda?** For a CUDA toolkit without a system install, or on a shared cluster.
- **Commit `.venv`?** No. Add `.venv/` to `.gitignore`. Commit `pyproject.toml` and the lockfile.
- **No CUDA on a Mac?** That is expected. MPS is the Apple GPU backend.
- **Why does `(3, 2)` with `(3,)` fail?** The trailing 2 and 3 differ. Use `keepdims=True`.

## Tips
type: tips
from: phases/00-setup-and-tooling/01-dev-environment/docs/en.md, phases/00-setup-and-tooling/06-python-environments/docs/en.md, phases/00-setup-and-tooling/13-python-for-ai-engineering/docs/en.md

- Run every lesson command from the repository root.
- Fix the first failed preflight line before you read the next one.
- Install later tools when a lesson asks for them.
- Give `encoding="utf-8"` to each file open. Open CSV files with `newline=""`.
- Split the data before standardization. Fit statistics on the train split only.

## Editor and SSH commands
type: command-table
from: phases/00-setup-and-tooling/08-editor-setup/docs/en.md

| Command | What it does |
|---|---|
| `code --install-extension <id>` | Install one extension by ID |
| `code --list-extensions` | List installed extension IDs |
| `ssh-keygen -t ed25519 -C "<email>"` | Make an SSH key |
| `ssh-copy-id user@your-gpu-box-ip` | Passwordless login to the GPU box |
| `Remote-SSH: Connect to Host` | Open the remote folder as local |
| `watch -n 1 nvidia-smi` | Watch the GPU in a split terminal |
Code and artifacts 1
What you take away

Saved in your notebook on this device.

Sources and limits

Reading checkpoints are self-reported. Test results are recorded separately and apply to the executed cases.

AI Engineering from Scratch · 3f9715c · MIT

Download this file ↓