langchain-rag

作者: langchain-ai

當建構任何檢索增強生成(RAG)系統時,應呼叫此技能。涵蓋文件載入器、RecursiveCharacterTextSplitter、嵌入(OpenAI)、…

npx skills add https://github.com/langchain-ai/skills-benchmarks --skill langchain-rag
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
Vector StoreUse CasePersistence
InMemoryTestingMemory only
FAISSLocal, high performanceDisk
ChromaDevelopmentDisk
PineconeProduction, managedCloud

Complete RAG Pipeline

End-to-end RAG pipeline: load documents, split into chunks, embed, store, retrieve, and generate a response. ```python 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}, ])

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

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`);
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();
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 directory

loader = 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)

Vector Stores

Create a persistent Chroma vector store and reload it from disk. ```python 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", )

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

Load (requires allow_dangerous_deserialization)

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

Retrieval

Perform similarity search and retrieve results with relevance scores. ```python # 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}")

</python>
<typescript>
Perform similarity search and retrieve results with relevance scores.
```typescript
// 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}`);
}
Use MMR (Maximal Marginal Relevance) to balance relevance and diversity in search results. ```python # 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 to documents and filter search results by metadata properties. ```python # 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 )

</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_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?"}]
})
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)

# CORRECT
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
Chunk size 500-1500 is typically good. ```typescript // WRONG: Too small or too large const splitter = new RecursiveCharacterTextSplitter({ chunkSize: 50 });

// CORRECT const 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 boundaries
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)

# CORRECT: 10-20% overlap
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
Use persistent vector store instead of in-memory to avoid data loss. ```python # WRONG: InMemory - lost on restart vectorstore = InMemoryVectorStore.from_documents(docs, embeddings)

CORRECT

vectorstore = 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 restart
const vectorstore = await MemoryVectorStore.fromDocuments(docs, embeddings);

// CORRECT
const vectorstore = await Chroma.fromDocuments(docs, embeddings, { collectionName: "my-collection" });
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 model

embeddings = 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
Explicitly allow deserialization when loading FAISS indexes. ```python # 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)

</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 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 1536

來自 langchain-ai 的更多技能

langgraph-docs
langchain-ai
存取 LangGraph 文件以建構具狀態代理與多代理工作流程。擷取官方 LangGraph Python 文件,涵蓋狀態機、基於圖形的代理設計及人機協作模式。根據查詢類型優先提供相關文件:實作指南用於操作問題、概念頁面用於理論、教學用於端到端範例、API 參考用於技術細節。自動選取 2 至 4 個最相關的文件 URL 並擷取內容以回答...
official
langgraph-human-in-the-loop
langchain-ai
暫停圖形執行以進行人工審查、批准或驗證,然後根據其輸入繼續執行。需要三個組件:檢查點儲存器(InMemorySaver 或 PostgresSaver)、配置中的執行緒 ID,以及可序列化為 JSON 的中斷負載。interrupt(value) 會暫停並顯示資料;Command(resume=value) 會繼續執行,並將該值返回給暫停的節點。所有 interrupt() 之前的程式碼在恢復時會重新執行,因此副作用必須是冪等的(使用 upsert,而非 insert)。支援審批工作流程,...
official
web-research
langchain-ai
使用此技能處理與網路研究相關的請求;它提供了一種結構化方法來進行全面的網路研究
official
langchain-oss-primer
langchain-ai
務必從此處開始任何 LangChain、Deep Agents 或 Lang
official
skill-creator
langchain-ai
建立有效技能的指南,透過專業知識、工作流程或工具整合來擴展代理功能。當使用者…時,請使用此技能。
official
social-media
langchain-ai
根據研究內容撰寫特定平台的社群媒體貼文,並生成搭配圖片。支援LinkedIn貼文(1,300字元,專業語氣)與Twitter/X推文串(每則280字元,採用1/🧵格式)。寫作前需將研究任務委派給子代理,並閱讀其發現以確保準確性與相關性。使用generate_social_image工具自動生成吸睛的社群圖片,採用大膽高對比構圖,針對小螢幕進行優化。
official
deep-agents-memory
langchain-ai
為Deep Agents提供可插拔的記憶體與檔案後端,支援短暫、持久及混合路由選項。四種後端類型:StateBackend(執行緒範圍內短暫)、StoreBackend(跨工作階段持久)、FilesystemBackend(本地開發的真實磁碟存取)及CompositeBackend(將不同路徑路由至不同後端)。FilesystemMiddleware提供六種檔案操作工具:ls、read_file、write_file、edit_file、glob、grep。CompositeBackend使用最長前綴匹配進行路由...
official
deep-agents-orchestration
langchain-ai
協調子代理、規劃多步驟任務,並在敏感操作時要求人類批准。透過任務工具將工作委派給專業子代理;自訂子代理支援隔離的工具集與系統提示,而預設的「通用」子代理則繼承主代理配置。使用 write_todos 規劃與追蹤複雜工作流程,將任務組織為待處理、進行中與已完成狀態;需提供 thread_id 以在多次調用間保持持續性。實作...
official