How to Use FAISS or ChromaDB for Vector Storage in the AI Agent Book
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, 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 file handles FAISS index lifecycle management with lazy import guards to handle environments where the package is unavailable:
try:
import faiss
except ImportError: # pragma: no cover
faiss = None
When initializing a new index, the system creates a flat L2 distance index:
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:
# 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, the client initialization accepts a path configuration for persistent storage:
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:
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:
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:
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 for FAISS and chapter9/gaia-experience/AWorld/tests/memory/utils.py for ChromaDB.
# 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]}")
# 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.pyinstantiates either FAISS or ChromaDB based on theproviderconfiguration field. - FAISS uses
IndexFlatL2for in-memory similarity search with binary persistence viafaiss.write_indexandfaiss.read_index. - ChromaDB leverages
PersistentClientwith collections configured for cosine similarity, storing both embeddings and source documents. - Both backends implement identical
add_documentsandqueryinterfaces, allowing seamless backend migration without application code changes. - Test implementations in
test_kb_topk_zero.pyandtests/memory/utils.pyvalidate 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →