LangChain Hands-on · Module 2 · Lab 09

Vector Stores

⏱ 20 min + hands-on🎯 Beginner🖼 2 diagrams🧪 2 live demos🐍 Python code

Comparing a question with every chunk one by one (Lab 08) is fine for 5 FAQs, not for 5 million chunks. A vector store is a database built for this: it keeps the vector, the text and the metadata together and finds the nearest chunks in milliseconds. In this lab you use three of them: in-memory, FAISS (a file on disk) and Chroma (a small local database).

In this session

  • What a vector store keeps: vector + text + metadata
  • InMemoryVectorStore for learning
  • FAISS: fast, save and load from disk
  • Chroma: persistent, metadata filters, delete
  • Score direction: similarity vs distance
  • MMR: relevant and diverse

01The big idea: a library index for meanings

📚

Think of a library catalogue. Instead of reading every book, you look up the catalogue and go straight to the right shelf. A vector store is a catalogue sorted by meaning: you give it the question’s vector and it returns the nearest chunks, with their labels (metadata) so you can filter, for example only the “UPI” shelf.

Chunksfrom Lab 07embed_documentsLab 08Vector storevector + text + metadatasimilarity_searchquestion → top-k
Indexing happens once; search happens for every question.
StoreTypeGood for
InMemoryVectorStoreRAMlearning, small demos
FAISSlocal filefast, offline, save/load
Chromalocal DBpersistent, metadata filters, delete by id
Pinecone, Qdrant, Weaviate, pgvector, Azure AI Searchcloudproduction, millions of chunks, many users

02Search, scores, filters and MMR

InMemory / Chroma (cosine)• score = similarity• HIGHER = more similar• range roughly 0 to 1FAISS (default L2)• score = distance• LOWER = more similar• 0 = identical
The classic confusion: always check whether your store returns similarity or distance.
OperationCode
search top-kstore.similarity_search("lost card", k=2)
with scoresstore.similarity_search_with_score(q, k=3)
filter by metadatastore.similarity_search("limit", k=2, filter={"topic": "upi"})
add laterstore.add_documents([doc], ids=["offer-1"])
deletechroma_store.delete(ids=["offer-1"])
save / load FAISSsave_local("idx") / FAISS.load_local("idx", emb, allow_dangerous_deserialization=True)
diverse resultsmax_marginal_relevance_search(q, k=2, fetch_k=6)
Demo · Why MMR?
Security: allow_dangerous_deserialization=True is needed because FAISS indexes are saved with pickle. Only load index files that you created; a pickle from a stranger can run code.

03Hands-on: run it here

The notebook’s six NovaBank documents in InMemory and FAISS: scores, save and reload from disk, add a new FD document, filter by topic and MMR.

lab09_vectorstores.py
import warnings; warnings.filterwarnings("ignore")
from standins import KeywordEmbeddings
from langchain_core.documents import Document
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_community.vectorstores import FAISS
embeddings = KeywordEmbeddings()        # Colab: HuggingFaceEmbeddings("sentence-transformers/all-MiniLM-L6-v2")

docs = [Document("Report a lost card within 3 days for zero liability.", metadata={"topic": "cards", "id": 1}),
        Document("Card-not-present payments above Rs 5,000 need OTP.", metadata={"topic": "cards", "id": 2}),
        Document("UPI limit for a new payee is Rs 25,000 in the first 24 hours.", metadata={"topic": "upi", "id": 3}),
        Document("Never share your UPI PIN with anyone.", metadata={"topic": "upi", "id": 4}),
        Document("Video KYC is available from 9 AM to 9 PM.", metadata={"topic": "kyc", "id": 5}),
        Document("Home loan interest starts at 8.5% per year.", metadata={"topic": "loans", "id": 6})]

store = InMemoryVectorStore.from_documents(docs, embeddings)
print("InMemory, cosine (higher = closer):")
for d, s in store.similarity_search_with_score("I lost my card, what should I do?", k=2): print(f"  {s:.3f}  {d.page_content}")

faiss_store = FAISS.from_documents(docs, embeddings)
print("FAISS, L2 distance (LOWER = closer):")
for d, s in faiss_store.similarity_search_with_score("loan interest rate", k=2): print(f"  {s:.3f}  {d.page_content}")
faiss_store.save_local("faiss_bank_index")
loaded = FAISS.load_local("faiss_bank_index", embeddings, allow_dangerous_deserialization=True)
print("reloaded from disk:", loaded.similarity_search("video KYC timing", k=1)[0].page_content)

faiss_store.add_documents([Document("Fixed deposit rate is 7.1% for 1 year.", metadata={"topic": "deposits", "id": 7})])
print("after add:", faiss_store.similarity_search("FD deposit rate", k=1)[0].page_content)
print("filter topic=upi:", [d.page_content for d in faiss_store.similarity_search("limit", k=2, filter={"topic": "upi"})])
print("MMR (diverse):", [d.metadata["id"] for d in faiss_store.max_marginal_relevance_search("card rules", k=2, fetch_k=6)])
InMemory, cosine (higher = closer): 0.200 Report a lost card within 3 days for zero liability. 0.100 Card-not-present payments above Rs 5,000 need OTP. FAISS, L2 distance (LOWER = closer): 1.183 Home loan interest starts at 8.5% per year. 2.000 Report a lost card within 3 days for zero liability. reloaded from disk: Video KYC is available from 9 AM to 9 PM. after add: Fixed deposit rate is 7.1% for 1 year. filter topic=upi: ['UPI limit for a new payee is Rs 25,000 in the first 24 hours.', 'Never share your UPI PIN with anyone.'] MMR (diverse): [2, 1]
Runs here without downloads. A tiny keyword embedding (KeywordEmbeddings in standins.py) stands in for MiniLM, so every output below is real, but the scores are smaller than MiniLM’s. In Colab use HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2").

04Hands-on: Ajeetkumar’s Colab notebook

Colab setup (same in every notebook): click 🔑 Secrets in the Colab sidebar, add groq_key with your free key from console.groq.com, switch on Notebook access, then run the cells from the top.
Demo · Notebook player · Lab 09

Outputs labelled stand-in embeddings, including all the Chroma cells, are from re-running the notebook here with the keyword stand-in.

05Practice tasks

  1. Load a PDF, split it, store it in FAISS, save and reload it.
  2. Store 20 product descriptions in Chroma with category metadata and filter by category.
  3. Compare FAISS vs InMemory scores for the same question.

Try these in the same Colab notebook after you finish the lab. Change one thing at a time and look at the output again.

06Summary

07Quick quiz

1. FAISS similarity_search_with_score returns 0.3 and 1.2. Which is closer?

2. Search only UPI documents?

3. Which store survives a restart with no extra code?

4. What does MMR add?

5. Why is allow_dangerous_deserialization needed for FAISS?

08References

Created by Ajeetkumar