LESSON 33 ยท VECTOR DATABASES

FAISS

FAISS is a library for efficient similarity search and clustering of dense vectors. It is a powerful building block for semantic search, recommendation systems, and retrieval pipelines built with Python.

30 min readโ€ขBeginnerโ€ขGenerative AI

By the end of this lesson, you will be able to:

  • Explain what FAISS is and what problem it solves.
  • Create a simple FAISS index with Python.
  • Add vectors and search for their nearest neighbors.
  • Understand the difference between exact and approximate search.
  • Explain why FAISS is useful in semantic search and RAG prototypes.
  • Recognize when FAISS is a good fit and when a full vector database may be better.
1

What Is FAISS?

FAISS stands for Facebook AI Similarity Search. It is an open-source library designed to make similarity search over dense vectors efficient.

INPUTDense vectors

Numerical representations produced by an embedding model.

โ†’
FAISSIndex + search

Organizes vectors and finds nearby vectors efficiently.

โ†’
OUTPUTNearest neighbors

Returns IDs and distances for the best matches.

Important:FAISS is primarily a similarity-search library. It is not the same thing as a complete, hosted vector database with built-in application services.
2

Why Do We Need FAISS?

Suppose an embedding model converts every document chunk into a vector. A simple approach would compare a query vector with every stored vector. That works for small experiments, but repeated brute-force comparisons become expensive as the collection grows.

SMALL EXPERIMENT

Compare everything

Store vectors in memory and calculate a similarity or distance against every vector.

FAISS

Use an index

Choose an index structure designed for efficient nearest-neighbor search.

Mental model: An index is a data structure that helps you search a large collection without treating every query like a completely new full scan.
3

How FAISS Search Works

DocumentsText chunks
โ†’
EmbeddingsDense vectors
โ†’
FAISS IndexStore + organize vectors
โ†’
Query VectorSearch input
โ†’
Top-kNearest results

The application first creates vectors, adds them to an index, and later asks the index to find the nearest vectors to a query vector. FAISS returns distances and the integer positions of the matching vectors.

4

Exact Search with IndexFlatL2

One of the easiest FAISS indexes to understand is IndexFlatL2. It uses Euclidean distance and performs an exact nearest-neighbor search.

INDEXIndexFlatL2

Simple, exact L2-distance search.

GOOD FORLearning & baselines

Useful when you want a clear reference implementation.

TRADE-OFFMore work at scale

Exact search can become expensive as the collection grows.

Remember:Cosine similarity and L2 distance are different metrics. If your application is designed around cosine similarity, make sure your vectors and index choice match that requirement.
5

Python: Build a FAISS Index

This example creates three-dimensional vectors and searches for the nearest two vectors.

</> Python
import numpy as np
import faiss

vectors = np.array([
    [1.0, 0.0, 0.0],
    [0.9, 0.1, 0.0],
    [0.0, 1.0, 0.0],
    [0.0, 0.9, 0.1],
], dtype="float32")

index = faiss.IndexFlatL2(vectors.shape[1])
index.add(vectors)

query = np.array([[0.95, 0.05, 0.0]], dtype="float32")

distances, indices = index.search(query, k=2)

print("Distances:", distances)
print("Vector IDs:", indices)
Expected idea:The first two vectors are close to the query, so their IDs should appear among the top results.
6

What Does k Mean?

The k value tells FAISS how many nearest neighbors to return.

k = 1Best match

Useful when only one candidate is needed.

k = 3Top three

Useful when the application needs several candidates.

k = 10Broader retrieval

Useful when a later reranking or filtering stage will narrow the results.

RAG connection: A retrieval pipeline often fetches more than the final number of context chunks, then applies filtering or reranking before sending context to the LLM.
7

FAISS and Cosine Similarity

FAISS can work with different distance strategies. A common pattern for cosine-style comparison is to normalize vectors and use an inner-product index.

</> Python
import numpy as np
import faiss

vectors = np.array([
    [1.0, 0.0],
    [0.8, 0.2],
    [0.0, 1.0],
], dtype="float32")

faiss.normalize_L2(vectors)

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

query = np.array([[0.9, 0.1]], dtype="float32")
faiss.normalize_L2(query)

scores, indices = index.search(query, k=2)

print("Similarity scores:", scores)
print("Vector IDs:", indices)
Why normalize?After L2 normalization, the inner product corresponds to cosine similarity. This lets the search ranking focus on vector direction rather than magnitude.
8

FAISS Is an Index, Not Your Whole Data Model

