Embeddings, vector stores and retrievers

LangChain · Advanced · 14 min

Semantic search over your own data is the core of retrieval-augmented generation.

An embedding model maps text to a vector so that similar meanings are close together. LangChain's Embeddings interface has embed_documents(texts) and embed_query(text); providers include OpenAIEmbeddings, GoogleGenerativeAIEmbeddings, OllamaEmbeddings and Hugging Face models.

A vector store stores vectors with their documents and finds nearest neighbours:

  • InMemoryVectorStore(embeddings) for prototypes and tests.
  • Chroma, FAISS, pgvector (Postgres), Qdrant, Pinecone, Elasticsearch, and others for real workloads.

Common methods: add_documents(docs) (returns IDs), similarity_search(query, k=4), similarity_search_with_score, delete(ids), and metadata filters (syntax depends on the store).

vector_store.as_retriever(search_kwargs={"k": 4}) returns a retriever, a runnable that maps a query string to a list of Documents, so it plugs into chains and tools. search_type="mmr" (maximal marginal relevance) trades a little relevance for diversity, avoiding near-duplicate chunks.

Practical advice:

  • Use the same embedding model for indexing and querying; changing it requires re-indexing.
  • Store stable IDs (e.g. source plus chunk number) so re-ingesting updates rather than duplicates.
  • Combine vector search with keyword search (hybrid) when exact terms like product codes matter.

Example

from langchain_core.documents import Document
from langchain_core.embeddings import DeterministicFakeEmbedding
from langchain_core.vectorstores import InMemoryVectorStore

# real: from langchain_openai import OpenAIEmbeddings; emb = OpenAIEmbeddings(model="text-embedding-3-small")
emb = DeterministicFakeEmbedding(size=64)     # offline stand-in (hash-based, not semantic)

store = InMemoryVectorStore(emb)
ids = store.add_documents([
    Document("Refunds are processed within 5 days.", metadata={"topic": "billing"}),
    Document("Reset your password from the login page.", metadata={"topic": "account"}),
    Document("Invoices can be downloaded as PDF.", metadata={"topic": "billing"}),
], ids=["faq-1", "faq-2", "faq-3"])
print(ids)                                    # ['faq-1', 'faq-2', 'faq-3']

hits = store.similarity_search("Refunds are processed within 5 days.", k=1)
print(hits[0].metadata)                       # {'topic': 'billing'}

retriever = store.as_retriever(search_kwargs={"k": 2})
docs = retriever.invoke("How do I get my money back?")
print(len(docs), type(docs[0]).__name__)      # 2 Document

Remember

  • Embeddings turn text into vectors; vector stores search them by similarity
  • as_retriever() exposes a store as a runnable returning Documents
  • Index and query with the same embedding model; use stable IDs

Watch out for

  • Switching embedding models without re-indexing, so query vectors no longer match stored vectors.

Check yourself

  1. What does a retriever's invoke('question') return?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.langchain.com/oss/python/langchain/knowledge-base