# Switching Immich Facial Recognition Models

> How to switch between `antelopev2`, `buffalo_l`, and `buffalo_s`
> facial recognition models — and the critical gotcha that WILL bite you.

## When to switch

- **antelopev2 → buffalo_l**: Family members with similar faces are getting
  merged/confused. buffalo_l is significantly better at distinguishing
  similar faces (larger model, better embeddings).
- **buffalo_l → buffalo_s**: Running low on VRAM (buffalo_s is ~50MB vs
  buffalo_l's ~182MB). Trade quality for memory.
- **Reverse (experimental)**: If buffalo_l somehow performs worse for your
  specific dataset (unlikely but possible).

## Procedure

### 1. Set the model in .env

```bash
# /opt/immich/.env
MACHINE_LEARNING_FACIAL_RECOGNITION_MODEL_NAME=buffalo_l
```

Valid values: `antelopev2`, `buffalo_l`, `buffalo_s`.

### 2. Restart the ML container

```bash
cd /opt/immich
sudo docker compose up -d immich-machine-learning
```

The new model downloads automatically on first use (~182 MB for buffalo_l).
To pre-cache and avoid the download-on-first-request delay, see
`references/pre-caching-ml-models.md`.

### 3. Check the model is in place

```bash
sudo docker exec immich_machine_learning find /cache/facial-recognition -name '*.onnx'
# Should show: /cache/facial-recognition/buffalo_l/detection/model.onnx
#              /cache/facial-recognition/buffalo_l/recognition/model.onnx
```

## 🚨 CRITICAL PITFALL: Model switch does NOT re-process existing faces

**Changing `MACHINE_LEARNING_FACIAL_RECOGNITION_MODEL_NAME` in `.env` and
restarting the ML container only changes which model is loaded for FUTURE
face detection.** It does NOT touch the existing face embeddings already
stored in the database.

Old `antelopev2` embeddings remain and Immich will keep using them — meaning
face confusion persists until you explicitly re-run face detection.

### The fix: Re-run face detection

**From the UI (easiest):**

1. Go to Immich admin → **Administration → Jobs → Face Detection**
2. Click **All** (NOT "Missing" — "Missing" only processes photos without
   ANY embedding, and your old antelopev2 photos already have embeddings)
3. Wait — on GPU this takes 1-2 hours for ~23K photos

**Via the API:**

```bash
# Login
LOGIN=$(curl -s -X POST http://localhost:2283/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@example.com","password":"your-password"}')
TOK=*** -e "console.log(JSON.parse(process.argv[1]).accessToken)" -- "$LOGIN")

# Trigger face detection with force=true to re-process all assets
curl -s -X PUT "http://localhost:2283/api/jobs/faceDetection" \
  -H "Authorization: Bearer $TOK" \
  -H "Content-Type: application/json" \
  -d '{"command":"start","force":true}'

# Trigger facial recognition too
curl -s -X PUT "http://localhost:2283/api/jobs/facialRecognition" \
  -H "Authorization: Bearer $TOK" \
  -H "Content-Type: application/json" \
  -d '{"command":"start","force":true}'
```

### What happens after re-processing

- Old face clusters (People) remain but get new embeddings
- Faces that were incorrectly merged under `antelopev2` will get separate
  clusters under `buffalo_l`
- You may need to manually clean up: remove wrong photos from a person's
  page in the UI (buffalo_l won't auto-unmerge what antelopev2 merged —
  it just won't merge new ones incorrectly)

### How to know it worked

```bash
# ML container should show facial recognition activity
sudo docker logs immich_machine_learning --tail 20 | head

# GPU should be actively processing
nvidia-smi
# Expect: ~1200 MiB VRAM, 10-40% utilization

# Server logs should show face detection activity
sudo docker logs immich_server --tail 50 | grep -i 'detect\|face\|person'
```

## Model comparison

| Model | Size | Quality | VRAM (loaded) | Best for |
|-------|------|---------|---------------|----------|
| antelopev2 | ~100 MB | Moderate | ~100 MB | Low-resource, not picky about false merges |
| buffalo_l | ~182 MB | High | ~182 MB | **Default choice** — best accuracy, distinguishing similar faces |
| buffalo_s | ~50 MB | Lower | ~50 MB | Extreme VRAM constraints |

## Internal ML URL

The ML container runs as `immich_machine_learning` on the Docker network.
The default URL Immich uses is:

```
http://immich-machine-learning:3003
```

This is auto-discovered via Docker DNS. If the "Machine Learning URL" field
in Immich admin settings is blank, it's using this default — which is
correct when ML runs on the same Docker host. Only fill it in when running
ML on a separate machine.
