FAISS flat IP index with cosine similarity

FAISS is a library from Meta that does fast similarity search over dense vectors. For a per-video index with a few hundred chunks, the simplest flavor (IndexFlatIP) is perfect. It does an exact inner product across every vector.

FAISS does not have a built-in cosine similarity index, but there is a standard trick: if you L2-normalize every vector before indexing, then inner product is exactly cosine similarity. One division, one flag, done.

embedder.py
python
import faiss


def build_index(chunks: list[dict],
                client=None) -> tuple[faiss.Index, list[dict]]:
    """Build a FAISS inner-product index (cosine after normalization)."""
    texts = [c["text"] for c in chunks]
    embeddings = get_embeddings(texts)

    # L2 normalize so inner product == cosine similarity
    norms = np.linalg.norm(embeddings, axis=1, keepdims=True)
    embeddings = embeddings / (norms + 1e-10)

    dim = embeddings.shape[1]
    index = faiss.IndexFlatIP(dim)
    index.add(embeddings)

    return index, chunks

Normalize every vector to unit length, then add to an inner-product index. The tiny epsilon (1e-10) prevents division by zero on pathological vectors.

embedder.py
python
def search_index(query: str, index: faiss.Index,
                 chunks: list[dict], client=None,
                 top_k: int = 5) -> list[dict]:
    """Search the FAISS index for chunks most relevant to query."""
    q_emb = get_embeddings([query])
    q_emb = q_emb / (np.linalg.norm(q_emb) + 1e-10)

    scores, indices = index.search(q_emb, top_k)

    results = []
    for score, idx in zip(scores[0], indices[0]):
        if idx < len(chunks):
            chunk = chunks[idx].copy()
            chunk["score"] = float(score)
            results.append(chunk)
    return results

The query goes through the same embedding model and the same normalization. FAISS returns the top_k matches with their similarity scores, and we attach those scores to the returned chunks.

Ordering exercise: Order the indexing steps

Loading practice…

Quiz: Quiz

Loading practice…