[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C5H7A9339APDENGJ4DACT5":3,"skill-same:01M6C5H7A9339APDENGJ4DACT5":55},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":29,"linkOnly":30,"markdownContent":31,"markdownBody":32,"frontMatter":33,"refName":34,"commitSha":35,"skillDirectory":36,"forksCount":14,"repositoryHtmlUrl":37,"repositoryHomepageUrl":6,"ownerHtmlUrl":38,"ownerBlogUrl":39,"ownerDescription":6,"updatedAt":40,"install":41,"resources":54},"01M6C5H7A9339APDENGJ4DACT5","langchain-rag",null,"INVOKE THIS SKILL when building ANY retrieval-augmented generation (RAG) system. Covers document loaders, RecursiveCharacterTextSplitter, embeddings (OpenAI), and vector stores (Chroma, FAISS, Pinecone).","CoralShades\u002Facm-ai","CoralShades","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F220297585?v=4","01M6C5211QSJHZ8HXSDDWCR507","Coral Shades AI Agency","01M6C52161FNQDRQ0FRR8DAA9D",0,"MIT","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flangchain-rag\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28],"rag","langchain","langchain rag","openai","vector","embeddings","system","vector stores","chroma","faiss","2026-11-10 10:12:30",false,"---\nname: langchain-rag\ndescription: \"INVOKE THIS SKILL when building ANY retrieval-augmented generation (RAG) system. Covers document loaders, RecursiveCharacterTextSplitter, embeddings (OpenAI), and vector stores (Chroma, FAISS, Pinecone).\"\n---\n\n\u003Coverview>\nRetrieval Augmented Generation (RAG) enhances LLM responses by fetching relevant context from external knowledge sources.\n\n**Pipeline:**\n1. **Index**: Load → Split → Embed → Store\n2. **Retrieve**: Query → Embed → Search → Return docs\n3. **Generate**: Docs + Query → LLM → Response\n\n**Key Components:**\n- **Document Loaders**: Ingest data from files, web, databases\n- **Text Splitters**: Break documents into chunks\n- **Embeddings**: Convert text to vectors\n- **Vector Stores**: Store and search embeddings\n\u003C\u002Foverview>\n\n\u003Cvectorstore-selection>\n\n| Vector Store | Use Case | Persistence |\n|--------------|----------|-------------|\n| **InMemory** | Testing | Memory only |\n| **FAISS** | Local, high performance | Disk |\n| **Chroma** | Development | Disk |\n| **Pinecone** | Production, managed | Cloud |\n\n\u003C\u002Fvectorstore-selection>\n\n---\n\n## Complete RAG Pipeline\n\n\u003Cex-basic-rag-setup>\n\u003Cpython>\nEnd-to-end RAG pipeline: load documents, split into chunks, embed, store, retrieve, and generate a response.\n```python\nfrom langchain_openai import ChatOpenAI, OpenAIEmbeddings\nfrom langchain_community.vectorstores import InMemoryVectorStore\nfrom langchain_text_splitters import RecursiveCharacterTextSplitter\nfrom langchain_core.documents import Document\n\n# 1. Load documents\ndocs = [\n    Document(page_content=\"LangChain is a framework for LLM apps.\", metadata={}),\n    Document(page_content=\"RAG = Retrieval Augmented Generation.\", metadata={}),\n]\n\n# 2. Split documents\nsplitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)\nsplits = splitter.split_documents(docs)\n\n# 3. Create embeddings and store\nembeddings = OpenAIEmbeddings(model=\"text-embedding-3-small\")\nvectorstore = InMemoryVectorStore.from_documents(splits, embeddings)\n\n# 4. Create retriever\nretriever = vectorstore.as_retriever(search_kwargs={\"k\": 4})\n\n# 5. Use in RAG\nmodel = ChatOpenAI(model=\"gpt-4.1\")\nquery = \"What is RAG?\"\nrelevant_docs = retriever.invoke(query)\n\ncontext = \"\\n\\n\".join([doc.page_content for doc in relevant_docs])\nresponse = model.invoke([\n    {\"role\": \"system\", \"content\": f\"Use this context:\\n\\n{context}\"},\n    {\"role\": \"user\", \"content\": query},\n])\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nEnd-to-end RAG pipeline: load documents, split into chunks, embed, store, retrieve, and generate a response.\n```typescript\nimport { ChatOpenAI, OpenAIEmbeddings } from \"@langchain\u002Fopenai\";\nimport { MemoryVectorStore } from \"@langchain\u002Fclassic\u002Fvectorstores\u002Fmemory\";\nimport { RecursiveCharacterTextSplitter } from \"@langchain\u002Ftextsplitters\";\nimport { Document } from \"@langchain\u002Fcore\u002Fdocuments\";\n\n\u002F\u002F 1. Load documents\nconst docs = [\n  new Document({ pageContent: \"LangChain is a framework for LLM apps.\", metadata: {} }),\n  new Document({ pageContent: \"RAG = Retrieval Augmented Generation.\", metadata: {} }),\n];\n\n\u002F\u002F 2. Split documents\nconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 500, chunkOverlap: 50 });\nconst splits = await splitter.splitDocuments(docs);\n\n\u002F\u002F 3. Create embeddings and store\nconst embeddings = new OpenAIEmbeddings({ model: \"text-embedding-3-small\" });\nconst vectorstore = await MemoryVectorStore.fromDocuments(splits, embeddings);\n\n\u002F\u002F 4. Create retriever\nconst retriever = vectorstore.asRetriever({ k: 4 });\n\n\u002F\u002F 5. Use in RAG\nconst model = new ChatOpenAI({ model: \"gpt-4.1\" });\nconst query = \"What is RAG?\";\nconst relevantDocs = await retriever.invoke(query);\n\nconst context = relevantDocs.map(doc => doc.pageContent).join(\"\\n\\n\");\nconst response = await model.invoke([\n  { role: \"system\", content: `Use this context:\\n\\n${context}` },\n  { role: \"user\", content: query },\n]);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-basic-rag-setup>\n\n---\n\n## Document Loaders\n\n\u003Cex-loading-pdf>\n\u003Cpython>\nLoad a PDF file and extract each page as a separate document.\n```python\nfrom langchain_community.document_loaders import PyPDFLoader\n\nloader = PyPDFLoader(\".\u002Fdocument.pdf\")\ndocs = loader.load()\nprint(f\"Loaded {len(docs)} pages\")\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nLoad a PDF file and extract each page as a separate document.\n```typescript\nimport { PDFLoader } from \"@langchain\u002Fcommunity\u002Fdocument_loaders\u002Ffs\u002Fpdf\";\n\nconst loader = new PDFLoader(\".\u002Fdocument.pdf\");\nconst docs = await loader.load();\nconsole.log(`Loaded ${docs.length} pages`);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-loading-pdf>\n\n\u003Cex-loading-web-pages>\n\u003Cpython>\nFetch and parse content from a web URL into a document.\n```python\nfrom langchain_community.document_loaders import WebBaseLoader\n\nloader = WebBaseLoader(\"https:\u002F\u002Fdocs.langchain.com\")\ndocs = loader.load()\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nFetch and parse content from a web URL into a document using Cheerio.\n```typescript\nimport { CheerioWebBaseLoader } from \"@langchain\u002Fcommunity\u002Fdocument_loaders\u002Fweb\u002Fcheerio\";\n\nconst loader = new CheerioWebBaseLoader(\"https:\u002F\u002Fdocs.langchain.com\");\nconst docs = await loader.load();\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-loading-web-pages>\n\n\u003Cex-loading-directory>\n\u003Cpython>\nLoad all text files from a directory using a glob pattern.\n```python\nfrom langchain_community.document_loaders import DirectoryLoader, TextLoader\n\n# Load all text files from directory\nloader = DirectoryLoader(\n    \"path\u002Fto\u002Fdocuments\",\n    glob=\"**\u002F*.txt\",  # Pattern for files to load\n    loader_cls=TextLoader\n)\ndocs = loader.load()\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-loading-directory>\n\n---\n\n## Text Splitting\n\n\u003Cex-text-splitting>\n\u003Cpython>\nSplit documents into chunks using RecursiveCharacterTextSplitter with configurable size and overlap.\n```python\nfrom langchain_text_splitters import RecursiveCharacterTextSplitter\n\nsplitter = RecursiveCharacterTextSplitter(\n    chunk_size=1000,        # Characters per chunk\n    chunk_overlap=200,      # Overlap for context continuity\n    separators=[\"\\n\\n\", \"\\n\", \" \", \"\"],  # Split hierarchy\n)\n\nsplits = splitter.split_documents(docs)\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-text-splitting>\n\n---\n\n## Vector Stores\n\n\u003Cex-chroma-vectorstore>\n\u003Cpython>\nCreate a persistent Chroma vector store and reload it from disk.\n```python\nfrom langchain_chroma import Chroma\nfrom langchain_openai import OpenAIEmbeddings\n\nvectorstore = Chroma.from_documents(\n    documents=splits,\n    embedding=OpenAIEmbeddings(),\n    persist_directory=\".\u002Fchroma_db\",\n    collection_name=\"my-collection\",\n)\n\n# Load existing\nvectorstore = Chroma(\n    persist_directory=\".\u002Fchroma_db\",\n    embedding_function=OpenAIEmbeddings(),\n    collection_name=\"my-collection\",\n)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nCreate a Chroma vector store connected to a running Chroma server.\n```typescript\nimport { Chroma } from \"@langchain\u002Fcommunity\u002Fvectorstores\u002Fchroma\";\nimport { OpenAIEmbeddings } from \"@langchain\u002Fopenai\";\n\nconst vectorstore = await Chroma.fromDocuments(\n  splits,\n  new OpenAIEmbeddings(),\n  { collectionName: \"my-collection\", url: \"http:\u002F\u002Flocalhost:8000\" }\n);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-chroma-vectorstore>\n\n\u003Cex-faiss-vectorstore>\n\u003Cpython>\nCreate a FAISS vector store, save it to disk, and reload it.\n```python\nfrom langchain_community.vectorstores import FAISS\n\nvectorstore = FAISS.from_documents(splits, embeddings)\nvectorstore.save_local(\".\u002Ffaiss_index\")\n\n# Load (requires allow_dangerous_deserialization)\nloaded = FAISS.load_local(\n    \".\u002Ffaiss_index\",\n    embeddings,\n    allow_dangerous_deserialization=True\n)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nCreate a FAISS vector store, save it to disk, and reload it.\n```typescript\nimport { FaissStore } from \"@langchain\u002Fcommunity\u002Fvectorstores\u002Ffaiss\";\n\nconst vectorstore = await FaissStore.fromDocuments(splits, embeddings);\nawait vectorstore.save(\".\u002Ffaiss_index\");\n\nconst loaded = await FaissStore.load(\".\u002Ffaiss_index\", embeddings);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-faiss-vectorstore>\n\n---\n\n## Retrieval\n\n\u003Cex-similarity-search>\n\u003Cpython>\nPerform similarity search and retrieve results with relevance scores.\n```python\n# Basic search\nresults = vectorstore.similarity_search(query, k=5)\n\n# With scores\nresults_with_score = vectorstore.similarity_search_with_score(query, k=5)\nfor doc, score in results_with_score:\n    print(f\"Score: {score}, Content: {doc.page_content}\")\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nPerform similarity search and retrieve results with relevance scores.\n```typescript\n\u002F\u002F Basic search\nconst results = await vectorstore.similaritySearch(query, 5);\n\n\u002F\u002F With scores\nconst resultsWithScore = await vectorstore.similaritySearchWithScore(query, 5);\nfor (const [doc, score] of resultsWithScore) {\n  console.log(`Score: ${score}, Content: ${doc.pageContent}`);\n}\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-similarity-search>\n\n\u003Cex-mmr-search>\n\u003Cpython>\nUse MMR (Maximal Marginal Relevance) to balance relevance and diversity in search results.\n```python\n# MMR balances relevance and diversity\nretriever = vectorstore.as_retriever(\n    search_type=\"mmr\",\n    search_kwargs={\"fetch_k\": 20, \"lambda_mult\": 0.5, \"k\": 5},\n)\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-mmr-search>\n\n\u003Cex-metadata-filtering>\n\u003Cpython>\nAdd metadata to documents and filter search results by metadata properties.\n```python\n# Add metadata when creating documents\ndocs = [\n    Document(\n        page_content=\"Python programming guide\",\n        metadata={\"language\": \"python\", \"topic\": \"programming\"}\n    ),\n]\n\n# Search with filter\nresults = vectorstore.similarity_search(\n    \"programming\",\n    k=5,\n    filter={\"language\": \"python\"}  # Only Python docs\n)\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-metadata-filtering>\n\n\u003Cex-rag-with-agent>\n\u003Cpython>\nCreate an agent that uses RAG as a tool for answering questions.\n```python\nfrom langchain.agents import create_agent\nfrom langchain.tools import tool\n\n@tool\ndef search_docs(query: str) -> str:\n    \"\"\"Search documentation for relevant information.\"\"\"\n    docs = retriever.invoke(query)\n    return \"\\n\\n\".join([d.page_content for d in docs])\n\nagent = create_agent(\n    model=\"gpt-4.1\",\n    tools=[search_docs],\n)\n\nresult = agent.invoke({\n    \"messages\": [{\"role\": \"user\", \"content\": \"How do I create an agent?\"}]\n})\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nCreate an agent that uses RAG as a tool for answering questions.\n```typescript\nimport { createAgent } from \"langchain\";\nimport { tool } from \"@langchain\u002Fcore\u002Ftools\";\nimport { z } from \"zod\";\n\nconst searchDocs = tool(\n  async (input) => {\n    const docs = await retriever.invoke(input.query);\n    return docs.map(d => d.pageContent).join(\"\\n\\n\");\n  },\n  {\n    name: \"search_docs\",\n    description: \"Search documentation for relevant information.\",\n    schema: z.object({ query: z.string() }),\n  }\n);\n\nconst agent = createAgent({\n  model: \"gpt-4.1\",\n  tools: [searchDocs],\n});\n\nconst result = await agent.invoke({\n  messages: [{ role: \"user\", content: \"How do I create an agent?\" }],\n});\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-rag-with-agent>\n\n\u003Cboundaries>\n### What You CAN Configure\n\n- Chunk size\u002Foverlap\n- Embedding model\n- Number of results (k)\n- Metadata filters\n- Search algorithms: Similarity, MMR\n\n### What You CANNOT Configure\n\n- Embedding dimensions (per model)\n- Mix embeddings from different models in same store\n\u003C\u002Fboundaries>\n\n\u003Cfix-chunk-size>\n\u003Cpython>\nChunk size 500-1500 is typically good.\n```python\n# WRONG: Too small (loses context) or too large (hits limits)\nsplitter = RecursiveCharacterTextSplitter(chunk_size=50)\nsplitter = RecursiveCharacterTextSplitter(chunk_size=10000)\n\n# CORRECT\nsplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nChunk size 500-1500 is typically good.\n```typescript\n\u002F\u002F WRONG: Too small or too large\nconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 50 });\n\n\u002F\u002F CORRECT\nconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000, chunkOverlap: 200 });\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-chunk-size>\n\n\u003Cfix-chunk-overlap>\n\u003Cpython>\nUse overlap (10-20% of chunk size) to maintain context at boundaries.\n```python\n# WRONG: No overlap - context breaks at boundaries\nsplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n\n# CORRECT: 10-20% overlap\nsplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)\n```\n\u003C\u002Fpython>\n\u003C\u002Ffix-chunk-overlap>\n\n\u003Cfix-persist-vectorstore>\n\u003Cpython>\nUse persistent vector store instead of in-memory to avoid data loss.\n```python\n# WRONG: InMemory - lost on restart\nvectorstore = InMemoryVectorStore.from_documents(docs, embeddings)\n\n# CORRECT\nvectorstore = Chroma.from_documents(docs, embeddings, persist_directory=\".\u002Fchroma_db\")\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse persistent vector store instead of in-memory to avoid data loss.\n```typescript\n\u002F\u002F WRONG: Memory - lost on restart\nconst vectorstore = await MemoryVectorStore.fromDocuments(docs, embeddings);\n\n\u002F\u002F CORRECT\nconst vectorstore = await Chroma.fromDocuments(docs, embeddings, { collectionName: \"my-collection\" });\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-persist-vectorstore>\n\n\u003Cfix-consistent-embeddings>\n\u003Cpython>\nUse the same embedding model for indexing and querying.\n```python\n# WRONG: Different embeddings for index and query - incompatible!\nvectorstore = Chroma.from_documents(docs, OpenAIEmbeddings(model=\"text-embedding-3-small\"))\nretriever = vectorstore.as_retriever(embeddings=OpenAIEmbeddings(model=\"text-embedding-3-large\"))\n\n# CORRECT: Same model\nembeddings = OpenAIEmbeddings(model=\"text-embedding-3-small\")\nvectorstore = Chroma.from_documents(docs, embeddings)\nretriever = vectorstore.as_retriever()  # Uses same embeddings\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse the same embedding model for indexing and querying.\n```typescript\nconst embeddings = new OpenAIEmbeddings({ model: \"text-embedding-3-small\" });\nconst vectorstore = await Chroma.fromDocuments(docs, embeddings);\nconst retriever = vectorstore.asRetriever();  \u002F\u002F Uses same embeddings\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-consistent-embeddings>\n\n\u003Cfix-faiss-deserialization>\n\u003Cpython>\nExplicitly allow deserialization when loading FAISS indexes.\n```python\n# WRONG: Will raise error\nloaded_store = FAISS.load_local(\".\u002Ffaiss_index\", embeddings)\n\n# CORRECT\nloaded_store = FAISS.load_local(\".\u002Ffaiss_index\", embeddings, allow_dangerous_deserialization=True)\n```\n\u003C\u002Fpython>\n\u003C\u002Ffix-faiss-deserialization>\n\n\u003Cfix-dimension-mismatch>\n\u003Cpython>\nEnsure embedding dimensions match the vector store index dimensions.\n```python\n# WRONG: Index has 1536 dimensions but using 512-dim embeddings\npc.create_index(name=\"idx\", dimension=1536, metric=\"cosine\")\nvectorstore = PineconeVectorStore.from_documents(\n    docs, OpenAIEmbeddings(model=\"text-embedding-3-small\", dimensions=512), index=pc.Index(\"idx\")\n)  # Error: dimension mismatch!\n\n# CORRECT: Match dimensions\nembeddings = OpenAIEmbeddings()  # Default 1536\n```\n\u003C\u002Fpython>\n\u003C\u002Ffix-dimension-mismatch>\n","\u003Coverview>\nRetrieval Augmented Generation (RAG) enhances LLM responses by fetching relevant context from external knowledge sources.\n\n**Pipeline:**\n1. **Index**: Load → Split → Embed → Store\n2. **Retrieve**: Query → Embed → Search → Return docs\n3. **Generate**: Docs + Query → LLM → Response\n\n**Key Components:**\n- **Document Loaders**: Ingest data from files, web, databases\n- **Text Splitters**: Break documents into chunks\n- **Embeddings**: Convert text to vectors\n- **Vector Stores**: Store and search embeddings\n\u003C\u002Foverview>\n\n\u003Cvectorstore-selection>\n\n| Vector Store | Use Case | Persistence |\n|--------------|----------|-------------|\n| **InMemory** | Testing | Memory only |\n| **FAISS** | Local, high performance | Disk |\n| **Chroma** | Development | Disk |\n| **Pinecone** | Production, managed | Cloud |\n\n\u003C\u002Fvectorstore-selection>\n\n---\n\n## Complete RAG Pipeline\n\n\u003Cex-basic-rag-setup>\n\u003Cpython>\nEnd-to-end RAG pipeline: load documents, split into chunks, embed, store, retrieve, and generate a response.\n```python\nfrom langchain_openai import ChatOpenAI, OpenAIEmbeddings\nfrom langchain_community.vectorstores import InMemoryVectorStore\nfrom langchain_text_splitters import RecursiveCharacterTextSplitter\nfrom langchain_core.documents import Document\n\n# 1. Load documents\ndocs = [\n    Document(page_content=\"LangChain is a framework for LLM apps.\", metadata={}),\n    Document(page_content=\"RAG = Retrieval Augmented Generation.\", metadata={}),\n]\n\n# 2. Split documents\nsplitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)\nsplits = splitter.split_documents(docs)\n\n# 3. Create embeddings and store\nembeddings = OpenAIEmbeddings(model=\"text-embedding-3-small\")\nvectorstore = InMemoryVectorStore.from_documents(splits, embeddings)\n\n# 4. Create retriever\nretriever = vectorstore.as_retriever(search_kwargs={\"k\": 4})\n\n# 5. Use in RAG\nmodel = ChatOpenAI(model=\"gpt-4.1\")\nquery = \"What is RAG?\"\nrelevant_docs = retriever.invoke(query)\n\ncontext = \"\\n\\n\".join([doc.page_content for doc in relevant_docs])\nresponse = model.invoke([\n    {\"role\": \"system\", \"content\": f\"Use this context:\\n\\n{context}\"},\n    {\"role\": \"user\", \"content\": query},\n])\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nEnd-to-end RAG pipeline: load documents, split into chunks, embed, store, retrieve, and generate a response.\n```typescript\nimport { ChatOpenAI, OpenAIEmbeddings } from \"@langchain\u002Fopenai\";\nimport { MemoryVectorStore } from \"@langchain\u002Fclassic\u002Fvectorstores\u002Fmemory\";\nimport { RecursiveCharacterTextSplitter } from \"@langchain\u002Ftextsplitters\";\nimport { Document } from \"@langchain\u002Fcore\u002Fdocuments\";\n\n\u002F\u002F 1. Load documents\nconst docs = [\n  new Document({ pageContent: \"LangChain is a framework for LLM apps.\", metadata: {} }),\n  new Document({ pageContent: \"RAG = Retrieval Augmented Generation.\", metadata: {} }),\n];\n\n\u002F\u002F 2. Split documents\nconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 500, chunkOverlap: 50 });\nconst splits = await splitter.splitDocuments(docs);\n\n\u002F\u002F 3. Create embeddings and store\nconst embeddings = new OpenAIEmbeddings({ model: \"text-embedding-3-small\" });\nconst vectorstore = await MemoryVectorStore.fromDocuments(splits, embeddings);\n\n\u002F\u002F 4. Create retriever\nconst retriever = vectorstore.asRetriever({ k: 4 });\n\n\u002F\u002F 5. Use in RAG\nconst model = new ChatOpenAI({ model: \"gpt-4.1\" });\nconst query = \"What is RAG?\";\nconst relevantDocs = await retriever.invoke(query);\n\nconst context = relevantDocs.map(doc => doc.pageContent).join(\"\\n\\n\");\nconst response = await model.invoke([\n  { role: \"system\", content: `Use this context:\\n\\n${context}` },\n  { role: \"user\", content: query },\n]);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-basic-rag-setup>\n\n---\n\n## Document Loaders\n\n\u003Cex-loading-pdf>\n\u003Cpython>\nLoad a PDF file and extract each page as a separate document.\n```python\nfrom langchain_community.document_loaders import PyPDFLoader\n\nloader = PyPDFLoader(\".\u002Fdocument.pdf\")\ndocs = loader.load()\nprint(f\"Loaded {len(docs)} pages\")\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nLoad a PDF file and extract each page as a separate document.\n```typescript\nimport { PDFLoader } from \"@langchain\u002Fcommunity\u002Fdocument_loaders\u002Ffs\u002Fpdf\";\n\nconst loader = new PDFLoader(\".\u002Fdocument.pdf\");\nconst docs = await loader.load();\nconsole.log(`Loaded ${docs.length} pages`);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-loading-pdf>\n\n\u003Cex-loading-web-pages>\n\u003Cpython>\nFetch and parse content from a web URL into a document.\n```python\nfrom langchain_community.document_loaders import WebBaseLoader\n\nloader = WebBaseLoader(\"https:\u002F\u002Fdocs.langchain.com\")\ndocs = loader.load()\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nFetch and parse content from a web URL into a document using Cheerio.\n```typescript\nimport { CheerioWebBaseLoader } from \"@langchain\u002Fcommunity\u002Fdocument_loaders\u002Fweb\u002Fcheerio\";\n\nconst loader = new CheerioWebBaseLoader(\"https:\u002F\u002Fdocs.langchain.com\");\nconst docs = await loader.load();\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-loading-web-pages>\n\n\u003Cex-loading-directory>\n\u003Cpython>\nLoad all text files from a directory using a glob pattern.\n```python\nfrom langchain_community.document_loaders import DirectoryLoader, TextLoader\n\n# Load all text files from directory\nloader = DirectoryLoader(\n    \"path\u002Fto\u002Fdocuments\",\n    glob=\"**\u002F*.txt\",  # Pattern for files to load\n    loader_cls=TextLoader\n)\ndocs = loader.load()\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-loading-directory>\n\n---\n\n## Text Splitting\n\n\u003Cex-text-splitting>\n\u003Cpython>\nSplit documents into chunks using RecursiveCharacterTextSplitter with configurable size and overlap.\n```python\nfrom langchain_text_splitters import RecursiveCharacterTextSplitter\n\nsplitter = RecursiveCharacterTextSplitter(\n    chunk_size=1000,        # Characters per chunk\n    chunk_overlap=200,      # Overlap for context continuity\n    separators=[\"\\n\\n\", \"\\n\", \" \", \"\"],  # Split hierarchy\n)\n\nsplits = splitter.split_documents(docs)\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-text-splitting>\n\n---\n\n## Vector Stores\n\n\u003Cex-chroma-vectorstore>\n\u003Cpython>\nCreate a persistent Chroma vector store and reload it from disk.\n```python\nfrom langchain_chroma import Chroma\nfrom langchain_openai import OpenAIEmbeddings\n\nvectorstore = Chroma.from_documents(\n    documents=splits,\n    embedding=OpenAIEmbeddings(),\n    persist_directory=\".\u002Fchroma_db\",\n    collection_name=\"my-collection\",\n)\n\n# Load existing\nvectorstore = Chroma(\n    persist_directory=\".\u002Fchroma_db\",\n    embedding_function=OpenAIEmbeddings(),\n    collection_name=\"my-collection\",\n)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nCreate a Chroma vector store connected to a running Chroma server.\n```typescript\nimport { Chroma } from \"@langchain\u002Fcommunity\u002Fvectorstores\u002Fchroma\";\nimport { OpenAIEmbeddings } from \"@langchain\u002Fopenai\";\n\nconst vectorstore = await Chroma.fromDocuments(\n  splits,\n  new OpenAIEmbeddings(),\n  { collectionName: \"my-collection\", url: \"http:\u002F\u002Flocalhost:8000\" }\n);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-chroma-vectorstore>\n\n\u003Cex-faiss-vectorstore>\n\u003Cpython>\nCreate a FAISS vector store, save it to disk, and reload it.\n```python\nfrom langchain_community.vectorstores import FAISS\n\nvectorstore = FAISS.from_documents(splits, embeddings)\nvectorstore.save_local(\".\u002Ffaiss_index\")\n\n# Load (requires allow_dangerous_deserialization)\nloaded = FAISS.load_local(\n    \".\u002Ffaiss_index\",\n    embeddings,\n    allow_dangerous_deserialization=True\n)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nCreate a FAISS vector store, save it to disk, and reload it.\n```typescript\nimport { FaissStore } from \"@langchain\u002Fcommunity\u002Fvectorstores\u002Ffaiss\";\n\nconst vectorstore = await FaissStore.fromDocuments(splits, embeddings);\nawait vectorstore.save(\".\u002Ffaiss_index\");\n\nconst loaded = await FaissStore.load(\".\u002Ffaiss_index\", embeddings);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-faiss-vectorstore>\n\n---\n\n## Retrieval\n\n\u003Cex-similarity-search>\n\u003Cpython>\nPerform similarity search and retrieve results with relevance scores.\n```python\n# Basic search\nresults = vectorstore.similarity_search(query, k=5)\n\n# With scores\nresults_with_score = vectorstore.similarity_search_with_score(query, k=5)\nfor doc, score in results_with_score:\n    print(f\"Score: {score}, Content: {doc.page_content}\")\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nPerform similarity search and retrieve results with relevance scores.\n```typescript\n\u002F\u002F Basic search\nconst results = await vectorstore.similaritySearch(query, 5);\n\n\u002F\u002F With scores\nconst resultsWithScore = await vectorstore.similaritySearchWithScore(query, 5);\nfor (const [doc, score] of resultsWithScore) {\n  console.log(`Score: ${score}, Content: ${doc.pageContent}`);\n}\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-similarity-search>\n\n\u003Cex-mmr-search>\n\u003Cpython>\nUse MMR (Maximal Marginal Relevance) to balance relevance and diversity in search results.\n```python\n# MMR balances relevance and diversity\nretriever = vectorstore.as_retriever(\n    search_type=\"mmr\",\n    search_kwargs={\"fetch_k\": 20, \"lambda_mult\": 0.5, \"k\": 5},\n)\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-mmr-search>\n\n\u003Cex-metadata-filtering>\n\u003Cpython>\nAdd metadata to documents and filter search results by metadata properties.\n```python\n# Add metadata when creating documents\ndocs = [\n    Document(\n        page_content=\"Python programming guide\",\n        metadata={\"language\": \"python\", \"topic\": \"programming\"}\n    ),\n]\n\n# Search with filter\nresults = vectorstore.similarity_search(\n    \"programming\",\n    k=5,\n    filter={\"language\": \"python\"}  # Only Python docs\n)\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-metadata-filtering>\n\n\u003Cex-rag-with-agent>\n\u003Cpython>\nCreate an agent that uses RAG as a tool for answering questions.\n```python\nfrom langchain.agents import create_agent\nfrom langchain.tools import tool\n\n@tool\ndef search_docs(query: str) -> str:\n    \"\"\"Search documentation for relevant information.\"\"\"\n    docs = retriever.invoke(query)\n    return \"\\n\\n\".join([d.page_content for d in docs])\n\nagent = create_agent(\n    model=\"gpt-4.1\",\n    tools=[search_docs],\n)\n\nresult = agent.invoke({\n    \"messages\": [{\"role\": \"user\", \"content\": \"How do I create an agent?\"}]\n})\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nCreate an agent that uses RAG as a tool for answering questions.\n```typescript\nimport { createAgent } from \"langchain\";\nimport { tool } from \"@langchain\u002Fcore\u002Ftools\";\nimport { z } from \"zod\";\n\nconst searchDocs = tool(\n  async (input) => {\n    const docs = await retriever.invoke(input.query);\n    return docs.map(d => d.pageContent).join(\"\\n\\n\");\n  },\n  {\n    name: \"search_docs\",\n    description: \"Search documentation for relevant information.\",\n    schema: z.object({ query: z.string() }),\n  }\n);\n\nconst agent = createAgent({\n  model: \"gpt-4.1\",\n  tools: [searchDocs],\n});\n\nconst result = await agent.invoke({\n  messages: [{ role: \"user\", content: \"How do I create an agent?\" }],\n});\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-rag-with-agent>\n\n\u003Cboundaries>\n### What You CAN Configure\n\n- Chunk size\u002Foverlap\n- Embedding model\n- Number of results (k)\n- Metadata filters\n- Search algorithms: Similarity, MMR\n\n### What You CANNOT Configure\n\n- Embedding dimensions (per model)\n- Mix embeddings from different models in same store\n\u003C\u002Fboundaries>\n\n\u003Cfix-chunk-size>\n\u003Cpython>\nChunk size 500-1500 is typically good.\n```python\n# WRONG: Too small (loses context) or too large (hits limits)\nsplitter = RecursiveCharacterTextSplitter(chunk_size=50)\nsplitter = RecursiveCharacterTextSplitter(chunk_size=10000)\n\n# CORRECT\nsplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nChunk size 500-1500 is typically good.\n```typescript\n\u002F\u002F WRONG: Too small or too large\nconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 50 });\n\n\u002F\u002F CORRECT\nconst splitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000, chunkOverlap: 200 });\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-chunk-size>\n\n\u003Cfix-chunk-overlap>\n\u003Cpython>\nUse overlap (10-20% of chunk size) to maintain context at boundaries.\n```python\n# WRONG: No overlap - context breaks at boundaries\nsplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n\n# CORRECT: 10-20% overlap\nsplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)\n```\n\u003C\u002Fpython>\n\u003C\u002Ffix-chunk-overlap>\n\n\u003Cfix-persist-vectorstore>\n\u003Cpython>\nUse persistent vector store instead of in-memory to avoid data loss.\n```python\n# WRONG: InMemory - lost on restart\nvectorstore = InMemoryVectorStore.from_documents(docs, embeddings)\n\n# CORRECT\nvectorstore = Chroma.from_documents(docs, embeddings, persist_directory=\".\u002Fchroma_db\")\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse persistent vector store instead of in-memory to avoid data loss.\n```typescript\n\u002F\u002F WRONG: Memory - lost on restart\nconst vectorstore = await MemoryVectorStore.fromDocuments(docs, embeddings);\n\n\u002F\u002F CORRECT\nconst vectorstore = await Chroma.fromDocuments(docs, embeddings, { collectionName: \"my-collection\" });\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-persist-vectorstore>\n\n\u003Cfix-consistent-embeddings>\n\u003Cpython>\nUse the same embedding model for indexing and querying.\n```python\n# WRONG: Different embeddings for index and query - incompatible!\nvectorstore = Chroma.from_documents(docs, OpenAIEmbeddings(model=\"text-embedding-3-small\"))\nretriever = vectorstore.as_retriever(embeddings=OpenAIEmbeddings(model=\"text-embedding-3-large\"))\n\n# CORRECT: Same model\nembeddings = OpenAIEmbeddings(model=\"text-embedding-3-small\")\nvectorstore = Chroma.from_documents(docs, embeddings)\nretriever = vectorstore.as_retriever()  # Uses same embeddings\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse the same embedding model for indexing and querying.\n```typescript\nconst embeddings = new OpenAIEmbeddings({ model: \"text-embedding-3-small\" });\nconst vectorstore = await Chroma.fromDocuments(docs, embeddings);\nconst retriever = vectorstore.asRetriever();  \u002F\u002F Uses same embeddings\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-consistent-embeddings>\n\n\u003Cfix-faiss-deserialization>\n\u003Cpython>\nExplicitly allow deserialization when loading FAISS indexes.\n```python\n# WRONG: Will raise error\nloaded_store = FAISS.load_local(\".\u002Ffaiss_index\", embeddings)\n\n# CORRECT\nloaded_store = FAISS.load_local(\".\u002Ffaiss_index\", embeddings, allow_dangerous_deserialization=True)\n```\n\u003C\u002Fpython>\n\u003C\u002Ffix-faiss-deserialization>\n\n\u003Cfix-dimension-mismatch>\n\u003Cpython>\nEnsure embedding dimensions match the vector store index dimensions.\n```python\n# WRONG: Index has 1536 dimensions but using 512-dim embeddings\npc.create_index(name=\"idx\", dimension=1536, metric=\"cosine\")\nvectorstore = PineconeVectorStore.from_documents(\n    docs, OpenAIEmbeddings(model=\"text-embedding-3-small\", dimensions=512), index=pc.Index(\"idx\")\n)  # Error: dimension mismatch!\n\n# CORRECT: Match dimensions\nembeddings = OpenAIEmbeddings()  # Default 1536\n```\n\u003C\u002Fpython>\n\u003C\u002Ffix-dimension-mismatch>\n",{"name":5,"description":7},"main","1ca81b0a7de199942400f965edd4d7544077ac5d",".claude\u002Fskills\u002Flangchain-rag","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai","https:\u002F\u002Fgithub.com\u002FCoralShades","coralshades.com.au","2026-04-18 00:45:07",{"source":8,"skillName":5,"commands":42,"prompt":52,"zipAvailable":53},[43,46,49],{"tool":44,"command":45},"npx","npx skills add CoralShades\u002Facm-ai --skill langchain-rag",{"tool":47,"command":48},"bunx","bunx skills add CoralShades\u002Facm-ai --skill langchain-rag",{"tool":50,"command":51},"pnpm","pnpm dlx skills add CoralShades\u002Facm-ai --skill langchain-rag","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flangchain-rag\u002FSKILL.md",true,[],[56,80,93,109,131,141],{"skillNo":57,"name":58,"nameZh":6,"description":59,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":60,"categories":61,"keywords":67,"publishedAt":29},"01M6C63HKXA890HHV47WBAX0TB","uncodixfy","Prevents generic AI\u002FCodex UI patterns when generating frontend code. Use this skill whenever generating HTML, CSS, React, Vue, Svelte, or any frontend UI code to enforce clean, human-designed aesthetics inspired by Linear, Raycast, Stripe, and GitHub instead of typical AI-generated UI.","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Funcodixfy\u002FSKILL.md",[62],{"categoryNo":63,"categoryName":64,"taxonomyType":65,"taxonomyTypeDesc":66},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[58,68,69,70,71,72,73,74,75,76,77,78,79],"github","frontend","css","codex","react","code","linear","ui","vue","generated","use","html",{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":84,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":29},"01M6C63FJ2GEBBGZ5XSMV40KXB","runpodctl","Runpod CLI to manage your GPU workloads.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Frunpodctl\u002FSKILL.md",[],[82,88,89,90,91,92],"macos","cli","linux","gpu","Bash",{"skillNo":94,"name":95,"nameZh":6,"description":96,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":99,"publishedAt":29},"01M6C63DPAV46TFVQ01SFYPJ7X","langgraph-persistence","INVOKE THIS SKILL when your LangGraph needs to persist state, remember conversations, travel through history, or configure subgraph checkpointer scoping. Covers checkpointers, thread_id, time travel, Store, and subgraph persistence modes.","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Flanggraph-persistence\u002FSKILL.md",[],[100,101,102,103,104,105,106,107,108],"langgraph persistence","langgraph","persistence","travel","history","scoping","remember","state","configure",{"skillNo":110,"name":111,"nameZh":6,"description":112,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":120,"publishedAt":29},"01M6C63BNS9CQEBTB8RNSSBFPA","langgraph-human-in-the-loop","INVOKE THIS SKILL when implementing human-in-the-loop patterns, pausing for approval, or handling errors in LangGraph. Covers interrupt(), Command(resume=...), approval\u002Fvalidation workflows, and the 4-tier error handling strategy.","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Flanggraph-human-in-the-loop\u002FSKILL.md",[115],{"categoryNo":116,"categoryName":117,"taxonomyType":118,"taxonomyTypeDesc":119},"01JBSEEDCAT000000000000038","人力资源","PROFESSION","适用职业",[121,122,101,123,124,125,126,127,128,129,130],"langgraph human in the loop","loop","workflows","error handling","validation","human-in-the-loop","command","strategy","approval","resume",{"skillNo":132,"name":133,"nameZh":6,"description":134,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":135,"categories":136,"keywords":137,"publishedAt":29},"01M6C639GVYZFX3NFPV5FBDR4F","langgraph-fundamentals","INVOKE THIS SKILL when writing ANY LangGraph code. Covers StateGraph, state schemas, nodes, edges, Command, Send, invoke, streaming, and error handling.","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Flanggraph-fundamentals\u002FSKILL.md",[],[138,101,124,107,139,140,127,73],"langgraph fundamentals","streaming","writing",{"skillNo":142,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":143,"categories":144,"keywords":145,"publishedAt":29},"01M6C6375N34YX2GZ3SD3R7XR2","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Flangchain-rag\u002FSKILL.md",[],[19,21,20,24,23,22,27,28,26,25]]