
langchain-rag
β 846by langchain-ai Β· part of langchain-ai/langchain-skills
Complete RAG pipeline for document ingestion, embedding, retrieval, and LLM-powered response generation. Supports multiple document loaders (PDF, web pages, directories) and persistent vector stores (Chroma, FAISS, Pinecone) with configurable chunk size and overlap for optimal context preservation Includes similarity search, MMR (Maximal Marginal Relevance) retrieval, and metadata filtering to balance relevance and diversity in results Works with OpenAI embeddings and integrates seamlessly...
Complete RAG pipeline for document ingestion, embedding, retrieval, and LLM-powered response generation. Supports multiple document loaders (PDF, web pages, directories) and persistent vector stores (Chroma, FAISS, Pinecone) with configurable chunk size and overlap for optimal context preservation Includes similarity search, MMR (Maximal Marginal Relevance) retrieval, and metadata filtering to balance relevance and diversity in results Works with OpenAI embeddings and integrates seamlessly...
Inspect the full instructions your agent will receiveExpandCollapse
This is the exact playbook injected into your agent when the skill activates β shown here so you can audit it before installing. You don't need to read it to use the skill.
name: langchain-rag description: "INVOKE THIS SKILL when building ANY retrieval-augmented generation (RAG) system. Covers document loaders, RecursiveCharacterTextSplitter, embeddings (OpenAI), and vector stores (Chroma, FAISS, Pinecone)."
<overview> Retrieval Augmented Generation (RAG) enhances LLM responses by fetching relevant context from external knowledge sources.Pipeline:
- Index: Load β Split β Embed β Store
- Retrieve: Query β Embed β Search β Return docs
- Generate: Docs + Query β LLM β Response
Key Components:
- Document Loaders: Ingest data from files, web, databases
- Text Splitters: Break documents into chunks
- Embeddings: Convert text to vectors
- Vector Stores: Store and search embeddings </overview>
| Vector Store | Use Case | Persistence |
|---|---|---|
| InMemory | Testing | Memory only |
| FAISS | Local, high performance | Disk |
| Chroma | Development | Disk |
| Pinecone | Production, managed | Cloud |
Complete RAG Pipeline
<ex-basic-rag-setup> <python> End-to-end RAG pipeline: load documents, split into chunks, embed, store, retrieve, and generate a response.from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import InMemoryVectorStore
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.documents import Document
# 1. Load documents
docs = [
Document(page_content="LangChain is a framework for LLM apps.", metadata={}),
Document(page_content="RAG = Retrieval Augmented Generation.", metadata={}),
]
# 2. Split documents
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
splits = splitter.split_documents(docs)
# 3. Create embeddings and store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = InMemoryVectorStore.from_documents(splits, embeddings)
# 4. Create retriever
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# 5. Use in RAG
model = ChatOpenAI(model="gpt-4.1")
query = "What is RAG?"
relevant_docs = retriever.invoke(query)
context = "\n\n".join([doc.page_content for doc in relevant_docs])
response = model.invoke([
{"role": "system", "content": f"Use this context:\n\n{context}"},
{"role": "user", "content": query},
])import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai";
import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { Document } from "@langchain/core/documents";
// 1. Load documents
const docs = [
new Document({ pageContent: "LangChain is a framework for LLM apps.", metadata: {} }),
new Document({ pageContent: "RAG = Retrieval Augmented Generation.", metadata: {} }),
];
// 2. Split documents
const splitter = new RecursiveCharacterTextSplitter({ chunkSize: 500, chunkOverlap: 50 });
const splits = await splitter.splitDocuments(docs);
// 3. Create embeddings and store
const embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });
const vectorstore = await MemoryVectorStore.fromDocuments(splits, embeddings);
// 4. Create retriever
const retriever = vectorstore.asRetriever({ k: 4 });
// 5. Use in RAG
const model = new ChatOpenAI({ model: "gpt-4.1" });
const query = "What is RAG?";
const relevantDocs = await retriever.invoke(query);
const context = relevantDocs.map(doc => doc.pageContent).join("\n\n");
const response = await model.invoke([
{ role: "system", content: `Use this context:\n\n${context}` },
{ role: "user", content: query },
]);Document Loaders
<ex-loading-pdf> <python> Load a PDF file and extract each page as a separate document.from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("./document.pdf")
docs = loader.load()
print(f"Loaded {len(docs)} pages")import { PDFLoader } from "@langchain/community/document_loaders/fs/pdf";
const loader = new PDFLoader("./document.pdf");
const docs = await loader.load();
console.log(`Loaded ${docs.length} pages`);from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://docs.langchain.com")
docs = loader.load()import { CheerioWebBaseLoader } from "@langchain/community/document_loaders/web/cheerio";
const loader = new CheerioWebBaseLoader("https://docs.langchain.com");
const docs = await loader.load();from langchain_community.document_loaders import DirectoryLoader, TextLoader
# Load all text files from directory
loader = DirectoryLoader(
"path/to/documents",
glob="**/*.txt", # Pattern for files to load
loader_cls=TextLoader
)
docs = loader.load()Text Splitting
<ex-text-splitting> <python> Split documents into chunks using RecursiveCharacterTextSplitter with configurable size and overlap.from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # Characters per chunk
chunk_overlap=200, # Overlap for context continuity
separators=["\n\n", "\n", " ", ""], # Split hierarchy
)
splits = splitter.split_documents(docs)Vector Stores
<ex-chroma-vectorstore> <python> Create a persistent Chroma vector store and reload it from disk.from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
vectorstore = Chroma.from_documents(
documents=splits,
embedding=OpenAIEmbeddings(),
persist_directory="./chroma_db",
collection_name="my-collection",
)
# Load existing
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=OpenAIEmbeddings(),
collection_name="my-collection",
)import { Chroma } from "@langchain/community/vectorstores/chroma";
import { OpenAIEmbeddings } from "@langchain/openai";
const vectorstore = await Chroma.fromDocuments(
splits,
new OpenAIEmbeddings(),
{ collectionName: "my-collection", url: "http://localhost:8000" }
);from langchain_community.vectorstores import FAISS
vectorstore = FAISS.from_documents(splits, embeddings)
vectorstore.save_local("./faiss_index")
# Load (requires allow_dangerous_deserialization)
loaded = FAISS.load_local(
"./faiss_index",
embeddings,
allow_dangerous_deserialization=True
)import { FaissStore } from "@langchain/community/vectorstores/faiss";
const vectorstore = await FaissStore.fromDocuments(splits, embeddings);
await vectorstore.save("./faiss_index");
const loaded = await FaissStore.load("./faiss_index", embeddings);Retrieval
<ex-similarity-search> <python> Perform similarity search and retrieve results with relevance scores.# Basic search
results = vectorstore.similarity_search(query, k=5)
# With scores
results_with_score = vectorstore.similarity_search_with_score(query, k=5)
for doc, score in results_with_score:
print(f"Score: {score}, Content: {doc.page_content}")// Basic search
const results = await vectorstore.similaritySearch(query, 5);
// With scores
const resultsWithScore = await vectorstore.similaritySearchWithScore(query, 5);
for (const [doc, score] of resultsWithScore) {
console.log(`Score: ${score}, Content: ${doc.pageContent}`);
}# MMR balances relevance and diversity
retriever = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={"fetch_k": 20, "lambda_mult": 0.5, "k": 5},
)# Add metadata when creating documents
docs = [
Document(
page_content="Python programming guide",
metadata={"language": "python", "topic": "programming"}
),
]
# Search with filter
results = vectorstore.similarity_search(
"programming",
k=5,
filter={"language": "python"} # Only Python docs
)from langchain.agents import create_agent
from langchain.tools import tool
@tool
def search_docs(query: str) -> str:
"""Search documentation for relevant information."""
docs = retriever.invoke(query)
return "\n\n".join([d.page_content for d in docs])
agent = create_agent(
model="gpt-4.1",
tools=[search_docs],
)
result = agent.invoke({
"messages": [{"role": "user", "content": "How do I create an agent?"}]
})import { createAgent } from "langchain";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const searchDocs = tool(
async (input) => {
const docs = await retriever.invoke(input.query);
return docs.map(d => d.pageContent).join("\n\n");
},
{
name: "search_docs",
description: "Search documentation for relevant information.",
schema: z.object({ query: z.string() }),
}
);
const agent = createAgent({
model: "gpt-4.1",
tools: [searchDocs],
});
const result = await agent.invoke({
messages: [{ role: "user", content: "How do I create an agent?" }],
});- Chunk size/overlap
- Embedding model
- Number of results (k)
- Metadata filters
- Search algorithms: Similarity, MMR
What You CANNOT Configure
- Embedding dimensions (per model)
- Mix embeddings from different models in same store </boundaries>
# WRONG: Too small (loses context) or too large (hits limits)
splitter = RecursiveCharacterTextSplitter(chunk_size=50)
splitter = RecursiveCharacterTextSplitter(chunk_size=10000)
# CORRECT
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)// WRONG: Too small or too large
const splitter = new RecursiveCharacterTextSplitter({ chunkSize: 50 });
// CORRECT
const splitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000, chunkOverlap: 200 });# WRONG: No overlap - context breaks at boundaries
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
# CORRECT: 10-20% overlap
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)# WRONG: InMemory - lost on restart
vectorstore = InMemoryVectorStore.from_documents(docs, embeddings)
# CORRECT
vectorstore = Chroma.from_documents(docs, embeddings, persist_directory="./chroma_db")// WRONG: Memory - lost on restart
const vectorstore = await MemoryVectorStore.fromDocuments(docs, embeddings);
// CORRECT
const vectorstore = await Chroma.fromDocuments(docs, embeddings, { collectionName: "my-collection" });# WRONG: Different embeddings for index and query - incompatible!
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings(model="text-embedding-3-small"))
retriever = vectorstore.as_retriever(embeddings=OpenAIEmbeddings(model="text-embedding-3-large"))
# CORRECT: Same model
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(docs, embeddings)
retriever = vectorstore.as_retriever() # Uses same embeddingsconst embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });
const vectorstore = await Chroma.fromDocuments(docs, embeddings);
const retriever = vectorstore.asRetriever(); // Uses same embeddings# WRONG: Will raise error
loaded_store = FAISS.load_local("./faiss_index", embeddings)
# CORRECT
loaded_store = FAISS.load_local("./faiss_index", embeddings, allow_dangerous_deserialization=True)# WRONG: Index has 1536 dimensions but using 512-dim embeddings
pc.create_index(name="idx", dimension=1536, metric="cosine")
vectorstore = PineconeVectorStore.from_documents(
docs, OpenAIEmbeddings(model="text-embedding-3-small", dimensions=512), index=pc.Index("idx")
) # Error: dimension mismatch!
# CORRECT: Match dimensions
embeddings = OpenAIEmbeddings() # Default 1536npx skills add https://github.com/langchain-ai/langchain-skills --skill langchain-ragRun this in your project β your agent picks the skill up automatically.
No common issues documented yet. If you hit a problem, the repository's GitHub Issues page is the best place to look.