A langchain pinecone rag pipeline gives you a clean separation between document ingestion, vector search, and LLM synthesis. This guide walks through a working Python implementation: chunk local files, embed them with OpenAI models, store vectors in Pinecone, and serve answers through a LangChain retrieval chain.
Step 1: Install dependencies and configure secrets
Use a fresh virtual environment. The LangChain ecosystem splits packages by provider, so install only what you need.
pip install langchain langchain-openai langchain-pinecone pinecone-client python-dotenv
Create a .env file. Pinecone’s serverless indexes only require an API key and an index name; you no longer need an environment string.
OPENAI_API_KEY=sk-...
PINECONE_API_KEY=pc-...
PINECONE_INDEX=rag-demo
Load these in Python with dotenv:
from dotenv import load_dotenv
import os
load_dotenv()
Step 2: Load and chunk your documents
LangChain’s loader abstractions keep ingestion uniform. For a quick start, use TextLoader; swap in PyPDFLoader or WebBaseLoader later.
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
loader = TextLoader("docs/intro.txt")
raw_docs = loader.load()
splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=100,
separators=["\n\n", "\n", ". ", " "]
)
chunks = splitter.split_documents(raw_docs)
print(f"Created {len(chunks)} chunks from {len(raw_docs)} files")
Chunk size is a retrieval lever, not a constant
800 tokens with 100 overlap works for prose. If your documents are dense specs, drop to 400–500 to improve precision. Overlap prevents a sentence from being split across boundaries, but too much overlap multiplies storage cost.
Preserve metadata. The loader attaches source and page (if available). Keep it; you will surface it to users for citation.
Step 3: Create the Pinecone index
Dimension must match your embedding model. text-embedding-3-small outputs 1536 dimensions. Use cosine similarity for normalized embeddings.
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
index_name = os.environ["PINECONE_INDEX"]
if index_name not in pc.list_indexes().names():
pc.create_index(
name=index_name,
dimension=1536,
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1")
)
index = pc.Index(index_name)
Serverless indexes scale without node provisioning. If you are on legacy pod-based Pinecone, replace ServerlessSpec with PodSpec.
Step 4: Embed and upsert vectors
LangChain’s PineconeVectorStore handles batch upsert automatically. Instantiate the embeddings client first.
from langchain_openai import OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = PineconeVectorStore.from_documents(
documents=chunks,
embedding=embeddings,
index_name=index_name
)
Routing embeddings through a gateway
If you want a single OpenAI-compatible endpoint that addresses 240+ models with automatic fallback when a provider is rate-limited or degraded, point the client at n4n.ai:
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
base_url="https://api.n4n.ai/v1",
api_key=os.environ["N4N_API_KEY"]
)
The from_documents call chunks your list into Pinecone’s recommended batch size (100 vectors) and writes metadata. For very large corpora, call vectorstore.add_documents(chunks) in your own loop to control concurrency and log progress.
Step 5: Build the retrieval-augmented generation chain
A minimal RAG chain needs three parts: a retriever, a prompt, and an LLM. Use RetrievalQA for clarity, or compose with LCEL for finer control.
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
qa = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
chain_type="stuff",
return_source_documents=True
)
Tuning the retriever
k=4 is a starting point. Increase to 6–8 for broad questions, but watch context window limits. For metadata filtering, pass filter={"tenant": "acme"} in search_kwargs.
Prompt discipline
The default stuff chain concatenates retrieved chunks into the prompt. Add a system message that forbids outside knowledge:
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "Answer only from the context. If unsure, say 'not specified'."),
("human", "Context: {context}\n\nQuestion: {question}")
])
Step 6: Query and verify success
Run a query and inspect both the answer and the sources.
response = qa.invoke({"query": "What is the refund window?"})
print("ANSWER:", response["result"])
for doc in response["source_documents"]:
print("SOURCE:", doc.metadata["source"], "|", doc.page_content[:120])
Verification checklist
A healthy langchain pinecone rag pipeline should pass these:
source_documentsis non-empty and relevant.- The answer cites a fact present in the printed chunk.
- No hallucinated dates or policies appear when the doc lacks them.
Automate with a tiny test:
def test_rag_grounding():
out = qa.invoke({"query": "What is the refund window?"})
assert out["source_documents"]
assert "refund" in out["result"].lower()
Run with pytest. If the assertion fails, lower k or adjust chunk size.
Step 7: Production hardening
The toy pipeline above works locally. For production, address these:
Namespaces and multi-tenancy
Pinecone supports namespaces. Pass namespace="tenant_123" to PineconeVectorStore so queries isolate data.
vectorstore = PineconeVectorStore(
index=index,
embedding=embeddings,
namespace="tenant_123"
)
Re-indexing strategy
Embeddings are immutable once computed. When source docs change, delete by filter and re-upsert. Keep a hash of file content in metadata to detect drift.
Latency and caching
Embedding calls dominate ingestion cost. Cache embeddings keyed by content hash. For query-time LLM calls, set temperature=0 and reuse the chain. If you used a gateway in Step 4, you already get per-token metering and provider cache-control forwarding without extra code.
Monitoring retrieval quality
Log the retrieved chunk IDs and the user question. Sample weekly to check precision. A langchain pinecone rag pipeline degrades silently when chunks drift from queries; track hit rate on source clicks if you expose citations.
Wrapping up
You now have an end-to-end langchain pinecone rag pipeline: documents chunked, embedded, stored in Pinecone, and served through a LangChain retrieval chain with source grounding. Swap the loaders for your own data, tune k and chunk size, and add namespaces before shipping.