Local vector search lets a RAG prototype look up approved text without running a separate database service. In LangChain, the FAISS integration wraps an in-process FAISS index so embedded Document objects can be searched, saved, and exposed as a retriever.
FAISS stores numeric vectors, while LangChain keeps the matching documents and metadata in a docstore. The documented FAISS integration path uses langchain-community with faiss-cpu; the CPU package is enough for a local smoke test and avoids a model-provider API key when paired with a small embedding class.
Saved FAISS folders contain both the index and a pickle-backed docstore. Load only indexes created by your application or a trusted build pipeline, then run one similarity search and one retriever call before wiring the store into a RAG chain.
Use a virtual environment so the FAISS wheel and LangChain integration packages stay inside the project.
Related: How to create a virtual environment for LangChain
$ python3 -m pip install -U langchain-community faiss-cpu
Current langchain-community releases may print a sunset warning when FAISS is imported. The official FAISS integration page still documents this package path; test any standalone replacement before changing production code.
Related: How to install LangChain with pip
from langchain_community.vectorstores import FAISS from langchain_core.documents import Document from langchain_core.embeddings import Embeddings class KeywordEmbeddings(Embeddings): vocabulary = ["faiss", "index", "retrieval", "metadata", "save", "reuse"] def _embed(self, text: str) -> list[float]: lowered = text.lower() return [float(lowered.count(term)) for term in self.vocabulary] def embed_documents(self, texts: list[str]) -> list[list[float]]: return [self._embed(text) for text in texts] def embed_query(self, text: str) -> list[float]: return self._embed(text) documents = [ Document( page_content="Build the FAISS index from embedded LangChain documents.", metadata={"source": "indexing"}, ), Document( page_content="Use the retriever view when a RAG chain needs documents.", metadata={"source": "retrieval"}, ), Document( page_content="Save the FAISS index and docstore before reuse.", metadata={"source": "persistence"}, ), Document( page_content="Attach metadata filters before narrowing search results.", metadata={"source": "metadata"}, ), ] embeddings = KeywordEmbeddings() vector_store = FAISS.from_documents(documents, embeddings) print(f"created index documents: {vector_store.index.ntotal}") match = vector_store.similarity_search("FAISS index", k=1)[0] print(f"best match: {match.page_content}") vector_store.save_local("faiss_index") loaded_store = FAISS.load_local( "faiss_index", embeddings, allow_dangerous_deserialization=True, ) loaded_match = loaded_store.similarity_search("save index for reuse", k=1)[0] print(f"loaded match: {loaded_match.page_content}") retriever = loaded_store.as_retriever(search_kwargs={"k": 1}) retrieved = retriever.invoke("retrieval documents")[0] print(f"retriever match: {retrieved.page_content}")
The local KeywordEmbeddings class makes the smoke test deterministic and keeps text inside the process. Replace it with OpenAI, Ollama, Sentence Transformers, or another embedding integration after the FAISS store shape works.
FAISS.load_local() uses allow_dangerous_deserialization=True because the docstore is pickle-backed. Do not load a FAISS folder from an untrusted user upload or unknown build artifact.
$ python3 faiss_store_demo.py created index documents: 4 best match: Build the FAISS index from embedded LangChain documents. loaded match: Save the FAISS index and docstore before reuse. retriever match: Use the retriever view when a RAG chain needs documents.
If Python prints a langchain-community sunset warning before the output, the warning is on stderr and does not change the printed FAISS smoke-test results.
$ ls faiss_index index.faiss index.pkl
index.faiss stores the vector index. index.pkl stores the LangChain docstore and ID mapping.
$ rm -r faiss_index faiss_store_demo.py