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.

Steps to build a FAISS vector store in LangChain:

  1. Open an activated Python project environment.

    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

  2. Install the LangChain community integration and FAISS CPU package.
    $ 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

  3. Create faiss_store_demo.py with a local embedding class, a FAISS vector store, a save/load check, and a retriever call.
    faiss_store_demo.py
    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.

  4. Run the script and confirm the index, reload, and retriever results.
    $ 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.

  5. Check the saved FAISS files.
    $ ls faiss_index
    index.faiss
    index.pkl

    index.faiss stores the vector index. index.pkl stores the LangChain docstore and ID mapping.

  6. Remove the temporary script and local index after the smoke test.
    $ rm -r faiss_index faiss_store_demo.py