LangChain 的 RAG Chain 我调了三天才跑通——DeepAgents 把它变成了一个工具
用 LangChain 做 RAG你大概率写过这段代码loader DirectoryLoader(./docs, glob**/*.md)docs loader.load()splitter RecursiveCharacterTextSplitter(chunk_size1000, chunk_overlap200)chunks splitter.split_documents(docs)embeddings OpenAIEmbeddings()vectorstore FAISS.from_documents(chunks, embeddings)retriever vectorstore.as_retriever(search_kwargs{k: 4})chain RetrievalQA.from_chain_type(llmllm, retrieverretriever)七行每行一个组件每个组件有三五个参数要调。跑通容易调好难。我上个月做一个内部知识库问答光调chunk_size就试了 8 组500 太碎语义断裂2000 太粗检索精度差1000 勉强能用但碰到表格就乱切。再加上chunk_overlap、search_kwargs、similarity_score_threshold……排列组合下来调参空间比模型微调还大。更头疼的是调试。用户问退货政策是什么系统返回了物流时效的内容——到底是 embedding 质量问题、chunk 切割问题、还是 retriever 的 top_k 太小LangChain 的 chain 是黑盒中间过程看不到只能加一堆print或者接 LangSmith。直到看 DeepAgents 的 RAG 集成方式发现它换了个思路RAG 不是一条 chain而是一个工具。Agent 自己决定什么时候检索、检索什么、怎么用检索结果。这是 Day 10 的笔记把这个思路讲清楚。阅读提示适合谁看用 LangChain 做过 RAG觉得 chain 太重、调试太难看完能做什么用 DeepAgents 搭一个文档问答 Agent能加载 Markdown 文件、向量检索、上下文注入带走什么判断什么场景该用 RAG-as-Tool什么场景还是需要独立的 RAG pipeline全文约 14 分钟一、全局地图Day 10 在哪一层12 天计划进入第三阶段——工程化能力Day 9 讲了容错与可观测性错误处理、重试、TracingDay 10本篇讲 RAG 集成Day 11 讲综合项目实现Day 12 讲测试优化与总结RAG 是 Agent 从靠 prompt 硬编进化到有知识库支撑的关键一步。Day 4-8 讲的 Agent、Tool、Memory、Workflow、Multi-Agent 都是在处理怎么做事RAG 解决的是从哪获取知识。图 1RAG Pipeline 数据流二、先搞清楚LangChain 的 RAG Chain 到底重在哪LangChain 的 RAG 实现是一条线性 pipelineDocumentLoader → TextSplitter → Embeddings → VectorStore → Retriever → Chain → LLM每个环节一个类串起来就是一条 chain。问题是组件太多。光 loader 就有DirectoryLoader、WebLoader、NotionLoader、PDFLoader……每种 loader 返回的 Document 格式不完全一致splitter 要适配。耦合太紧。Retriever 和 Chain 绑在一起想换一种检索策略比如先 BM25 再向量要重写整条链。调试太难。chain 是黑盒中间结果chunks、scores、context要加 callback 或者接 LangSmith 才能看到。和 Agent 集成很别扭。想让 Agent 自己决定要不要检索要么用AgentExecutorretriever_tool要么自己写tool装饰器把 retriever 包起来。我在实际项目里最常见的痛苦是第 4 点RAG 和 Agent 是两套逻辑拼起来很割裂。Agent 用 ReAct 循环RAG 用 chain 调用两者的状态管理、错误处理、超时控制都不一样。三、DeepAgents 的做法RAG 是一个 ToolDeepAgents 的核心设计是一切能力都是工具RAG 也不例外。你不需要写一条 RAG chain。你只需要准备好 VectorStoreFAISS / Chroma / Pinecone把检索能力封装成一个 Tool把 Tool 注册给 AgentAgent 的 LLM 自己决定什么时候调这个工具、怎么用返回的结果。代码 1— 最小 RAG Tool 定义from deepagents import create_deep_agentfrom langchain_community.vectorstores import FAISSfrom langchain_openai import OpenAIEmbeddings# Step 1: 准备 VectorStoreembeddings OpenAIEmbeddings()vectorstore FAISS.load_local(./my_index, embeddings, allow_dangerous_deserializationTrue)retriever vectorstore.as_retriever(search_kwargs{k: 4})# Step 2: 定义 RAG Tooldef search_docs(query: str) - str: 搜索内部文档库返回与查询最相关的文档片段。 docs retriever.invoke(query) results [] for i, doc in enumerate(docs): results.append(f[{i1}] {doc.page_content}\n(source: {doc.metadata.get(source, unknown)})) return \n\n---\n\n.join(results)# Step 3: 注册给 Agentagent create_deep_agent( modelopenai:gpt-4o, tools[search_docs], system_prompt( 你是内部知识库问答助手。用户提问时先用 search_docs 检索相关文档 然后根据检索结果回答。如果文档里没有相关信息诚实说不知道。 ),)result agent.invoke({messages: [{role: user, content: 退货政策是什么}]})对比一下 LangChain 版的代码量LangChain 版要实例化 5-6 个组件、串 chain、配 callbackDeepAgents 版就是一个函数 一个create_deep_agent。关键差异在 LangChain 里RAG 是一条预定义的执行路径在 DeepAgents 里RAG 是 Agent按需调用的工具。Agent 可以先检索、再调其他工具、再检索、再回答——它自己决定执行顺序。四、文档加载与分块DeepAgents 怎么处理文档加载和分块是 RAG 的第一步也是最容易被低估的一步。4.1 文档加载DeepAgents 本身不提供 loader——它复用 LangChain 的DocumentLoader体系。这一点要讲清楚事实DeepAgents 没有重新发明 loader。DirectoryLoader、WebLoader、PDFLoader这些 LangChain 组件照常用加载出来的Document对象格式也一样。代码 2— 加载 Markdown 文档from langchain_community.document_loaders import DirectoryLoader, TextLoaderloader DirectoryLoader( ./docs, glob**/*.md, loader_clsTextLoader, loader_kwargs{encoding: utf-8},)docs loader.load()print(f加载了 {len(docs)} 个文档)4.2 分块策略分块也复用 LangChain 的TextSplitter。但这里有一个工程判断值得说chunk_size 的选择不是技术问题是业务问题。你的文档是短段落 FAQ每条 100-300 字→chunk_size500就够甚至不用切你的文档是长篇技术文档每段 500-1500 字→chunk_size800-1200overlap100-200你的文档有表格 → 先用结构化 loader如UnstructuredHTMLLoader再按语义切分我自己的经验判断先用默认值跑通再根据检索效果反调。具体来说先用chunk_size1000, overlap200跑一轮找几个典型 query看 retriever 返回的 chunks 是否切在语义完整的位置如果发现答案被切断了 → 增大 overlap如果发现返回的内容太杂、不相关 → 减小 chunk_size代码 3— 分块from langchain_text_splitters import RecursiveCharacterTextSplittersplitter RecursiveCharacterTextSplitter( chunk_size1000, chunk_overlap200, separators[\n\n, \n, 。, , , ., , ],)chunks splitter.split_documents(docs)print(f切分为 {len(chunks)} 个 chunks)注意separators参数。默认值是英文分隔符\n\n,\n,.等处理中文文档时建议加上中文句号、感叹号、问号。五、向量化与存储选什么、怎么选向量化是把文本变成向量存储是把向量存起来供检索。DeepAgents 不绑定特定的 VectorStore——任何实现了 LangChainVectorStore接口的都可以用。场景推荐理由本地开发 / PoCFAISS零依赖纯本地不需要服务小团队 / 几百个文档Chroma轻量 server支持持久化生产 / 大规模Pinecone / Weaviate / Milvus托管服务有监控、备份、扩展代码 4— 向量化 存储FAISSfrom langchain_openai import OpenAIEmbeddingsfrom langchain_community.vectorstores import FAISSembeddings OpenAIEmbeddings(modeltext-embedding-3-small)vectorstore FAISS.from_documents(chunks, embeddings)vectorstore.save_local(./my_index)一个容易踩的坑embedding 模型要一致。你建索引时用text-embedding-3-small查询时也必须用同一个模型。我见过有人建索引用text-embedding-ada-002查询用text-embedding-3-small结果检索精度直接腰斩——因为两个模型的向量空间不一样。六、检索与上下文注入Agent 怎么用检索结果这是 RAG 和 Agent 结合最关键的部分。在 LangChain 的 RAG chain 里检索结果是自动注入到 LLM prompt 里的——chain 帮你做了这一步。你不需要管。在 DeepAgents 里检索结果是通过 Tool 返回值进入 Agent 的推理循环的。Agent 调用search_docs→ 得到字符串结果 → LLM 看到结果 → 决定怎么回答。图 2RAG Agent 架构这两种方式的区别维度LangChain RAG ChainDeepAgents RAG-as-Tool检索时机chain 执行时自动检索Agent LLM 决定是否检索检索次数通常 1 次Agent 可以多次检索改 query 重试结果处理chain 自动拼接Agent LLM 理解后决定怎么用多工具协作难chain 和 tool 是两套自然RAG 只是众多 tool 之一调试callback / LangSmithTool call 日志直接看我倾向的判断经验判断如果你的场景是纯问答用户问、系统答、不需要调其他工具LangChain RAG chain 更简单直接如果你的场景是Agent 需要先查资料、再调 API、再综合回答DeepAgents 的 RAG-as-Tool 更合适七、最小实验完整 RAG 问答 Agent实验条件环境DeepAgents 0.2.xLangChain 0.3.xPython 3.11输入一组 Markdown 文档放在./docs目录用户问如何配置 CI/CD预期观察Agent 调用search_docs检索 → 拿到相关文档 → 生成回答代码 5— 完整可运行示例from langchain_community.document_loaders import DirectoryLoader, TextLoaderfrom langchain_text_splitters import RecursiveCharacterTextSplitterfrom langchain_openai import OpenAIEmbeddingsfrom langchain_community.vectorstores import FAISSfrom deepagents import create_deep_agent# 1. 加载文档loader DirectoryLoader(./docs, glob**/*.md, loader_clsTextLoader)docs loader.load()# 2. 分块splitter RecursiveCharacterTextSplitter(chunk_size1000, chunk_overlap200)chunks splitter.split_documents(docs)# 3. 向量化 存储embeddings OpenAIEmbeddings(modeltext-embedding-3-small)vectorstore FAISS.from_documents(chunks, embeddings)# 4. 定义 RAG Toolretriever vectorstore.as_retriever(search_kwargs{k: 4})def search_docs(query: str) - str: 搜索内部文档库返回与查询最相关的文档片段。 docs retriever.invoke(query) if not docs: return 没有找到相关文档。 results [] for i, doc in enumerate(docs): source doc.metadata.get(source, unknown) results.append(f[{i1}] ({source})\n{doc.page_content}) return \n\n---\n\n.join(results)# 5. 创建 Agentagent create_deep_agent( modelopenai:gpt-4o, tools[search_docs], system_prompt( 你是内部知识库问答助手。\n 用户提问时先用 search_docs 检索相关文档。\n 根据检索结果回答引用文档来源。\n 如果文档里没有相关信息诚实说不知道。 ),)# 6. 运行result agent.invoke( {messages: [{role: user, content: 如何配置 CI/CD}]})print(result[messages][-1].content)你应该看到的日志[agent] 收到用户问题如何配置 CI/CD[agent] - tool_call: search_docs(queryCI/CD 配置)[search_docs] 返回 4 个相关文档片段[agent] 根据检索结果生成回答[agent] 根据文档配置 CI/CD 的步骤如下...如果结果不符合预期先看哪里Agent 没调search_docs直接用 LLM 知识回答 →system_prompt没强调必须先检索检索结果不相关 → 检查 embedding 模型是否一致chunk 切割是否合理检索结果正确但回答错误 → LLM 可能没理解 context试试增大k值或优化 prompt报错allow_dangerous_deserialization→ FAISS 加载本地索引需要显式允许这是安全设计八、踩坑记录坑 1Chunk 切割把表格切碎了现象文档里有一个 5 行的配置参数表被 splitter 从第 3 行切开。检索到的 chunk 只有半张表Agent 回答时缺了关键参数。原因RecursiveCharacterTextSplitter按字符数切分不认表格结构。解法对包含表格的文档先用MarkdownHeaderTextSplitter按标题切分再对每个 section 做字符级切分。或者用UnstructuredMarkdownLoader的modeelements按元素切分。坑 2检索结果重复度太高现象同一个文档被切成了 10 个 chunk检索 top_k4 返回的 4 个 chunk 都来自同一篇文档内容高度重复。原因文档很长chunks 之间 overlap 大向量相似度都很高。解法用 MMRMaximal Marginal Relevance检索策略。vectorstore.as_retriever(search_typemmr, search_kwargs{k: 4, fetch_k: 20})。MMR 会在保证相关性的同时降低结果重复度。坑 3Agent 每次都检索不管问题是否需要现象用户问你好、谢谢这种不需要检索的问题Agent 也调了search_docs。原因system_prompt写的是用户提问时先用 search_docs 检索太绝对了。解法改 prompt 为用户提问时如果问题涉及内部知识用 search_docs 检索如果是闲聊或通用问题直接回答。坑 4Embedding 模型不一致现象建索引时用text-embedding-ada-002查询时换了text-embedding-3-small检索精度断崖式下降。原因两个模型的向量维度和训练数据不同向量空间不兼容。解法建索引和查询必须用同一个 embedding 模型。如果要换模型需要重建整个索引。九、什么时候该用 RAG-as-Tool什么时候用独立 RAG Pipeline更适合 RAG-as-ToolAgent 需要结合检索结果和其他工具API、数据库综合回答查询意图不确定需要 LLM 判断是否检索多轮对话中需要动态调整检索策略更适合独立 RAG Pipeline纯问答场景用户问、系统答不需要调其他工具对延迟极度敏感RAG chain 比 Agent 少一轮 LLM 调用检索逻辑复杂混合检索、重排序、多路召回需要精细控制成本突然变高的点Agent 每次都检索 多轮对话 → embedding API 调用量翻倍3 问判断法Agent 除了检索还需要调用其他工具API、数据库、代码执行吗用户的问题是否需要 LLM 判断该不该检索你是否需要看到 Agent 的完整推理过程包括为什么检索、怎么用检索结果如果 3 个问题都是是用 RAG-as-Tool。如果都是否独立 RAG Pipeline 更简单。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】