KlarkLabs
Back to blog
AI
15 February 2026
5 min read

Building a RAG Pipeline with LangChain and MongoDB

A complete guide to implementing a high-performance RAG pipeline using LangChain and MongoDB Atlas Vector Search.

RAGLangChainMongoDBAI

Retrieval-Augmented Generation (RAG) has become the go-to architecture for building AI applications that can answer questions about your own data. In this article, we will build a complete RAG pipeline combining LangChain and MongoDB Atlas Vector Search.

Why RAG?

Large language models (LLMs) suffer from two major limitations: their knowledge cutoff and their inability to access proprietary data. RAG solves both problems by dynamically retrieving relevant documents before generating a response, ensuring answers are up-to-date and grounded in your context.

Pipeline Architecture

Our pipeline consists of three main stages:

  1. Ingestion: document chunking, embedding generation, storage in MongoDB
  2. Retrieval: vector search to find relevant passages
  3. Generation: sending context to the LLM to produce a response

Environment Setup

# requirements.txt
langchain==0.3.0
langchain-mongodb==0.2.0
langchain-openai==0.2.0
pymongo==4.8.0
python-dotenv==1.0.0
# config.py
import os
from dotenv import load_dotenv
 
load_dotenv()
 
MONGODB_URI = os.getenv("MONGODB_URI")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
DB_NAME = "rag_demo"
COLLECTION_NAME = "documents"
VECTOR_INDEX_NAME = "vector_index"

Step 1: Document Ingestion

Chunking quality is critical to retrieval relevance. We use RecursiveCharacterTextSplitter, which respects the natural structure of text by trying larger separators first before falling back to smaller ones.

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_mongodb import MongoDBAtlasVectorSearch
from pymongo import MongoClient
 
def ingest_documents(documents: list[str]) -> MongoDBAtlasVectorSearch:
    client = MongoClient(MONGODB_URI)
    collection = client[DB_NAME][COLLECTION_NAME]
 
    # Split with overlap to preserve cross-chunk context
    splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=200,
        separators=["\n\n", "\n", ".", " "]
    )
 
    embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
 
    vector_store = MongoDBAtlasVectorSearch.from_texts(
        texts=splitter.split_text("\n\n".join(documents)),
        embedding=embeddings,
        collection=collection,
        index_name=VECTOR_INDEX_NAME,
    )
 
    return vector_store

Step 2: Creating the MongoDB Vector Index

In MongoDB Atlas, create a vector index on your collection via the console or the API:

{
  "fields": [
    {
      "type": "vector",
      "path": "embedding",
      "numDimensions": 1536,
      "similarity": "cosine"
    },
    {
      "type": "filter",
      "path": "metadata.source"
    }
  ]
}

Step 3: Full RAG Chain

from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
 
PROMPT_TEMPLATE = """You are an expert assistant. Use only the following context excerpts
to answer the question. If you cannot find the answer in the context,
say so clearly.
 
Context:
{context}
 
Question: {question}
 
Answer:"""
 
def build_rag_chain(vector_store: MongoDBAtlasVectorSearch) -> RetrievalQA:
    llm = ChatOpenAI(model="gpt-4o", temperature=0)
 
    prompt = PromptTemplate(
        template=PROMPT_TEMPLATE,
        input_variables=["context", "question"]
    )
 
    retriever = vector_store.as_retriever(
        search_type="similarity",
        search_kwargs={"k": 5}
    )
 
    chain = RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=retriever,
        chain_type_kwargs={"prompt": prompt},
        return_source_documents=True
    )
 
    return chain

Advanced Optimizations

Hybrid Search

MongoDB Atlas supports hybrid search (vector + full-text), which significantly improves precision for keyword-heavy queries:

retriever = vector_store.as_retriever(
    search_type="similarity_score_threshold",
    search_kwargs={
        "k": 10,
        "score_threshold": 0.75,
        "pre_filter": {"metadata.category": {"$eq": "technical"}}
    }
)

Embedding Caching

Generating embeddings is expensive. Use LangChain's CacheBackedEmbeddings to avoid recomputing embeddings for documents already seen, reducing costs by up to 70%.

Results and Metrics

On a corpus of 50,000 technical documents, this pipeline achieves:

  • Precision@5: 89% (the top 5 retrieved documents contain the answer)
  • P95 latency: 340ms (retrieval + generation combined)
  • Cost per query: ~$0.004 with GPT-4o

Conclusion

LangChain and MongoDB Atlas make a powerful combination for building production-grade RAG pipelines. LangChain's flexibility for orchestrating each stage and MongoDB Atlas Vector Search's robustness for indexing and querying millions of vectors at low latency make this stack ideal for large-scale AI applications.

The complete code for this example is available on our GitHub. Feel free to adapt it to your specific use case.

Klark Labs
Technology Studio