LangChain实战:从0到1构建RAG知识库问答与AI Agent

发布时间:2026/9/1 7:52:38
LangChain实战:从0到1构建RAG知识库问答与AI Agent 很多同学在入门 AI 应用开发时都会经历一段“资料很多、但不知道从哪下手”的阶段大模型 API 调通了却只会写聊天机器人RAG 的词听熟了却不知道怎么用在自己的文档上看到 LangChain 教程一大把跟着敲完又发现版本升级后 API 全变了。这篇文章不打算重复那种“贴一段官方 demo 就结束”的教程而是按照一条从 0 到 1 的实战路线完整拆解 RAG 知识库问答和 AI Agent 的构建过程并把学习过程中最容易踩的坑一起梳理清楚。适合刚接触 LangChain 的新手也适合需要快速在项目中落地 RAG 或 Agent 的开发者。文章会先讲清楚概念再带你把环境搭建起来然后分别完成一个可运行的 RAG 问答链路和一个支持工具调用的 Agent最后补充常见报错、工程化经验和一套 36 讲学习路径。跟着本文走完一遍你会对 LangChain 的项目结构、核心抽象、调试方式和优化方向有整体认识不再是被动抄代码而是能根据自己的场景做裁切。1. 为什么都在学 RAG 与 AI Agent1.1 纯大模型推理的边界先从一个很现实的问题出发企业里想用大模型回答业务问题最常见的方式是直接把问题丢给 GPT 这类模型。但你很快会发现几个问题。第一是知识时效性。大模型的训练数据往往截止到某个时间点新上线的产品、新发布的政策、内部的规章制度它根本不知道。第二是领域知识缺失。模型没有读过你的私有文档、项目方案、售后工单你问它公司内部某个流程它只能凭常识编一个答案这在严肃场景下非常危险。第三是成本问题。把一个 1000 页的规章制度全部塞进 Prompt 里让模型回答Token 消耗巨大而且超出上下文窗口后根本没法治。这些边界决定了想在实际业务里用大模型不能只靠模型本身的“记忆”必须给模型接上外部数据和外部工具。这就是 RAG 和 AI Agent 出现的原因。1.2 RAG 解决什么问题RAG 的全称是 Retrieval-Augmented Generation检索增强生成。它的核心思路很简单在让大模型回答问题之前先从你的知识库或文档库里把相关内容“检索”出来然后把“用户问题 检索到的资料”一起交给大模型生成答案。这样做的好处非常明显模型不再凭记忆硬编而是基于你提供的最新、最准确的资料做回答答案有出处、可追溯同时你不需要把整个知识库塞进 Prompt每次只取最相关的几个片段Token 成本可控更重要的是文档更新后重新建立索引即可不需要重新训练模型。常见落地场景包括企业知识库问答、产品文档智能客服、财报和研报分析、合同审核辅助、针对特定协议或规范的技术问答等。后面实战部分我会以一个本地文本文档作为知识库完整跑通这个流程。1.3 AI Agent 解决什么问题如果说 RAG 解决的是“让模型知道更多知识”那么 AI Agent 解决的就是“让模型能做更多事情”。大模型本质上是一个文本生成器它不能直接查数据库、调用接口、操作文件。Agent 的思路是给模型配备一系列“工具Tool”让模型在回答问题的过程中自主决定调用哪个工具、传入什么参数、拿到结果后再继续推理直到完成一个目标。比如一句话“帮我算出本月销售额并把异常订单整理成表格”Agent 会拆解成多个步骤先查询数据库再计算结果再生成表格每一步都可能有工具参与。这种“推理 行动”的循环常见框架叫 ReAct也就是思考Thought、行动Action、观察Observation交替进行。LangChain 把这种机制封装成了 Agent 模块后面我们会用一个具体例子把它跑起来。1.4 本文的学习脉络结合标题里“从0到1”的定位本文的路线是五步递进搞清楚 RAG、Agent、LangChain 三个核心概念。搭建可运行的 Python 开发环境。掌握 LangChain 的模型、Prompt、输出解析和记忆等基础能力。从 0 到 1 构建一个 RAG 知识库问答。从 0 到 1 构建一个支持工具调用的 AI Agent。每一步都包含可直接复制的代码最后统一梳理常见问题和工程最佳实践。2. 核心概念RAG、Agent 与 LangChain2.1 LangChain 是什么LangChain 是一个用于构建大模型应用的开源开发框架。它把大模型应用里的常见组件抽象成了统一接口模型封装、Prompt 管理、文档加载、文本切分、向量存储、检索、工具、记忆、Agent 等。你当然可以用原生代码自己实现这些组件但 LangChain 的价值在于“标准化组合”。今天你用的是 OpenAI 的模型明天可能换成国产模型或本地部署模型只要它们兼容同一套调用协议业务层代码可以基本不动。这也是为什么很多团队把 LangChain 作为 AI 应用开发的首选框架。需要提醒的是LangChain 迭代速度非常快版本升级偶尔会带来 API 变化。本文示例以当前常见稳定版本为准如果你使用的版本较新个别模块的导入路径可能不同请以官方文档为准。2.2 LangGraph 与 LangChain 的关系现在很多资料里同时出现 LangChain 和 LangGraph初学者容易混淆。可以这样理解LangChain 提供的是构建大模型应用的“基础零件”比如模型封装、工具、检索器而 LangGraph 是一个偏底层的编排框架专门用来构建有状态、多节点、可循环的复杂 Agent 工作流。普通的分步任务用 LangChain 的 Chain 就够了但一旦你的 Agent 需要维护复杂状态、需要人工审批节点、需要平行分支或循环执行LangGraph 是更合适的选择。学习顺序上先掌握 LangChain 的基本用法再根据项目复杂度决定要不要上 LangGraph不建议一上来就钻进框架的内核否则容易被概念淹没。2.3 RAG 流程里的三个关键动作RAG 的全流程可以压缩成三个动作。一是索引Indexing把文档读进来切成小块做向量化存入向量数据库。二是检索Retrieval用户提问后把问题也向量化在向量库里找最相似的 TopK 个片段。三是生成Generation把原始问题和检索到的片段拼成 Prompt交给大模型生成答案。这三点听起来简单但每一步都有大量可优化的细节切分粒度怎么定、Embedding 模型怎么选、检索结果怎么做重排、Prompt 怎么写才能避免模型编造。后面实战部分我会逐个演示。3. 环境准备搭建 LangChain 开发环境3.1 版本与 Python 环境说明本文示例使用 Python 3.10 及以上版本操作系统不限Windows、macOS、Linux 都可以。LangChain 以及周边组件的包名比较多不同版本之间存在依赖关系建议你在正式项目中使用虚拟环境管理依赖避免全局环境被搞乱。版本方面我不写死因为 LangChain 迭代很快固定某个老版本反而不利于后续学习。你只需要安装时保证各 langchain 相关包的大版本一致即可比如都使用 0.3.x 的稳定版本线。如果你的项目已有依赖约束请以实际项目为准。3.2 创建虚拟环境并安装依赖打开终端依次执行下面的命令。以 macOS 和 Linux 为例Windows 下激活命令略有不同我会在注释里标注。# 创建虚拟环境 python -m venv .venv # 激活虚拟环境 # macOS / Linux: source .venv/bin/activate # Windows: # .venv\Scripts\activate # 升级 pip避免安装时解析依赖出问题 python -m pip install --upgrade pip接着安装核心依赖。为了便于复现我准备了一个 requirements.txt你在项目根目录创建同名文件写入以下内容langchain langchain-openai langchain-community langchain-text-splitters langchain-chroma chromadb python-dotenv然后执行安装命令pip install -r requirements.txt简单解释一下每个包的作用langchain是主框架langchain-openai提供 OpenAI 接口的模型封装langchain-community包含社区维护的各类文档加载器、工具等langchain-text-splitters负责文本切分langchain-chroma和chromadb提供本地向量数据库python-dotenv用于读取 .env 环境变量文件避免把密钥写进代码。3.3 项目目录结构建议按照下面的结构组织项目方便后续扩展langchain-practice/ ├── .env # 环境变量API Key 等不进 Git ├── requirements.txt # 依赖清单 ├── docs/ │ └── knowledge.txt # 示例知识库文档 ├── rag_demo.py # RAG 实战代码 └── agent_demo.py # Agent 实战代码在项目根目录创建.env文件写入你的模型服务配置OPENAI_API_KEY你的密钥如果你使用的是兼容 OpenAI 协议的本地模型服务或第三方平台可以额外指定接口地址和模型名LangChain 的支持方式是在模型对象里传base_url参数这块我们稍后说明。3.4 最小可运行验证环境装好后先写一段最简单的代码验证链路是否通畅。在项目根目录创建hello_llm.pyimport os from dotenv import load_dotenv from langchain_openai import ChatOpenAI load_dotenv() llm ChatOpenAI( modelgpt-4o-mini, temperature0, api_keyos.getenv(OPENAI_API_KEY), ) response llm.invoke(请用一句话介绍检索增强生成) print(response.content)运行python hello_llm.py如果能看到模型输出一段关于大数据、语义搜索、自动生成报表的介绍说明环境已经没问题了。接下来可以开始正式学习 LangChain 的核心组件。4. LangChain 核心能力拆解4.1 模型封装ChatModelsLangChain 把大模型封装成统一的接口最常用的是ChatOpenAI。它和直接调用 OpenAI API 相比有几点优势接口统一切换模型厂商时不用重写业务逻辑支持流式输出、异步调用、回调监控等高级能力可以和其他 LangChain 组件无缝组合。上面已经写过最小示例这里补充一个关键参数说明model模型名称需要与你使用的服务商保持一致。temperature控制随机性0 表示基本不随机适合问答和抽取任务0.7 以上适合创意写作。api_key密钥生产环境务必通过环境变量注入不要硬编码。max_tokens限制单次生成的最大 Token 数防止长文本把成本打爆。如果你使用 Ollama 本地部署的模型可以安装langchain-ollama包使用ChatOllama如果使用 vLLM 这类高性能推理服务通常它暴露的是 OpenAI 兼容接口直接用ChatOpenAI并指定base_url即可。核心思想是“语言模型统一抽象”业务代码不关心底层实现。4.2 Prompt 模板Prompt 模板的价值在于把“固定的指令”和“变化的输入”分离。你可能要反复回答不同用户的问题但系统指令、回答格式、约束条件是固定的。用模板管理代码会清爽很多。下面是一个带变量的例子from langchain_core.prompts import ChatPromptTemplate prompt ChatPromptTemplate.from_messages([ (system, 你是一个严谨的技术问答助手请用简洁、准确的中文回答问题。), (human, 问题{question}), ]) formatted prompt.format_messages(question什么是向量数据库) print(formatted)from_messages里的每一项是一个角色消息模板变量用花括号占位。在实际 RAG 应用中系统指令里通常还会加入“请只基于以下上下文回答不要编造”这类约束这就是防止大模型幻觉的关键手段之一。4.3 输出解析器大模型返回的是文本但你的下游程序可能需要 JSON、Markdown 列表、布尔值等结构化的内容。输出解析器OutputParser就负责把大模型的原始输出解析成可用结构。最常用的是StrOutputParser它直接把消息内容转成字符串。如果模型配置了response_format支持 JSON 模式可以配合JsonOutputParser使用。下面是一个组合示例from langchain_openai import ChatOpenAI from langchain_core.output_parsers import StrOutputParser llm ChatOpenAI(modelgpt-4o-mini, temperature0) parser StrOutputParser() chain llm | parser result chain.invoke(用一句话解释什么是 Token) print(result)这里的|是 LangChain 表达式语法LCEL中的管道操作非常像 Unix 管道llm输出传给parser最终得到字符串结果。LCEL 是 LangChain 里非常核心的抽象后面的 RAG 链路也会用它组合多个组件。4.4 记忆机制默认情况下每次调用大模型都是独立的一次对话模型不记得你上一句说了什么。要让模型具备对话的连续性需要把历史消息一起传入。LangChain 提供了多种记忆实现最简单的是把历史消息放在变量里手动拼接。在 Agent 场景中记忆更是关键否则 Agent 会在多轮工具调用之间丢失用户的原始意图。下面是一个带记忆的最小对话示例这里用langchain_core.messages里的消息对象来组织历史from langchain_core.messages import HumanMessage, AIMessage from langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-4o-mini, temperature0) history [ HumanMessage(content我的名字叫小明), AIMessage(content你好小明很高兴认识你), ] response llm.invoke(history [HumanMessage(content我叫什么名字)]) print(response.content)实际项目中你需要自己维护history列表并在每次对话后追加最新的消息。更复杂的会话存储、滑动窗口裁剪、摘要式记忆等能力LangChain 也有对应封装但背后思路都是“把历史作为上下文的一部分传给模型”。5. 从 0 到 1 构建 RAG 知识库问答5.1 准备示例知识文档为了跑通 RAG我们需要一份本地知识库。这里我准备了一个简短的文档docs/knowledge.txt内容是关于 RAG 和 Agent 的一些介绍相当于你要让模型“学习”的内部资料检索增强生成Retrieval-Augmented Generation简称 RAG是一种结合信息检索与大语言模型生成能力的技术架构。它的核心思想是在模型回答之前先从外部知识库中检索与用户问题相关的文档片段再将这些片段与原始问题一起输入大模型从而生成更准确、更可靠的答案。 RAG 的典型流程包括文档加载、文本切分、向量化、向量存储、检索和生成。文档切分时需要选择合适的块大小chunk_size和重叠长度chunk_overlap过大容易丢失细粒度语义过小则会破坏上下文连贯性。 AI Agent智能代理是指能够根据用户目标自主规划、调用工具并逐步完成任务的智能系统。Agent 通常具备工具调用、记忆、规划和反思等能力。在 LangChain 中Agent 通过定义工具列表让大模型决定调用哪个工具以及传入什么参数。 LangGraph 是一个用于构建有状态和复杂工作流的大模型应用编排框架适合多节点、循环、条件分支等复杂场景。你完全可以用自己的文档替换它比如一份产品说明、规章制度的摘录只要能通过TextLoader读进来即可。5.2 文档加载与文本切分RAG 的第一步是加载文档。TextLoader是最简单的加载器适合纯文本文件。如果你的资料是 PDF、Word、网页LangChain 也提供了对应的加载器比如PyPDFLoader、Docx2txtLoader等加载思路基本一样把文件内容读取成Document对象列表。文档加载后往往很长无法直接作为 Prompt 的一部分。文本切分器的职责就是把它切成合适粒度的小块。RecursiveCharacterTextSplitter会按优先级尝试按换行符、句号、空格等分隔符递归切分尽量保证语义连续。from langchain_community.document_loaders import TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter loader TextLoader(docs/knowledge.txt, encodingutf-8) documents loader.load() splitter RecursiveCharacterTextSplitter( chunk_size300, chunk_overlap50, separators[\n\n, \n, 。, , , , ], ) chunks splitter.split_documents(documents) print(f原文共 {len(documents)} 篇切分为 {len(chunks)} 个小块) for i, chunk in enumerate(chunks): print(f\n--- 第 {i 1} 块 ---) print(chunk.page_content)关于参数选择chunk_size是每块的最大字符数chunk_overlap是相邻块之间的重叠长度作用是避免句子被从中间切断导致语义丢失。示例中用 300/50 是为了方便查看效果实际项目中建议根据文档类型测试 500 到 1000 之间的大小再结合后续检索效果调整。5.3 向量化与向量库文本切分完成后需要把每一块转成向量。这个向量化过程由 Embedding 模型完成。它的特点是语义接近的文本在向量空间里距离更近。比如“怎么申请报销”和“报销流程是什么”这两句话字面不同但向量相似度会很高。这里使用OpenAIEmbeddings默认模型是text-embedding-3-small对中文支持不错。向量库选择 Chroma它支持本地持久化开发调试非常方便不需要额外部署服务。from langchain_openai import OpenAIEmbeddings from langchain_chroma import Chroma embeddings OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory./chroma_db, ) print(f已写入向量库文档块数量{vectorstore._collection.count()})这段代码会把切分好的文档块向量化并写入本地目录chroma_db。下次启动应用时如果知识库内容没有变化可以直接用Chroma(persist_directory./chroma_db, embedding_functionembeddings)加载而不用重新构建索引。5.4 构建检索与生成链路向量库建好后剩下的事情是接收问题、检索相关片段、组装 Prompt、调用模型生成答案。我先把核心代码写出来再逐行解释。import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain_chroma import Chroma from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser load_dotenv() # 1. 加载已持久化的向量库 embeddings OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore Chroma(persist_directory./chroma_db, embedding_functionembeddings) # 2. 创建检索器取最相似的 4 个片段 retriever vectorstore.as_retriever(search_kwargs{k: 4}) # 3. 定义 Prompt强调基于上下文回答 prompt ChatPromptTemplate.from_messages([ (system, 你是一个知识库问答助手。请只根据给定的上下文回答问题 不要依赖你的预先知识编造答案。如果上下文中没有相关内容请直接回答“资料中未找到相关信息”。), (human, 上下文\n{context}\n\n问题{question}), ]) llm ChatOpenAI(modelgpt-4o-mini, temperature0) parser StrOutputParser() # 4. 定义检索格式化函数 def retrieve_context(question: str) - str: docs retriever.invoke(question) return \n\n.join(doc.page_content for doc in docs) # 5. 组合成最终问答函数 def ask(question: str) - str: context retrieve_context(question) chain prompt | llm | parser return chain.invoke({context: context, question: question}) if __name__ __main__: result ask(RAG 的典型流程包括哪些步骤) print(result)解释几个关键点。vectorstore.as_retriever(search_kwargs{k: 4})把向量库包装成检索器k4表示每次返回与问题最相似的 4 个片段。这个值直接影响答案质量设置太少容易漏掉关键信息设置太多会把噪声塞进上下文。Prompt 里的约束很重要“只根据给定上下文回答不要编造”。RAG 项目最常见的翻车点就是模型把上下文当作“参考”仍然按自己的记忆生成答案。把这句话写进系统提示词能显著降低幻觉风险。最后用 LCEL 把prompt | llm | parser串起来输入一个包含context和question的字典输出字符串答案。5.5 运行与验证保存为rag_demo.py在项目根目录执行python rag_demo.py预期输出大致是RAG 的典型流程包括文档加载、文本切分、向量化、向量存储、检索和生成。注意这个问题在知识库里是有原文的所以模型能给出准确答案。你可以再问一个知识库里没有的问题比如“明天会下雨吗”观察模型是否按 Prompt 约束回答“资料中未找到相关信息”。这一步能直观验证 RAG 的“可约束性”到底有没有生效。如果想验证检索效果可以把retriever.invoke的结果打印出来看看模型用到的上下文到底是什么。很多线上 RAG 效果不佳问题不在生成环节而在检索环节——用户问题在向量空间里没找到正确的片段答案自然不对。6. 从 0 到 1 构建 AI Agent6.1 Agent 的核心机制RAG 解决的是“让模型知道更多信息”但模型仍然只能“说”不能“做”。Agent 要解决的是让模型能够调用外部工具完成一个多步骤目标。以一个常见场景为例用户说“帮我算一下 24 乘以 7然后查一下北京今天的天气”。如果只调大模型它算乘法经常出错更不可能知道你所在城市的实时天气。但如果你给模型配备一个计算器工具和一个天气查询工具模型就能自己组合调用先调计算器拿到结果再调天气工具拿到天气最后把两部分信息整理成自然语言回答。这个过程的循环逻辑就是 ReAct模型先思考Thought“用户需要两个信息我可以先用计算器工具”然后行动Action调用工具得到观察结果Observation后继续思考下一步直到信息齐全后给出最终答案Final Answer。6.2 自定义 Tool在 LangChain 里定义一个工具最简洁的方式是使用tool装饰器。工具需要有一个函数名、一段清晰的功能描述、以及参数注解。函数名和描述会被大模型看到所以描述必须写清楚“这个工具是做什么的”“适合什么场景”这对模型能否正确选择工具至关重要。下面定义两个演示工具。第一个是计算器第二个是模拟的天气查询工具。from langchain_core.tools import tool tool def calculate(expression: str) - str: 计算数学表达式的结果。输入必须是数学表达式例如 24 * 7 或 100 / 4。 try: result eval(expression) return f计算结果{result} except Exception as e: return f计算失败请检查表达式是否正确。错误信息{str(e)}关于eval需要特别提醒eval执行任意字符串表达式存在安全风险生产环境千万不要直接用来处理不可信的外部输入。这里只是为了演示工具定义方式更安全的做法是使用ast.literal_eval或专门的数学表达式解析库。如果你要在生产环境实现计算能力请务必做输入校验。tool def get_city_weather(city: str) - str: 查询指定城市的实时天气情况输入为城市名称例如 北京。 # 演示代码实际项目请接入真实天气 API return f{city} 今天晴转多云气温 18~26℃东南风 2 级6.3 创建 Agent 并执行有了工具之后把模型和工具交给create_tool_calling_agent再用AgentExecutor来实际执行。下面是一个完整可运行的agent_demo.pyimport os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain.agents import create_tool_calling_agent, AgentExecutor load_dotenv() llm ChatOpenAI(modelgpt-4o-mini, temperature0) tools [calculate, get_city_weather] prompt ChatPromptTemplate.from_messages([ (system, 你是一个智能助手可以调用工具来帮助用户完成任务。 请结合工具返回的结果给用户简洁、完整的中文回答。), (human, {input}), (placeholder, {agent_scratchpad}), ]) agent create_tool_calling_agent(llm, tools, prompt) executor AgentExecutor(agentagent, toolstools, verboseTrue) result executor.invoke({ input: 帮我计算 24 * 7 的结果然后查询一下北京今天的天气情况 }) print(\n最终答案, result[output])这里的placeholder消息是 Agent 工作区的固定写法Agent 在执行过程中会把自己的中间推理过程和工具调用记录放在agent_scratchpad里框架会自动管理不需要你手动拼消息。运行命令python agent_demo.py设置verboseTrue后控制台会打印 Agent 的完整执行过程包括它选择了哪些工具、工具返回了什么结果这对学习调试非常有帮助。6.4 理解 Agent 的执行日志上面代码运行后你会看到类似下面的日志 Entering new AgentExecutor chain... Invoking: calculate with {expression: 24 * 7} 计算结果168 Invoking: get_city_weather with {city: 北京} 北京 今天晴转多云气温 18~26℃东南风 2 级 Finished chain.从日志可以很清楚地看到 Agent 的决策链路模型从用户问题里识别出两个子任务分别选择了正确的工具、传入正确的参数最后把两个结果汇总成回答。这就是“智能代理”的核心价值。在生产项目中工具往往不止两个可能是数据库查询接口、业务系统 REST API、文件导出服务等。模型是否能选对工具、传对参数很大程度取决于你的工具描述是否准确。描述含糊时模型就会“乱点工具”。这一点在工程化部分会重点展开。7. 常见问题与排查思路LangChain 开发生态变化快运行时报错种类也多。下面整理几个新手最高频的问题按“现象、原因、解决”的顺序说明。问题现象常见原因解决思路调用模型报 401 / AuthenticationErrorAPI Key 写错、未加载 .env、密钥过期检查 .env 文件确认load_dotenv()已调用打印环境变量确认报 ModuleNotFoundError缺少某个 langchain 子包按 requirements.txt 补装依赖注意各子包的大版本保持一致向量库加载报维度不匹配Embedding 模型更换后向量维度变了删除旧的chroma_db目录用新模型重新构建索引Agent 不调用工具直接编答案工具描述不清晰或模型不支持工具调用优化工具 description检查模型是否支持 function calling 能力输出中文乱码终端编码问题确保文件头部# -*- coding: utf-8 -*-终端设置为 UTF-8Prompt 太长超过上下文窗口chunk_size 或 k 值设置过大调小chunk_size、k值或使用支持更长上下文的模型下面挑三个重点展开。首先是 API Key 相关报错。dotenv加载.env文件时文件必须位于当前工作目录并且load_dotenv()要在创建模型之前调用。排查时可以在代码里加一行print(os.getenv(OPENAI_API_KEY))确认密钥是否真的读到了。如果输出None说明是加载路径问题而不是密钥本身的问题。其次是依赖版本冲突。LangChain 主包和子包分开维护如果你的langchain是 0.2langchain-openai却装成了 0.1某些 API 就会出现兼容问题。建议在虚拟环境里执行pip list | grep langchain查看版本尽量把主版本统一到同一大版本。特别注意langchain、langchain-core、langchain-community的版本要匹配。最后是 Agent 不调工具的奇葩现象。有些同学发现 Agent 总是拒绝调用工具直接凭记忆回答。原因一般是两个一是模型本身不支持工具调用你在使用一些老模型或本地小模型时可能遇到这种问题二是工具的描述写得像废话模型读了也判断不出来该在什么时候用。把工具描述改成“当用户需要计算 X 时使用本工具”这种明确句式通常能改善很多。8. 工程化最佳实践8.1 RAG 效果优化方向RAG 跑通只是开始真正麻烦的是把效果调到可用。按优先级排序我建议你先关注这些方向。第一文档切分策略。切分不是越大越好也不是越小越好。你可以把不同chunk_size下的检索结果打印出来看返回片段是否准确命中问题需要的段落。必要时可以按文档结构切分比如先按 Markdown 标题、PDF 章节切再在块内做二次细分。第二检索策略。纯粹的向量相似度在中文场景不一定够用关键词完全一致也很重要。建议尝试混合检索向量 关键词再做结果合并这叫混合搜索。检索回 TopK 片段后还可以再加一个重排模型Reranker对候选片段重新打分排序最终只把质量最高的几个片段送给大模型。第三上下文组织。多个检索片段拼接进 Prompt 时要保留来源信息比如“片段 1 来自 xx.pdf 第 3 节”。这样答案后面如果要做引用溯源你的系统才能给出依据。Prompt 里也建议明确告诉模型“标注引用来源”。8.2 用指标衡量 RAG 质量没有指标优化就是盲人摸象。业内常见的 RAG 评估维度有三个上下文相关性Context Relevance检索到的片段是否真的和问题相关。这个指标衡量的是检索模块。忠实性Faithfulness模型的答案是否忠于检索到的上下文有没有编造上下文里不存在的信息。这个指标衡量的是幻觉风险。答案相关性Answer Relevance最终答案是否回答了用户的问题。你可以人工构建一小批评测问题集把每个问题跑一遍 RAG再逐条打分。很多团队使用 RAGAS 这类评估框架做自动化评估思路是一致的先定标准再量化再对照优化。8.3 Agent 生产落地注意事项Agent 在生产环境比 RAG 的不可控因素更多。核心风险是模型可能调用错误的工具、传入危险参数或者陷入反复调用工具的循环。下面几条建议值得认真对待。第一工具权限最小化。给 Agent 的每个工具只授权执行它完成目标所需的最小范围。比如数据库查询工具应该只允许查询不允许修改、删除如果一定要修改必须加人工确认节点。第二记录完整执行轨迹。Agent 的每次工具调用、参数、返回值都应该落日志方便出问题时复现和审计。特别是涉及业务操作时没有轨迹就意味着无法追责。第三设置执行上限。AgentExecutor或 LangGraph 里可以配置最大迭代次数防止 Agent 因为推理错误无限循环白白消耗 Token。设置超时时间也是同样的目的。8.4 安全与合规边界无论 RAG 还是 Agent安全都是底线。密钥管理方面API Key、数据库密码等敏感信息必须放在环境变量或密钥管理系统里严禁提交到 Git 仓库。.gitignore里一定要包含.env。Prompt 注入方面用户可能在问题里塞入“忽略之前的指令”之类的攻击文本。引入 RAG 后外部文档内容同样可能是注入来源。建议在系统提示词里明确知识库内容的“参考”属性并对输出做敏感词和 PII个人隐私信息过滤。数据权限方面RAG 系统只应该检索用户有权限访问的文档。如果一份文档属于机密那么不管向量库里有没有都不能被普通用户的问题检索出来。实现方式通常是在文档元数据里打权限标签检索时按用户权限过滤。9. 一套 36 讲学习路径建议9.1 分阶段学习安排结合标题里的“36 讲”我按实战推进的节奏给你列一份可执行的学习路径。不需要纠结课程数量本身重点是每个阶段要能动手产出一个小项目。阶段内容课时建议阶段产出基础篇Python 环境、API 调用、Prompt 基础6 讲本地跑通模型问答模型与记忆ChatModels、输出解析、消息历史、记忆类6 讲带上下文的聊天机器人RAG 实战文档加载、切分、Embedding、向量库、检索、重排10 讲知识库问答系统Agent 实战Tool 定义、ReAct、工具调用、多工具协同8 讲具备计算/查询能力的助手LangGraph 与上线状态管理、多节点流程、评估、监控、部署6 讲接近生产环境的完整应用按照这个顺序学你会发现每阶段之间是接着的没有模型调用基础就谈不上 RAG没有 RAG 的文档处理经验就理解不了 Agent 里的工具参数设计。跳着学容易卡在某个环节。9.2 建议的练习项目和延伸方向学习 AI 应用开发项目是检验是否真的学会的唯一标准。我给你三个递进方向的练习建议。第一做个人知识库助手。把你自己的笔记、收藏文章、技术文档丢进去做一个能回答私人问题的助手。这是 RAG 的入门项目数据量小几天能完成。第二做一个能对接内部 API 的 Agent。比如让 Agent 通过 ES REST API 智能分析日志或者对接公司数据平台做查询。这个项目会让你的 Agent 从“演示工具”变成“生产工具”。第三研究 Agent 的评估与稳定性。试着评测同一个 Agent 在 50 个问题上的成功率分析失败原因再优化工具描述和 Prompt。做完这一步你对 Agent 的理解会超过大部分停留在“调通 demo”阶段的同学。关于选型你可以继续关注 LangGraph 在有状态复杂工作流上的用法也可以横向对比 Dify 这样的低代码 RAG 平台。框架只是手段核心能力始终是你对模型、检索、工具编排和业务边界的理解。这些能力都来自反复动手而不是只看不做。9.3 最后的建议如果你刚接触这部分内容不要想着一次把 36 讲全部学完也不要一开始就追求“完美架构”。先把第一个 RAG 跑通把第一个 Agent 跑通哪怕代码写得粗糙至少你完整经历了数据加载、向量化、检索、生成、工具调用这些环节。之后再回头看工程化指标、性能优化、安全加固你会知道每一项优化是在解决什么问题。希望这份从 0 到 1 的实战拆解能帮你少走一些弯路。如果本文对你有帮助建议收藏备用后续我也会继续整理 RAG 检索优化和 Agent 生产落地的实践经验欢迎关注交流。