Langchain Rag

作者 langchain-ai16a992f09ab3無授權條款1.2K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫2 天前更新

INVOKE THIS SKILL when building ANY retrieval-augmented generation (RAG) system. Covers document loaders, RecursiveCharacterTextSplitter, embeddings (OpenAI), and vector stores (Chroma, FAISS, Pinecone).

僅含說明AI & Agents
AI 產生的概覽

指導使用 LangChain 建構檢索增強生成(RAG)流程,涵蓋載入器、文字切分、嵌入與向量儲存。

功能
提供建構 RAG 流程的參考說明與程式碼範例,涵蓋 Python 與 TypeScript:載入文件、切分文字、建立嵌入、儲存向量、檢索結果並生成回答。它比較 InMemory、FAISS、Chroma 與 Pinecone 等向量儲存方案,並展示相似度搜尋、MMR 與中繼資料過濾等檢索模式。它也列出常見錯誤與修正方式,例如分塊大小、重疊、嵌入一致性與 FAISS 反序列化安全。
適用情境
適用於使用 LangChain 實作或除錯檢索增強生成系統的情境。適合涉及文件載入器、文字切分器、OpenAI 嵌入或 Chroma、FAISS、Pinecone 等向量儲存的工作。
執行需求
僅為說明文件,不附帶指令碼。範例假定已安裝 Python 或 TypeScript 的 LangChain 相關套件,擁有用於嵌入與聊天模型的 OpenAI API 金鑰,並可選地需要執行中的 Chroma 伺服器或 Pinecone 帳戶。

<overview>

Retrieval Augmented Generation (RAG) enhances LLM responses by fetching relevant context from external knowledge sources.

Pipeline:

  1. Index: Load → Split → Embed → Store
  2. Retrieve: Query → Embed → Search → Return docs
  3. 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>

<vectorstore-selection>

Vector StoreUse CasePersistence
InMemoryTestingMemory only
FAISSLocal, high performanceDisk
ChromaDevelopmentDisk
PineconeProduction, managedCloud

</vectorstore-selection>


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.

python
from langchain_openai import ChatOpenAI, OpenAIEmbeddingsfrom langchain_community.vectorstores import InMemoryVectorStorefrom langchain_text_splitters import RecursiveCharacterTextSplitterfrom langchain_core.documents import Document
# 1. Load documentsdocs = [    Document(page_content="LangChain is a framework for LLM apps.", metadata={}),    Document(page_content="RAG = Retrieval Augmented Generation.", metadata={}),]
# 2. Split documentssplitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)splits = splitter.split_documents(docs)
# 3. Create embeddings and storeembeddings = OpenAIEmbeddings(model="text-embedding-3-small")vectorstore = InMemoryVectorStore.from_documents(splits, embeddings)
# 4. Create retrieverretriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# 5. Use in RAGmodel = 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},])

</python>

<typescript>

End-to-end RAG pipeline: load documents, split into chunks, embed, store, retrieve, and generate a response.

typescript
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 documentsconst docs = [  new Document({ pageContent: "LangChain is a framework for LLM apps.", metadata: {} }),  new Document({ pageContent: "RAG = Retrieval Augmented Generation.", metadata: {} }),];
// 2. Split documentsconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 500, chunkOverlap: 50 });const splits = await splitter.splitDocuments(docs);
// 3. Create embeddings and storeconst embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });const vectorstore = await MemoryVectorStore.fromDocuments(splits, embeddings);
// 4. Create retrieverconst retriever = vectorstore.asRetriever({ k: 4 });
// 5. Use in RAGconst 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 },]);

</typescript>

</ex-basic-rag-setup>


Document Loaders

<ex-loading-pdf>

<python>

Load a PDF file and extract each page as a separate document.

python
from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("./document.pdf")docs = loader.load()print(f"Loaded {len(docs)} pages")

</python>

<typescript>

Load a PDF file and extract each page as a separate document.

