# How to Use FAISS or ChromaDB for Vector Storage in the AI Agent Book

> Learn to use FAISS or ChromaDB for vector storage in the AI Agent Book. Explore pluggable architecture for easy switching between local and client-server options.

- Repository: [Bojie Li/ai-agent-book](https://github.com/bojieli/ai-agent-book)
- Tags: how-to-guide
- Published: 2026-08-22

---

**The AI Agent Book implements a pluggable vector storage architecture that abstracts FAISS and ChromaDB behind a unified factory interface, allowing developers to switch between local in-process indexing and persistent client-server storage by changing a single configuration field.**

The `bojieli/ai-agent-book` repository provides a production-ready vector storage layer designed for AI agent memory systems. Its abstraction layer enables seamless swapping between **FAISS** for high-speed local retrieval and **ChromaDB** for scalable persistent storage without modifying application logic.

## Architecture and Factory Pattern

The vector storage system uses a factory pattern to instantiate the appropriate backend based on runtime configuration. In [`chapter9/gaia-experience/AWorld/aworld/memory/vector/factory.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter9/gaia-experience/AWorld/aworld/memory/vector/factory.py), the system reads the `vector_db_config.provider` field and returns either a `FaissVectorDB` or `ChromaVectorDB` instance. Both classes implement identical methods—`add_documents`, `query`, `save`, and `load`—ensuring the rest of the codebase remains agnostic to the underlying storage engine.

## FAISS Implementation for Local Vector Storage

The FAISS backend provides in-process vector indexing ideal for single-node deployments requiring fast similarity search without external dependencies.

### Index Initialization and Persistence

The [`knowledge_base.py`](https://github.com/bojieli/ai-agent-book/blob/main/knowledge_base.py) file handles FAISS index lifecycle management with lazy import guards to handle environments where the package is unavailable:

```python
try:
    import faiss
except ImportError:  # pragma: no cover

    faiss = None

```

When initializing a new index, the system creates a flat L2 distance index:

```python
self.index = faiss.IndexFlatL2(self.embedding_dim)

```

Persistence is managed through binary serialization to disk. The index is saved to `<index_path>/faiss.index` using `faiss.write_index` and loaded via `faiss.read_index`:

```python

# Loading

self.index = faiss.read_index(index_file)

# Saving

faiss.write_index(self.index, index_file)

```

### Adding and Querying Vectors

Vectors are added directly to the index using `self.index.add()`, where embeddings are stored as contiguous float32 arrays. Retrieval uses `self.index.search()` to return the top-k nearest neighbor indices and distances, which are then mapped back to metadata stored in parallel Python dictionaries.

## ChromaDB Implementation for Persistent Storage

The ChromaDB backend supports multi-process persistence and HTTP-based client-server architectures, making it suitable for distributed agent systems.

### Client Configuration and Collections

In [`chapter9/gaia-experience/AWorld/aworld/memory/vector/dbs/chroma.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter9/gaia-experience/AWorld/aworld/memory/vector/dbs/chroma.py), the client initialization accepts a path configuration for persistent storage:

```python
self.client = chromadb.PersistentClient(path=config.get('chroma_data_path'))

```

Collections are created or retrieved with explicit distance metric configuration. The implementation uses cosine similarity by setting the `hnsw:space` metadata:

```python
self.collection = self.client.get_or_create_collection(
    name=self.collection_name,
    metadata={"hnsw:space": "cosine"}
)

```

### Document Storage and Retrieval

Documents are stored with their raw text, embeddings, and arbitrary metadata dictionaries. The `add` method batches inserts for efficiency:

```python
self.collection.add(
    ids=ids,
    embeddings=vectors,
    documents=texts,
    metadatas=metadata_dicts,
)

```

Query operations return normalized similarity scores. The implementation remaps ChromaDB's cosine distance range `[0, 2]` to `[0, 1]` for intuitive interpretation, where higher values indicate greater similarity:

```python
results = self.collection.query(
    query_embeddings=query_vectors,
    n_results=top_k,
    include=["documents", "metadatas", "distances"]
)

```

## Configuration and Provider Selection

Switching between backends requires only modifying the configuration dictionary passed to the factory. Set `vector_db_config.provider` to `"faiss"` for local file-based storage or `"chroma"` for persistent client mode. Both implementations expose the same interface defined in the vector storage base class, ensuring zero code changes in the agent logic when migrating between single-node and distributed deployments.

## Practical Implementation Examples

The following examples demonstrate the exact patterns used in the repository's test suites, including [`chapter9/gaia-experience/test_kb_topk_zero.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter9/gaia-experience/test_kb_topk_zero.py) for FAISS and [`chapter9/gaia-experience/AWorld/tests/memory/utils.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter9/gaia-experience/AWorld/tests/memory/utils.py) for ChromaDB.

```python

# FAISS Example: Local Vector Index

from pathlib import Path
import numpy as np
import faiss

# Initialize flat L2 index with 384-dimension embeddings

dim = 384
index = faiss.IndexFlatL2(dim)

# Add random example vectors

vectors = np.random.random((5, dim)).astype('float32')
index.add(vectors)

# Persist to disk

index_path = Path("./faiss_storage")
index_path.mkdir(exist_ok=True)
faiss.write_index(index, str(index_path / "faiss.index"))

# Query for top-3 neighbors

query = np.random.random((1, dim)).astype('float32')
distances, ids = index.search(query, k=3)
print(f"Nearest IDs: {ids[0]}")

```

```python

# ChromaDB Example: Persistent Client

import chromadb
import numpy as np

# Create persistent client

client = chromadb.PersistentClient(path="./chroma_db")

# Initialize collection with cosine similarity

collection = client.get_or_create_collection(
    name="agent_memory",
    metadata={"hnsw:space": "cosine"}
)

# Store documents with embeddings

texts = ["Project requirements", "Meeting notes", "Code review"]
embeddings = np.random.random((3, 384)).astype('float32').tolist()
ids = [f"doc_{i}" for i in range(3)]

collection.add(
    ids=ids,
    documents=texts,
    embeddings=embeddings
)

# Query with normalization remapped to [0,1]

query_vec = np.random.random((1, 384)).astype('float32').tolist()
results = collection.query(
    query_embeddings=query_vec,
    n_results=2,
    include=["documents", "distances"]
)

```

## Summary

- The **factory pattern** in [`factory.py`](https://github.com/bojieli/ai-agent-book/blob/main/factory.py) instantiates either FAISS or ChromaDB based on the `provider` configuration field.
- **FAISS** uses `IndexFlatL2` for in-memory similarity search with binary persistence via `faiss.write_index` and `faiss.read_index`.
- **ChromaDB** leverages `PersistentClient` with collections configured for cosine similarity, storing both embeddings and source documents.
- Both backends implement identical `add_documents` and `query` interfaces, allowing seamless backend migration without application code changes.
- Test implementations in [`test_kb_topk_zero.py`](https://github.com/bojieli/ai-agent-book/blob/main/test_kb_topk_zero.py) and [`tests/memory/utils.py`](https://github.com/bojieli/ai-agent-book/blob/main/tests/memory/utils.py) validate both storage engines against the same retrieval specifications.

## Frequently Asked Questions

### How do I choose between FAISS and ChromaDB for my agent?

Select **FAISS** when building single-process agents requiring maximum query throughput with minimal latency, as the index resides entirely in memory. Choose **ChromaDB** when agents must share memory across multiple processes or persist state between restarts, as it provides ACID-compliant storage and HTTP client capabilities.

### Can I migrate existing vectors from FAISS to ChromaDB?

Yes. Because both implementations adhere to the same interface, you can extract vectors from FAISS using `index.reconstruct_n()` or iterate over stored metadata, then batch-insert them into ChromaDB using the `collection.add()` method with the original IDs preserved to maintain referential integrity.

### What embedding dimensions are supported?

The storage layer is dimension-agnostic. The FAISS implementation initializes `IndexFlatL2` with `self.embedding_dim` passed during construction, while ChromaDB accepts any embedding length provided all vectors in a collection share the same dimensionality. The repository examples typically use 384-dimensional vectors compatible with all-MiniLM-L6-v2 encoders.

### Does the FAISS implementation support incremental updates?

Yes. The [`knowledge_base.py`](https://github.com/bojieli/ai-agent-book/blob/main/knowledge_base.py) implementation supports incremental indexing by calling `self.index.add()` with new vectors after initial creation. When persisting, `faiss.write_index` serializes the complete updated index, including all previously stored and newly added vectors, to the filesystem.