## TL;DR
Quantized FAISS indexes (IVF, PQ, and friends) must be trained on representative vectors before they accept data; calling `add` first raises "Index not trained." Train on a sample of your vectors with `index.train(sample)`, then add the full set.

```text
faiss 'Index not trained' on add
```

## Use this when
- `index.add()` raises Index not trained
- An agent constructs an IVF/PQ index and inserts immediately
- A deserialized index was saved before training

## Not for this skill when
- Add fails on dimension (thats a shape mismatch)
- GPU index creation fails (thats the GPU build)
- Search returns nothing on a trained index (thats a data problem)

## Steps

1. Confirm the index type needs training:

```python
print(index.is_trained)
```
Expected output: `False`. Flat indexes (IndexFlatL2) are always trained; IVF/PQ/IVFPQ need an explicit train step.

2. Train on a representative sample before adding:

```python
import numpy as np
sample = vectors[np.random.choice(len(vectors), min(100000, len(vectors)), replace=False)]
index.train(sample.astype(np.float32))
print(index.is_trained)
```
Expected output: `True`. Training learns the cluster centroids; the sample should look like the data you will add.

3. Now add the full dataset:

```python
index.add(vectors.astype(np.float32))
print(index.ntotal)
```
Expected output: `ntotal` equals your vector count. Train once, add as many times as you like after.

4. If you persist indexes, save after training:

```python
faiss.write_index(index, "index.faiss")
```
Expected output: the file on disk holds a trained index. Saving before train bakes the untrained state in, and every load reproduces the error.

## Variant phrasings

### IndexIVFPQ not trained after loading from disk
It was saved untrained. Retrain from a sample and re-save; there is no way to recover training from the file.

### training is slow on huge samples
Use 10k-100k vectors; more barely improves centroids. Also check nlist: too many clusters for the sample size trains poorly.

## Why it happens
FAISS splits index types into exact (flat, no training) and quantized (IVF/PQ, needs training to learn the codebook). The constructor doesnt train; it just allocates. Agent code usually copies the constructor line from docs and jumps straight to add, skipping the train call that the docs show two paragraphs later.

## Edge cases
- float16 vectors must be cast to float32 for train and add; FAISS trains in float32.
- Training on a sample from a different distribution than the added data gives bad recall; sample from the real data.
- `index.train` on an already-trained index re-trains and invalidates previously added vectors; dont call it twice.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_ZzosfvxVxXe5VSc-NxdBng
