Embeddings can be stored or temporarily cached to avoid recalculation.
Caching embeddings can be done using CacheBackedEmbeddings. A cache-backed embedder is a wrapper around an embedder that caches embeddings in a key-value store. The text is hashed, and the hash is used as a key in the cache.
from dotenv import load_dotenv
load_dotenv(override=True)
False
Check and create the ./cache/ directory for persistent storage.
import os
os.makedirs("./cache/", exist_ok=True)
print(os.path.exists("./cache/")) # Check if the directory exists
print(os.access("./cache/", os.W_OK)) # Check if the directory is writable
True
True
Using Embeddings with LocalFileStore (Persistent Storage)
The primary supported method for initializing CacheBackedEmbeddings is from_bytes_store.
It accepts the following parameters:
underlying_embeddings: The embedder is used for generating embeddings.
document_embedding_cache: One of the ByteStore implementations for caching document embeddings.
namespace: (Optional, default is "") A namespace is used for the document cache. This is utilized to avoid conflicts with other caches. For example, set it to the name of the embedding model being used.
Note: It is important to set the namespace parameter to avoid conflicts when the same text is embedded using different embedding models.
First, let's look at an example of storing embeddings using the local file system and retrieving them with the FAISS vector store.
from langchain.storage import LocalFileStore
from langchain_openai import OpenAIEmbeddings
from langchain.embeddings import CacheBackedEmbeddings
from langchain_community.vectorstores.faiss import FAISS
# Configure basic embeddings using OpenAI embeddings
underlying_embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# Set up a local file storage
store = LocalFileStore("./cache/")
# Create embeddings with caching support
cached_embedder = CacheBackedEmbeddings.from_bytes_store(
underlying_embeddings=underlying_embeddings,
document_embedding_cache=store,
namespace=underlying_embeddings.model, # Create a cache-backed embedder using the base embedding and storage
)
The cache is empty prior to embedding
list(store.yield_keys())
[]
Load the document, split it into chunks, embed each chunk and load it into the vector store.
from langchain.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
raw_documents = TextLoader("./data/state_of_the_union.txt", encoding="utf-8").load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
documents = text_splitter.split_documents(raw_documents)
Create FAISS database from documents.
%time db = FAISS.from_documents(documents, cached_embedder)
CPU times: user 105 ms, sys: 14.3 ms, total: 119 ms
Wall time: 1.49 s
If we try to create the vector store again, it'll be much faster since it does not need to re-compute any embeddings.