typescript
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`);

</typescript>

</ex-loading-pdf>

<ex-loading-web-pages>

<python>

Fetch and parse content from a web URL into a document.

python
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://docs.langchain.com")docs = loader.load()

</python>

<typescript>

Fetch and parse content from a web URL into a document using Cheerio.

typescript
import { CheerioWebBaseLoader } from "@langchain/community/document_loaders/web/cheerio";
const loader = new CheerioWebBaseLoader("https://docs.langchain.com");const docs = await loader.load();

</typescript>

</ex-loading-web-pages>

<ex-loading-directory>

<python>

Load all text files from a directory using a glob pattern.

python
from langchain_community.document_loaders import DirectoryLoader, TextLoader
# Load all text files from directoryloader = DirectoryLoader(    "path/to/documents",    glob="**/*.txt",  # Pattern for files to load    loader_cls=TextLoader)docs = loader.load()

</python>

</ex-loading-directory>


Text Splitting

<ex-text-splitting>

<python>

Split documents into chunks using RecursiveCharacterTextSplitter with configurable size and overlap.

python
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)

</python>

</ex-text-splitting>


Vector Stores

<ex-chroma-vectorstore>

<python>

Create a persistent Chroma vector store and reload it from disk.

python
from langchain_chroma import Chromafrom langchain_openai import OpenAIEmbeddings
vectorstore = Chroma.from_documents(    documents=splits,    embedding=OpenAIEmbeddings(),    persist_directory="./chroma_db",    collection_name="my-collection",)
# Load existingvectorstore = Chroma(    persist_directory="./chroma_db",    embedding_function=OpenAIEmbeddings(),    collection_name="my-collection",)

</python>

<typescript>

Create a Chroma vector store connected to a running Chroma server.

typescript
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" });

</typescript>

</ex-chroma-vectorstore>

<ex-faiss-vectorstore>

<python>

Create a FAISS vector store, save it to disk, and reload it.

python
from langchain_community.vectorstores import FAISS
vectorstore = FAISS.from_documents(splits, embeddings)vectorstore.save_local("./faiss_index")
# Only load FAISS indexes that you created and fully control.# The Python FAISS loader uses pickle-backed metadata, so never load# downloaded, shared, or otherwise untrusted index directories.loaded = FAISS.load_local(    "./faiss_index",    embeddings,    allow_dangerous_deserialization=True,)

</python>

<typescript>

Create a FAISS vector store, save it to disk, and reload it.

typescript
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);

</typescript>

</ex-faiss-vectorstore>


Retrieval

<ex-similarity-search>

<python>

Perform similarity search and retrieve results with relevance scores.

python
# Basic searchresults = vectorstore.similarity_search(query, k=5)
# With scoresresults_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}")

</python>

<typescript>

Perform similarity search and retrieve results with relevance scores.

typescript
// Basic searchconst results = await vectorstore.similaritySearch(query, 5);
// With scoresconst resultsWithScore = await vectorstore.similaritySearchWithScore(query, 5);for (const [doc, score] of resultsWithScore) {  console.log(`Score: ${score}, Content: ${doc.pageContent}`);}

</typescript>

</ex-similarity-search>

<ex-mmr-search>

<python>

Use MMR (Maximal Marginal Relevance) to balance relevance and diversity in search results.

python
# MMR balances relevance and diversityretriever = vectorstore.as_retriever(    search_type="mmr",    search_kwargs={"fetch_k": 20, "lambda_mult": 0.5, "k": 5},)

</python>

</ex-mmr-search>

<ex-metadata-filtering>

<python>

Add metadata to documents and filter search results by metadata properties.

python
# Add metadata when creating documentsdocs = [    Document(        page_content="Python programming guide",        metadata={"language": "python", "topic": "programming"}    ),]
# Search with filterresults = vectorstore.similarity_search(    "programming",    k=5,    filter={"language": "python"}  # Only Python docs)

</python>

</ex-metadata-filtering>

<ex-rag-with-agent>

<python>

Create an agent that uses RAG as a tool for answering questions.

python
from langchain.agents import create_agentfrom langchain.tools import tool
@tooldef 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?"}]})

</python>

<typescript>

Create an agent that uses RAG as a tool for answering questions.

typescript
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?" }],});

</typescript>

</ex-rag-with-agent>

<boundaries>

What You CAN Configure

  • 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>

<fix-chunk-size>

<python>

Chunk size 500-1500 is typically good.

python
# WRONG: Too small (loses context) or too large (hits limits)splitter = RecursiveCharacterTextSplitter(chunk_size=50)splitter = RecursiveCharacterTextSplitter(chunk_size=10000)
# CORRECTsplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)

</python>

<typescript>

Chunk size 500-1500 is typically good.

typescript
// WRONG: Too small or too largeconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 50 });
// CORRECTconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000, chunkOverlap: 200 });

</typescript>

</fix-chunk-size>

<fix-chunk-overlap>

<python>

Use overlap (10-20% of chunk size) to maintain context at boundaries.

python
# WRONG: No overlap - context breaks at boundariessplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
# CORRECT: 10-20% overlapsplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)

</python>

</fix-chunk-overlap>

<fix-persist-vectorstore>

<python>

Use persistent vector store instead of in-memory to avoid data loss.

python
# WRONG: InMemory - lost on restartvectorstore = InMemoryVectorStore.from_documents(docs, embeddings)
# CORRECTvectorstore = Chroma.from_documents(docs, embeddings, persist_directory="./chroma_db")

</python>

<typescript>

Use persistent vector store instead of in-memory to avoid data loss.

typescript
// WRONG: Memory - lost on restartconst vectorstore = await MemoryVectorStore.fromDocuments(docs, embeddings);
// CORRECTconst vectorstore = await Chroma.fromDocuments(docs, embeddings, { collectionName: "my-collection" });

</typescript>

</fix-persist-vectorstore>

<fix-consistent-embeddings>

<python>

Use the same embedding model for indexing and querying.

python
# 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 modelembeddings = OpenAIEmbeddings(model="text-embedding-3-small")vectorstore = Chroma.from_documents(docs, embeddings)retriever = vectorstore.as_retriever()  # Uses same embeddings

</python>

<typescript>

Use the same embedding model for indexing and querying.

typescript
const embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });const vectorstore = await Chroma.fromDocuments(docs, embeddings);const retriever = vectorstore.asRetriever();  // Uses same embeddings

</typescript>

</fix-consistent-embeddings>

<fix-faiss-deserialization>

<python>

Only opt in to FAISS deserialization for trusted local indexes. Python FAISS indexes include pickle-backed metadata, and untrusted pickle files can execute arbitrary code during loading.

python
# WRONG: Loading a downloaded, shared, cloud-hosted, or third-party-controlled# FAISS index with dangerous deserialization enabled.loaded_store = FAISS.load_local(    "./untrusted_faiss_index",    embeddings,    allow_dangerous_deserialization=True,)
# CORRECT: Only opt in when the index directory was created by you and has# remained under your control.loaded_store = FAISS.load_local(    "./faiss_index",    embeddings,    allow_dangerous_deserialization=True,)

If you cannot guarantee the provenance of a persisted index, do not load it with allow_dangerous_deserialization=True. Rebuild the index from trusted source documents or use a vector store/backend that does not require pickle deserialization for untrusted files.

</python>

</fix-faiss-deserialization>

<fix-dimension-mismatch>

<python>

Ensure embedding dimensions match the vector store index dimensions.

python
# WRONG: Index has 1536 dimensions but using 512-dim embeddingspc.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 dimensionsembeddings = OpenAIEmbeddings()  # Default 1536

</python>

</fix-dimension-mismatch>

來源與署名

來源:langchain-ai/langchain-skills位於config/skills/langchain-rag提交16a992f

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架