1. 从零到一AI Agent 到底在解决什么问题很多人第一次接触 AI Agent 这个词脑子里浮现的是科幻电影里那种能自己思考、自己行动的机器人。但真到了动手阶段看到的却是一堆名词LangChain、LangGraph、RAG、MCP、智能体、工具调用、记忆机制……每个词都认识拼在一起就不知道从哪下手了。我刚开始接触这块的时候也一样。翻了一圈教程发现大部分内容要么是官方文档的翻译要么是跑一个 Demo 就结束真正能把 Agent 从概念到落地串起来的少之又少。后来自己踩了不少坑才慢慢理清楚这条链路LLM 是大脑Agent 是让大脑长出手脚的那套机制RAG 是给大脑外挂一个知识库MCP 是统一手脚和大脑之间的通信协议LangChain 和 LangGraph 则是搭建这套系统的工具箱。这套教程面向的是零基础但想真正把 AI Agent 跑起来的人。不管你是做后端的、做产品的还是纯粹对智能体感兴趣想自己搭一个玩只要你能看懂基本的 Python 代码后面这些内容都能跟着走下来。我不会只给你一个能跑的 Demo而是会把每一步为什么这么做、不这么做会出什么问题都讲清楚。1.1 LLM、AI 模型、Agent 三者的关系先把这个最基础的概念理清楚不然后面全是糊涂账。LLM大语言模型是一个具体的模型比如 DeepSeek、GPT、Claude、通义千问这些。它的本质是一个函数输入一段文本输出一段文本。它没有记忆没有手脚不会主动做任何事。你问它一句它答一句仅此而已。AI 模型是一个更大的范畴LLM 只是其中一种。图像识别模型、语音识别模型、推荐模型这些都算 AI 模型。只不过这两年 LLM 太火了很多人说“AI 模型”的时候其实指的就是 LLM。AI Agent则是在 LLM 基础上加了一整套外围机制。它让 LLM 能够记住之前聊过什么记忆、调用外部工具工具调用、自己决定下一步做什么规划、从知识库里查资料RAG。打个比方LLM 是一个很聪明但被关在房间里的人Agent 就是给这个人配了电话、电脑、笔记本和图书馆借书证。所以当你听到有人说“我用 DeepSeek 搭了一个 Agent”他的意思其实是用 DeepSeek 作为底层 LLM外面套了一层 Agent 框架让 DeepSeek 能调工具、能查知识库、能记住上下文。1.2 为什么现在必须学 Agent 开发一个很现实的原因是单纯调用 LLM API 已经不够用了。你直接问 LLM“帮我查一下今天北京的天气”它答不出来因为它没有实时数据。你问它“帮我分析一下我们公司上季度的销售数据”它也不知道因为数据在你自己的数据库里。你让它“帮我把这段代码部署到服务器上”它做不到因为它没有执行权限。Agent 就是来解决这些问题的。它让 LLM 能够通过工具调用去查天气 API、通过 RAG 去检索内部文档、通过代码执行器去跑脚本。这才是 LLM 真正能落地产生价值的地方。从招聘市场也能看出来现在招“AI 应用开发”的岗位JD 里几乎都会提到 LangChain、RAG、Agent 这些关键词。不是说要你造一个大模型出来而是要你能把现有的大模型用起来解决实际业务问题。1.3 这套教程的路线图整个学习路径我把它分成四个阶段每个阶段都有明确的产出物阶段核心内容产出物第一阶段LLM 基础调用 Prompt 工程能稳定调用 LLM API 完成指定任务第二阶段RAG 知识库搭建一个能回答私有文档问题的问答系统第三阶段LangChain Agent 开发一个能调用多种工具的智能体第四阶段LangGraph MCP 企业级实战一个多步骤、多角色协作的复杂 Agent 系统这个顺序不是随便排的。没有第一阶段的基础你连 LLM 的输出都控制不好没有第二阶段你的 Agent 就是个只会闲聊的玩具没有第三阶段你根本理解不了 Agent 的运行机制没有第四阶段你做的东西永远停留在 Demo 级别。2. 环境搭建别在第一步就卡住我见过太多人教程收藏了几十个环境搭了三天没搭起来然后就放弃了。这一章我把环境搭建的每个细节都拆开讲包括那些教程里通常不会提的坑。2.1 Python 环境与 conda 的选择首先说 Python 版本。建议用 Python 3.10 或 3.11不要用 3.12。原因很简单LangChain 和很多相关库对 3.12 的支持还不完善你会在安装依赖的时候遇到各种编译错误。我实测下来3.10 是最稳的3.11 也没问题3.12 就是给自己找麻烦。然后是 conda 还是 venv 的问题。如果你已经在用 conda那就继续用 conda创建一个独立环境conda create -n ai-agent python3.10 conda activate ai-agent如果你没用过 conda直接用 Python 自带的 venv 也完全够用python -m venv ai-agent-env # Windows ai-agent-env\Scripts\activate # Mac/Linux source ai-agent-env/bin/activate注意不管你用哪种方式一定要创建独立环境。不要图省事直接装在系统 Python 里后面依赖冲突的时候你会想重装系统。2.2 核心依赖安装与版本锁定这是最容易出问题的地方。LangChain 的生态更新非常快不同版本之间的 API 差异很大。你照着半年前的教程敲代码很可能跑不起来因为 API 已经变了。我的建议是先装核心包然后立刻把版本号固定下来。pip install langchain langchain-core langchain-community pip install langchain-openai # 如果用 OpenAI 兼容接口 pip install chromadb # 向量数据库 pip install streamlit # 快速做界面装完之后导出当前版本pip freeze requirements.txt这样下次换机器或者重装环境直接pip install -r requirements.txt就能复现。我踩过的一个坑langchain和langchain-core的版本必须匹配。如果你单独升级了其中一个另一个没升就会出现ImportError。所以要么一起升要么都别动。2.3 API Key 管理与安全实践不管你用哪家的 LLM都需要 API Key。绝对不要把 Key 硬编码在代码里。我见过有人把带 Key 的代码传到公开仓库结果被人刷了几百块的账单。正确的做法是用.env文件# .env OPENAI_API_KEYsk-xxxxxxxx OPENAI_BASE_URLhttps://api.xxx.com/v1然后在代码里用python-dotenv加载from dotenv import load_dotenv import os load_dotenv() api_key os.getenv(OPENAI_API_KEY)同时把.env加到.gitignore里确保不会被提交。提示如果你用的是国内模型的 API大部分都兼容 OpenAI 的接口格式只需要改base_url和model名字就行。这样你的代码可以在不同模型之间快速切换。2.4 验证环境是否可用装完依赖后跑一个最小验证脚本from langchain_openai import ChatOpenAI from dotenv import load_dotenv load_dotenv() llm ChatOpenAI(modelgpt-4o-mini, temperature0) response llm.invoke(用一句话解释什么是AI Agent) print(response.content)如果这段能跑通说明环境没问题。如果报错大概率是三个原因API Key 没配好、base_url 写错了、或者模型名字不对。逐个排查就行。3. RAG 实战让 Agent 拥有私有知识RAG 是 Retrieval-Augmented Generation 的缩写翻译过来叫“检索增强生成”。名字听着唬人其实逻辑特别简单用户问问题 → 先去知识库里搜相关内容 → 把搜到的内容和问题一起交给 LLM → LLM 基于这些内容生成回答。为什么要这么做因为 LLM 的知识是训练时固定的它不知道你公司的内部文档、不知道你个人的笔记、不知道最新的产品手册。RAG 就是给 LLM 外挂一个可以随时更新的知识库。3.1 RAG 的核心流程拆解一个完整的 RAG 系统包含两个阶段离线阶段数据准备加载文档PDF、Word、Markdown、网页等把文档切分成小块chunk把每个小块转成向量embedding存入向量数据库在线阶段问答用户输入问题把问题也转成向量在向量数据库里找最相似的几个块把问题和这些块一起发给 LLMLLM 生成回答这里面每一步都有讲究我逐个说。3.2 文档切分chunk size 到底怎么定切分是 RAG 里最容易被忽视但影响最大的环节。切得太大检索出来的内容包含太多无关信息LLM 容易被干扰切得太小上下文不完整LLM 理解不了。我的经验值是中文文档 chunk size 设在 500-800 字英文设在 1000-1500 字符overlap 设在 chunk size 的 10%-20%。from langchain.text_splitter import RecursiveCharacterTextSplitter splitter RecursiveCharacterTextSplitter( chunk_size600, chunk_overlap100, separators[\n\n, \n, 。, , , , , , ] )注意separators这个参数。默认的分隔符是英文的对中文文档效果不好。加上中文标点后切分出来的块会更符合语义边界。实操心得如果你的文档有明确的章节结构比如 Markdown 的标题可以用MarkdownHeaderTextSplitter先按标题切再按长度切。这样每个块都带有章节信息检索准确率会明显提升。3.3 向量化与向量数据库选型向量化就是把文本转成一串数字向量语义相近的文本向量距离也近。常用的 embedding 模型有 OpenAI 的text-embedding-3-small、智谱的embedding-3、以及开源的bge-large-zh。向量数据库的选择就多了数据库特点适用场景Chroma轻量、本地、零配置个人项目、快速原型FAISSFacebook 出品、性能好数据量大、需要高性能检索Milvus分布式、企业级生产环境、大规模数据Qdrant支持过滤、API 友好需要复杂过滤条件零基础建议从 Chroma 开始因为它真的零配置from langchain_chroma import Chroma from langchain_openai import OpenAIEmbeddings embeddings OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory./chroma_db )3.4 检索策略相似度搜索不够用怎么办基础的相似度搜索有个问题它只看语义相似度不看信息量。有时候搜出来的块虽然和问题很像但并没有包含答案。解决办法是MMR最大边际相关性检索。它的逻辑是既要和问题相关又要和已选的块不重复。这样能保证检索结果的多样性。retriever vectorstore.as_retriever( search_typemmr, search_kwargs{k: 5, fetch_k: 20, lambda_mult: 0.7} )fetch_k20表示先取 20 个候选然后从中选出 5 个最符合 MMR 标准的。lambda_mult0.7表示 70% 权重给相关性30% 给多样性。还有一个进阶玩法叫Agentic RAG让 Agent 自己决定要不要检索、检索什么、检索几次。这个后面讲 LangGraph 的时候会展开。3.5 RAG 效果不好的排查思路RAG 系统最常见的抱怨是“答非所问”。排查顺序应该是先看检索结果把检索出来的块打印出来看看是不是真的包含了答案。如果不包含问题出在检索环节。再看 LLM 回答如果检索结果没问题但回答不对问题出在 Prompt 上。最后看文档切分如果检索结果总是差一点可能是 chunk 切得不好。我遇到过一个典型案例用户问“公司的报销流程是什么”检索出来的全是“报销标准”“报销范围”就是没有“流程”。后来发现是因为文档里“流程”那一段被切成了两个块关键步骤分散了。把 chunk size 调大之后问题就解决了。4. LangChain 与 LangGraphAgent 的骨架与神经LangChain 和 LangGraph 是现在做 Agent 开发最主流的两个框架。很多人搞不清楚它俩的区别我用一句话概括LangChain 是工具箱LangGraph 是流程图。LangChain 提供了各种组件LLM 封装、Prompt 模板、工具定义、记忆管理、检索器。你用这些组件可以快速拼出一个 Agent。LangGraph 则是在 LangChain 的基础上用图的方式定义 Agent 的执行流程。每个节点是一个操作每条边是节点之间的跳转条件。这样你可以精确控制 Agent 先做什么、后做什么、什么情况下走哪条分支。4.1 LangChain 的核心抽象LangChain 里有几个核心概念必须理解Runnable这是 LangChain 里最基本的执行单元。LLM、Prompt、Retriever、Parser 都是 Runnable。Runnable 之间可以用|连接形成一条链from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser prompt ChatPromptTemplate.from_template(用一句话解释{concept}) chain prompt | llm | StrOutputParser() result chain.invoke({concept: RAG})这个|符号就是 LangChain Expression LanguageLCEL它让链式调用变得非常直观。Tool工具是 Agent 能调用的外部函数。定义一个工具很简单from langchain_core.tools import tool tool def get_weather(city: str) - str: 查询指定城市的天气 # 实际调用天气API return f{city}今天晴25度注意 docstring 很重要Agent 就是靠这个描述来决定什么时候调用这个工具的。Memory记忆让 Agent 能记住之前的对话。LangChain 提供了多种记忆类型最常用的是ConversationBufferMemory和ConversationSummaryMemory。4.2 从零搭一个 LangChain Agent下面是一个完整的 Agent 示例能查天气和做计算from langchain_openai import ChatOpenAI from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate from langchain_core.tools import tool tool def get_weather(city: str) - str: 查询指定城市的天气 return f{city}今天晴气温25度 tool def calculate(expression: str) - str: 计算数学表达式 return str(eval(expression)) llm ChatOpenAI(modelgpt-4o-mini, temperature0) tools [get_weather, calculate] 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: 北京今天天气怎么样顺便算一下25乘以4}) print(result[output])把verboseTrue打开你能看到 Agent 的完整思考过程它先决定调用get_weather拿到结果后再决定调用calculate最后综合两个结果给出回答。4.3 LangGraph 为什么会出现用 LangChain 的 AgentExecutor 做简单任务没问题但一旦流程复杂起来就会遇到瓶颈想让 Agent 先检索再回答如果检索结果不好就重新检索AgentExecutor 做不到。想让多个 Agent 协作一个负责检索、一个负责写作、一个负责审核AgentExecutor 很别扭。想在某个步骤加人工审核AgentExecutor 没有这个机制。LangGraph 就是来解决这些问题的。它把 Agent 的执行过程建模成一个状态图State一个共享的数据结构所有节点都能读写Node一个函数接收 State返回 State 的更新Edge定义节点之间的跳转关系可以是固定的也可以是条件判断4.4 LangGraph 实战带自我纠错的 RAG下面这个例子展示 LangGraph 的核心价值检索结果不好的时候自动重新检索。from langgraph.graph import StateGraph, END from typing import TypedDict, List class RAGState(TypedDict): question: str documents: List[str] answer: str retry_count: int def retrieve(state: RAGState): docs retriever.invoke(state[question]) return {documents: [d.page_content for d in docs]} def grade_documents(state: RAGState): # 判断检索结果是否相关 if len(state[documents]) 0: return rewrite return generate def rewrite_query(state: RAGState): # 重写问题换个角度检索 new_question llm.invoke(f请换个方式表达这个问题{state[question]}) return {question: new_question.content, retry_count: state[retry_count] 1} def generate(state: RAGState): context \n.join(state[documents]) answer llm.invoke(f基于以下内容回答问题\n{context}\n\n问题{state[question]}) return {answer: answer.content} workflow StateGraph(RAGState) workflow.add_node(retrieve, retrieve) workflow.add_node(rewrite, rewrite_query) workflow.add_node(generate, generate) workflow.set_entry_point(retrieve) workflow.add_conditional_edges(retrieve, grade_documents, { rewrite: rewrite, generate: generate }) workflow.add_edge(rewrite, retrieve) workflow.add_edge(generate, END) app workflow.compile()这个图的意思是先检索然后判断结果好不好。不好就重写问题再检索最多重试几次。好了就直接生成回答。这种“自我纠错”的能力是 LangGraph 相比 LangChain 最大的优势。4.5 LangChain 和 LangGraph 怎么选我的建议是简单任务用 LangChain单轮问答、固定流程的工具调用LangChain 足够。复杂流程用 LangGraph多步骤推理、条件分支、循环重试、多 Agent 协作必须用 LangGraph。两者可以混用LangGraph 的节点内部可以用 LangChain 的组件不冲突。实操心得不要一上来就用 LangGraph。先把 LangChain 的 Agent 跑通理解工具调用和 Prompt 的机制再过渡到 LangGraph。否则你会被状态管理和条件边搞晕。5. MCP 协议Agent 工具调用的统一标准MCP 是 Model Context Protocol 的缩写翻译过来叫“模型上下文协议”。它要解决的问题是让不同的 AI 应用能用同一套标准去调用外部工具和数据源。在没有 MCP 之前每个 AI 应用要接一个工具都得自己写一套适配代码。你想让 Agent 操作 Figma得写 Figma 的适配想让它操作 Blender得写 Blender 的适配想让它查数据库得写数据库的适配。每个都是重复劳动。MCP 的思路是定义一套标准协议工具提供方按照这个协议实现一个 MCP ServerAI 应用按照这个协议实现一个 MCP Client。这样任何 Client 都能调用任何 Server不用再一对一适配。5.1 MCP 的架构与核心概念MCP 采用 Client-Server 架构MCP Host运行 AI 应用的环境比如 Claude Desktop、Trae、CursorMCP ClientHost 内部负责和 Server 通信的组件MCP Server提供工具、资源、Prompt 的服务端MCP Server 可以暴露三种能力能力说明例子Tools可调用的函数查数据库、发请求、执行代码Resources可读取的数据文件内容、数据库记录Prompts预定义的提示模板代码审查模板、文档总结模板通信方式支持两种stdio标准输入输出和 SSE服务器发送事件。本地工具一般用 stdio远程服务用 SSE。5.2 常见的 MCP Server 与使用场景现在社区里已经有大量现成的 MCP Server我列几个实用的Playwright MCP让 Agent 能操作浏览器做网页自动化、爬虫、测试Figma MCP读取 Figma 设计稿自动生成代码Blender MCP通过自然语言控制 Blender 做 3D 建模数据库 MCP连接 MySQL、PostgreSQL让 Agent 直接查数据文件系统 MCP读写本地文件以 Playwright MCP 为例配置好之后你可以直接对 Agent 说“帮我打开某某网站把首页的标题截图保存下来”Agent 就会通过 Playwright MCP 去执行。5.3 自己写一个 MCP Server用 Python 写一个最简单的 MCP Serverfrom mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent app Server(my-server) app.list_tools() async def list_tools(): return [ Tool( nameget_time, description获取当前时间, inputSchema{type: object, properties: {}} ) ] app.call_tool() async def call_tool(name: str, arguments: dict): if name get_time: from datetime import datetime return [TextContent(typetext, textdatetime.now().isoformat())] async def main(): async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options()) if __name__ __main__: import asyncio asyncio.run(main())这个 Server 暴露了一个get_time工具。任何支持 MCP 的 Host 都能调用它。5.4 MCP 和 RAG 的区别这是热词里问得最多的一个问题。简单说RAG 解决的是“知识从哪来”它让 LLM 能访问外部知识库本质是检索 生成。MCP 解决的是“能力从哪来”它让 LLM 能调用外部工具本质是标准化的函数调用协议。两者不冲突可以配合使用。比如一个 Agent 可以通过 MCP 调用一个“知识库查询工具”而这个工具内部实现用的是 RAG。注意MCP 目前还在快速演进中不同 Host 对 MCP 的支持程度不一样。配置之前先确认你用的 Host 支持哪个版本的 MCP 协议。6. 企业级项目实战从 Demo 到生产前面五章都是打基础这一章讲怎么把学到的东西组合起来做一个真正能用的企业级 Agent 系统。6.1 项目需求分析智能客服 Agent假设我们要做一个电商平台的智能客服 Agent需求是能回答商品相关问题基于商品知识库用 RAG能查询订单状态调用订单系统 API用 MCP能处理退换货申请多步骤流程用 LangGraph回答不了的问题转人工条件分支这个需求覆盖了 RAG、MCP、LangGraph 三个核心能力是一个很典型的综合项目。6.2 系统架构设计整个系统分成四层接入层Web 界面或 API 接口接收用户消息。Agent 编排层用 LangGraph 定义整个对话流程。入口节点先做意图识别然后根据意图路由到不同的处理节点。能力层RAG 检索器、MCP 工具集、业务 API 封装。数据层向量数据库商品知识、业务数据库订单信息、日志存储。意图识别的节点大概长这样def classify_intent(state): prompt f判断用户问题的意图只返回以下之一 - product_query商品咨询 - order_query订单查询 - refund退换货 - other其他 用户问题{state[question]} intent llm.invoke(prompt).content.strip() return {intent: intent}然后根据intent路由到不同节点workflow.add_conditional_edges(classify, lambda s: s[intent], { product_query: rag_node, order_query: order_node, refund: refund_node, other: human_handoff })6.3 关键实现细节与踩坑记录坑一意图识别不稳定。一开始我用的是让 LLM 直接输出意图标签但发现它有时候会输出多余的解释。解决办法是在 Prompt 里加 few-shot 示例并且用temperature0。坑二RAG 检索和订单查询冲突。用户问“我买的那个手机什么时候到”既涉及商品又涉及订单。后来在意图识别里加了一个“复合意图”类别走一个并行节点同时查两边。坑三退换货流程的状态管理。退换货是多轮对话需要记住用户已经提供了哪些信息。这里用 LangGraph 的 State 来存每个节点更新 State 里的refund_info字段。坑四MCP Server 的超时处理。订单系统 API 偶尔会慢MCP 调用默认超时时间太短。需要在 MCP Client 配置里把超时调大并且加一个重试机制。6.4 效果评估与迭代方向上线之后怎么评估效果我建议关注这几个指标指标说明目标值意图识别准确率分类正确的比例 90%RAG 召回率检索结果包含答案的比例 85%端到端解决率无需转人工的比例 70%平均响应时间从用户发消息到收到回复 3秒迭代方向主要是两个一是补充 RAG 知识库把用户问得多但答不好的问题整理成 FAQ 加进去二是优化 Prompt把意图识别和回答生成的 Prompt 根据 bad case 不断调整。6.5 从个人项目到企业落地的经验最后分享几点从个人 Demo 到企业生产环境的经验第一日志一定要打全。每个节点的输入输出、每次 LLM 调用的 Prompt 和返回、每次工具调用的参数和结果都要记下来。出问题的时候没有日志就是盲人摸象。第二要有降级方案。LLM API 会挂向量数据库会挂MCP Server 会挂。每个环节都要有 fallback比如 LLM 调用失败就返回预设话术检索失败就只靠 LLM 自身知识回答。第三成本要控制。LLM 调用是按 token 收费的RAG 检索和工具调用也有成本。在生产环境里能用小模型的地方就用小模型能缓存的结果就缓存。第四人工兜底不能省。不管 Agent 做得多好总会有它处理不了的情况。转人工的入口必须畅通而且要把转人工之前的对话上下文一起带过去不然用户还得重新说一遍。这套东西我从零开始摸索了大半年踩了无数坑才跑通。你现在跟着这个路线走能省掉很多弯路。环境搭好之后先把 LangChain 的 Agent 跑起来再逐步加 RAG、加 LangGraph、加 MCP一步一步来别想着一步到位。每加一个能力都先把它的原理搞清楚再动手写代码。这样遇到问题的时候你才知道该从哪里排查。