LangChain Mastery

Course Content

LangChain Mastery

7 sections · 109 lessons

Implement a function to combine multiple vector stores in LangChain.


Fuse one ranking, or keep every sourceEnsembleRetriever• Weighted reciprocal rank fusion• One best-ranked list overall• A noisy store can crowd out others• Good when sources overlapRunnableParallel plus merge• Each store queried at the same time• Fixed quota per store, tagged by name• Dedupe by a stable id• Good when sources are separate
Rank fusion picks the best chunks; per-store quotas guarantee the clean help article is never pushed to rank six.

What you need to know

Why you end up with several stores

  • Different teams own different content (docs, FAQs, tickets).
  • Different embedding models suit different content (code vs prose).
  • Different access rules or retention (public docs vs internal notes).

You cannot merge vectors from different embedding models into one index, so combining at retrieval time is the normal answer.

Option 1: fuse rankings with EnsembleRetriever

Python
from langchain_classic.retrievers import EnsembleRetrievercombined = EnsembleRetriever(    retrievers=[docs_store.as_retriever(search_kwargs={"k": 5}),                faq_store.as_retriever(search_kwargs={"k": 5})],    weights=[0.6, 0.4],    id_key="id",          # metadata field used to spot the same doc in both lists)results = combined.invoke("how to reset UPI PIN")

In LangChain 1.x, EnsembleRetriever is imported from langchain_classic.retrievers.

Option 2: run in parallel, keep every source

Python
from langchain_core.runnables import RunnableParallel, RunnableLambdadef combine_stores(stores: dict, k: int = 4):    """Query several vector stores in parallel, tag each hit, drop duplicates."""    branches = {name: s.as_retriever(search_kwargs={"k": k}) for name, s in stores.items()}    def merge(results: dict) -> list:        seen, merged = set(), []        for name, docs in results.items():            for d in docs:                key = d.metadata.get("id") or d.page_content                if key not in seen:                    seen.add(key)                    d.metadata["store"] = name                    merged.append(d)        return merged    return RunnableParallel(branches) | RunnableLambda(merge)retriever = combine_stores({"docs": docs_store, "tickets": ticket_store})

RunnableParallel runs the retrievers concurrently, so latency is about the slowest store, not the sum. The store tag lets the prompt and the UI say where each fact came from. MergerRetriever (also in langchain_classic.retrievers) does a similar interleaved concatenation.

What to watch

  • Context size — 3 stores × k=5 is 15 chunks. Cap the merged list or rerank it down to 5–6.
  • Duplicates — the same article indexed in two stores. Dedupe by a stable id, or with EmbeddingsRedundantFilter from langchain_community.document_transformers.
  • Latency — one slow store delays everything; give each retriever a timeout or a fallback to an empty list.

A real-life example

A bank's customer-support assistant has three stores: public help articles, internal agent notes, and resolved tickets. First version: one EnsembleRetriever over all three. Complaints followed — for "how do I reset my UPI PIN", the tickets store dominated with long, messy chats and the clean help article dropped to rank 6.

The team switched to the parallel approach: 3 help articles, 2 agent notes and 1 ticket, each tagged. The prompt says "prefer help articles; use tickets only as examples". The average prompt shrank from 15 chunks to 6, cost per answer fell by about half, and the help article was always present.

Follow-up questions to expect

  • "How do you choose the weights?" — Start equal, then tune on a labelled question set; weights are a guess until measured.
  • "Could you just put everything in one store?" — Yes, with a source metadata field and filters, if all content uses the same embedding model and access rules. That is often simpler.
  • "Why not average the raw scores?" — Different stores and models produce scores on different scales; rank fusion avoids comparing them.