FAISS gives you efficient vector search, but your application still needs a way to map returned integer IDs back to documents, chunks, users, or metadata.

FAISSVector index

Vector positions and search results.

YOUR APPMetadata store

Document ID, title, source, tenant, permissions, timestamps, and other fields.

RETRIEVALJoin the results

Use the returned IDs to fetch the actual content and metadata.

Design principle: Keep a clear mapping between every vector position and the source record it represents.
9

Exact vs Approximate Search

EXACT

High confidence baseline

Search the full collection according to the selected metric. Simple to reason about, but can require more computation.

APPROXIMATE

Trade some recall for speed

Use an approximate nearest-neighbor structure to reduce search work.

MEASURE

Benchmark the workload

Compare recall, latency, memory use, and cost on representative queries.

FAISS includes several index families, each with different performance and memory trade-offs. The right choice depends on collection size, vector dimensionality, latency targets, and acceptable recall.

10

FAISS in Semantic Search

User queryโ€œHow can I reset my password?โ€
โ†’
EmbeddingQuery vector
โ†’
FAISSNearest-neighbor search
โ†’
DocumentsRelevant chunks

FAISS does not understand the text itself. The embedding model creates the representation; FAISS searches those numerical representations.

11

FAISS in a RAG Pipeline

1. ChunkSplit documents
โ†’
2. EmbedCreate vectors
โ†’
3. IndexAdd vectors to FAISS
โ†’
4. RetrieveSearch top-k
โ†’
5. GenerateLLM uses context
Key idea:FAISS is the retrieval component in this simplified architecture. It does not generate the final answer; the LLM does that after receiving retrieved context.
12

When FAISS Is a Good Choice

Local prototypesBuild and test retrieval without running a separate database service.
Research workflowsExperiment with index types, distances, and retrieval behavior.
Python applicationsIntegrate vector search directly into a Python process.
Controlled deploymentsUseful when your application owns persistence and infrastructure.
13

When a Vector Database May Be Better

A full vector database can be a better fit when your application needs capabilities around the index itself.

Managed persistenceCollections, backups, replication, and service operations.
Metadata filteringRich filtering and retrieval controls alongside vector search.
Multi-user workloadsShared infrastructure for concurrent applications and teams.
Do not over-engineer:If your dataset is small and a local index is sufficient, FAISS can be a practical solution. Choose infrastructure from measured requirements rather than from product popularity.
14

Common Mistakes

1. Forgetting vector shape

The index dimension must match the dimensionality of the vectors you add and search.

2. Mixing distance concepts

Do not treat L2 distance and cosine similarity as interchangeable without understanding the transformation.

3. Losing the ID mapping

A returned FAISS position is only useful if your application can map it to the source record.

4. Assuming top-k means relevant

Nearest neighbors are candidates. Evaluate whether they actually answer your retrieval task.

HANDS-ON PRACTICE

Build a Tiny Semantic Search Index

Create a small FAISS index and use it to retrieve the most similar sentence vectors.

  1. Install FAISS in a Python environment.
  2. Create at least five small vectors representing different sentences.
  3. Build an index with the correct vector dimension.
  4. Search with a new query vector using k=3.
  5. Map the returned IDs back to the original sentences.
  6. Try a different query and compare the ranking.
Challenge: Add normalized vectors and compare IndexFlatL2 with an inner-product index. Explain why the rankings may differ.

Quick Quiz

1. What is FAISS mainly designed for?

Efficient similarity search and clustering of dense vectors.

2. What does k control?

The number of nearest neighbors returned for a query.

3. Does FAISS generate LLM answers?

No. It searches vector representations; an application or LLM uses the retrieved content afterward.

4. Why normalize vectors for cosine-style search with inner product?

With unit-length vectors, inner product corresponds to cosine similarity.

30-Second Recap

EmbeddingsMeaning โ†’ vectors
โ†’
FAISSBuild an index
โ†’
SearchFind neighbors
โ†’
Top-kReturn candidates
โ†’
RAGUse context

Key Takeaways

  • FAISS is a library for efficient similarity search and clustering of dense vectors.
  • An index organizes vectors so nearest-neighbor search can be performed efficiently.
  • IndexFlatL2 is a useful exact-search baseline using L2 distance.
  • Normalized vectors plus inner product are a common way to implement cosine-style search.
  • FAISS returns vector positions and distances; your application must map those results to real records and metadata.
  • FAISS is excellent for many local and Python retrieval workloads, while a full vector database may be preferable for broader operational needs.