AI Agent 的资料现在很多,但多数要么只讲一个组件,要么直接从某个框架的 Hello World 开始。真正把 RAG、MCP、LangChain、LangGraph 串成一条完整技术链路,再落回企业级项目场景的内容,反而很少见。这次我们要梳理的这套方法,核心价值就是解决这个问题:它不以单个 API 演示为目标,而是按“知识库检索 -> 工具接入 -> 应用组装 -> 智能体编排 -> 项目落地”的完整路径来组织。
如果你正在学 AI Agent,或者准备在公司里做一个真正能用的智能体项目,建议先把这条技术栈的边界和顺序搞清楚。RAG 负责让模型“知道该查什么”,MCP 负责让 Agent“能操作什么”,LangChain 负责把组件拼起来,LangGraph 负责把流程控住。它们不是互相替代的关系,而是同一套系统里的不同层次。这篇文章会把这四个模块分别讲清楚,再用一个企业级项目案例说明如何整合,最后给出环境准备、最小验证、常见问题和工程化建议。
本文适合三类读者:第一类是已经会调用大模型 API,但不知道如何组织复杂业务逻辑的开发者;第二类是做过简单 RAG 问答,想从 Demo 走向生产环境的工程师;第三类是准备面试或者写技术方案,需要系统性理解 Agent 技术栈的人。
1. 全套知识地图:RAG、MCP、LangChain、LangGraph 到底在解决什么问题
很多人学 AI Agent 学不下去,不是因为模型多难,而是因为组件之间的关系没有建立起来。每个框架都在快速迭代,今天学的 API 明天可能就变了。但只要你能分清每个模块在整个系统中的位置,就不会被版本带着跑。
先给一张总览表:
| 技术栈 | 主要作用 | 典型问题 | 关键概念 |
|---|---|---|---|
| RAG | 检索增强生成,给模型补充外部知识 | 模型不知道私有知识、回答容易幻觉 | 文档切分、向量化、召回、重排、指标评估 |
| MCP | 模型上下文协议,规范 Agent 与外部工具/数据源的连接 | 每个工具一套接入方式,难以复用 | MCP Server、MCP Client、Tool 定义、资源权限 |
| LangChain | LLM 应用开发框架,提供基础组件和编排能力 | 手动拼接 Prompt、调用、解析太繁琐 | Prompt、Model、OutputParser、Retriever、Tool、Chain |
| LangGraph | 有状态的 Agent 编排引擎,控制智能体执行流程 | Agent 流程不可控、循环容易卡死、状态难管理 | StateGraph、Node、Edge、Conditional Edge、子图、持久化 |
| Agent | 智能体本体,负责理解目标、规划步骤、调用工具、评估结果 | 动态任务无法用固定流程写死 | 规划、工具调用、记忆、反思、终止条件 |
理解这张表的正确方式,不是问“RAG 好还是 Agent 好”,也不是“LangChain 是不是要被 LangGraph 替代”。更准确的关系是:RAG 是知识供给链路,MCP 是工具连接标准,LangChain 是组件抽象层,LangGraph 是流程执行层。Agent 是最终形态,它需要前面所有模块配合。
LangChain 和 LangGraph 的区别常常让人困惑。从设计定位看,LangChain 聚焦“将模型调用封装成链式组件”,适合线性、确定的流程;LangGraph 聚焦“图状态机编排”,适合带分支、循环、回退的复杂流程。实际项目中完全可以在 LangGraph 的节点内部使用 LangChain 的 Retriever、Prompt 和 Model 组件,两者不是竞争关系。
另一个需要区分的概念是 RAG 和 Agentic RAG。传统 RAG 是固定的“检索一次、生成一次”,Agentic RAG 则让 Agent 自主决定是否需要检索、分几步检索、如何根据检索结果调整下一步。从知识库问答到企业级 Agent,最常见的技术升级路径就是:先做标准 RAG,再把检索节点嵌入 LangGraph,让流程变得更智能。
2. RAG 模块:知识库问答的核心链路
RAG(Retrieval-Augmented Generation)是整套体系里最独立也最容易验证的模块。它解决的核心问题是:模型没有训练过的私有知识,如何通过检索补充进去。
2.1 RAG 的标准流程
一个可落地的 RAG 链路通常包含以下环节:
- 文档加载:从 PDF、Word、Markdown、HTML、数据库等来源读取内容。
- 文档切分:把长文本切成适合检索的 Chunk,切分策略直接影响召回效果。
- 向量化:用 Embedding 模型把每个 Chunk 转成向量。
- 存储:把向量写入向量数据库,同时保存原文和元数据。
- 检索:根据用户问题生成查询向量,做相似度检索。
- 重排(可选):对召回结果做二次排序,把最相关内容排到前面。
- 生成:把检索到的上下文和用户问题一起交给大模型,要求它基于上下文回答。
很多人做 RAG 效果不好,问题不一定出在模型,而更多是切分策略和检索质量的问题。比如一段产品文档被硬切成 512 字符的小块,完整的产品参数被拆到两个 Chunk,回答自然残缺。更合理的做法是优先按标题层级切分,再结合段落语义做二次合并。
2.2 RAG 知识库指标怎么看
热搜里提到“RAG 知识库指标有哪些、如何理解”,这块在项目验收时很关键。常见的评估维度包括:
| 指标类别 | 代表指标 | 说明 |
|---|---|---|
| 检索效果 | 召回率、命中率、MRR、NDCG | 判断正确答案是否在召回结果中,以及排序是否靠前 |
| 生成效果 | 忠实度、相关性、完整性 | 判断回答是否忠于检索内容,是否答非所问 |
| 系统效果 | 响应延迟、首 Token 时间、端到端成功率 | 判断线上是否可用 |
| 成本 | Token 消耗、向量库存储量 | 判断长期运行成本 |
判断 RAG 系统是否可用,不要只看“回答得像不像”,要拆开看:检索环节能召回正确答案吗?生成环节有没有忠实使用召回内容?如果检索没召回,生成模型再强也答不出来;如果召回了但生成时没用,那就是 Prompt 或上下文组织的问题。
2.3 RAG 最小实现示例
下面给一个常见实现结构,基于 LangChain 系列组件,核心目的是把流程跑通。不同版本组件路径可能有差异,实际运行时以你安装的版本为准。
# 示例:基于 LangChain 的 RAG 最小链路 from langchain_text_splitters import RecursiveCharacterTextSplitter # 1. 加载文本 with open("knowledge.txt", "r", encoding="utf-8") as f: text = f.read() # 2. 切分 splitter = RecursiveCharacterTextSplitter( chunk_size=500, chunk_overlap=50, separators=["\n\n", "\n", "。", "!", "?", " "], ) chunks = splitter.split_text(text) # 3. 向量化并存储 # 这里使用向量数据库客户端,具体 API 以实际库为准 # vectorstore.add_documents(documents) # 4. 检索 # docs = vectorstore.as_retriever().invoke("产品支持哪些协议?") # 5. 构造 Prompt 并调用模型 # prompt = ChatPromptTemplate.from_template("基于以下资料回答问题:\n{context}\n问题:{question}")上面代码省略了向量库和模型调用细节,目的是先建立流程感。实际落地时,需要根据选用的向量数据库、Embedding 模型和大模型 API 替换对应部分。
RAG 项目里最容易出问题的是 Embedding 模型。中文场景下,Embedding 模型的选择会直接影响相似度检索效果。建议在生产环境里准备一组真实问答对,分别用不同 Embedding 模型跑一遍召回率,用数据而不是感觉来做选择。
3. MCP 模块:让 Agent 安全地操作外部工具
MCP(Model Context Protocol)是当前 AI Agent 生态里非常重要的协议层。它解决的问题非常实际:Agent 需要调用数据库、日志系统、浏览器、设计稿、代码仓库等外部工具,如果每个工具都单独实现一套调用协议,Agent 的接入成本就会失控。
3.1 MCP 的角色
MCP 采用 Client-Server 结构:
- MCP Client:运行在 Agent 侧,负责发现可用的 MCP Server、调用工具、接收结果。
- MCP Server:封装具体能力,比如文件系统、Elasticsearch、Playwright 浏览器控制、蓝湖设计稿查询、Figma、IDA Pro 等。
- Tool:MCP Server 对外暴露的原子能力,有名称、描述、输入参数和返回结果。
对 Agent 来说,MCP 的价值在于标准化。Agent 不需要关心某个工具是 Java 写的还是 Python 写的,也不需要关心它的鉴权方式。只要目标是“帮我查一下 ES 里最近一小时的错误日志分布”,Agent 就能根据 MCP Server 暴露的 Tool 描述,自动生成参数并调用。
常见可接入的 MCP Server 包括:
| MCP Server | 能力场景 |
|---|---|
| 文件系统 | 读取、写入、搜索本地文件 |
| Elasticsearch | 查询日志、聚合分析、获取索引信息 |
| Playwright | 控制浏览器执行页面操作 |
| 蓝湖 / Figma | 读取设计稿、标注信息、切图资源 |
| 数据库 | 执行受控的只读 SQL 查询 |
| IDA Pro | 逆向分析场景的脚本化操作 |
3.2 MCP 工具定义与接入
下面的示例展示如何在一个 MCP Server 里声明一个日志查询工具。不同 MCP SDK 写法会有差异,这里只表达结构。
# 示例:MCP Server 中声明一个 Tool 的常见结构 # 具体导入路径和装饰器写法以你使用的 MCP SDK 为准 from mcp.server.fastmcp import FastMCP mcp = FastMCP("log-analysis") @mcp.tool() def query_es_logs(index: str, query: dict, time_range: str) -> str: """查询 Elasticsearch 日志索引。 Args: index: 日志索引名称。 query: 查询条件。 time_range: 时间范围,例如 1h。 """ # 实际实现替换为你的 ES 客户端调用 return "查询结果" if __name__ == "__main__": mcp.run()企业里接入 MCP 时,建议先把 MCP Server 封装在独立服务内,只暴露受控能力。不要把数据库的完整写权限直接暴露给 Agent,更不要让 Agent 直接操作生产环境。MCP 解决的是“能不能调用”的问题,但“该不该调用”需要 Agent 应用层做权限校验。
4. LangChain 模块:LLM 应用的组件化组装
LangChain 在整套体系里的角色,是提供一套通用的 LLM 应用组装抽象。它把 Prompt 管理、模型调用、输出解析、记忆、检索器、工具调用等操作封装成可组合的组件。即使你最终用 LangGraph 做流程编排,也依然可以在节点内部使用 LangChain 的组件。
4.1 核心组件
LangChain 的核心概念包括:
- ChatPromptTemplate:结构化 Prompt 模板,支持系统消息、用户消息、上下文变量注入。
- ChatModel / LLM:统一封装不同厂商的模型调用,比如 OpenAI、Anthropic、本地模型。
- OutputParser:把模型输出解析成结构化内容,比如 JSON、列表。
- Retriever:封装向量检索,给 RAG 提供统一接口。
- Tool:封装外部函数,供 Agent 调用。
- Memory:管理多轮对话的历史记录。
- Chain / Runnable:把多个组件串成执行链。
4.2 LangChain 适合做什么
LangChain 适合确定性强的链路。比如“问题 -> 检索 -> 组装 Prompt -> 调用模型 -> 输出解析”,这种流程用 LangChain 很顺手。它的组件抽象可以让你在不同模型、不同向量库之间切换,减少业务代码改动。
但 LangChain 不适合需要复杂分支、循环和状态管理的流程。比如一个 Agent 需要先判断问题是否需要检索,再决定调用哪个工具,工具结果异常时还要重试或换方案,这种流程如果硬用 Chain 拼,代码会非常难维护。
这也正是 LangGraph 存在的理由。LangGraph 把流程从“链”升级为“图”,每个节点是一个执行单元,节点之间有明确的流转关系,可以支持条件路由、循环、并分支和子图。
5. LangGraph 模块:有状态 Agent 编排的核心
LangGraph 是当前做企业级 Agent 编排时非常值得投入的技术方向。它和 LangChain 的区别可以概括为:LangChain 强调“组件怎么组织”,LangGraph 强调“流程怎么控制”。
5.1 LangGraph 的核心概念
用 LangGraph 构建一个 Agent,通常要理解以下概念:
| 概念 | 作用 |
|---|---|
| StateGraph | 对 Agent 执行流程建模,核心是维护一个全局 State |
| State | 跨节点传递的数据结构,比如问题、检索结果、中间判断、最终回答 |
| Node | 执行单元,每个 Node 接收 State 并返回 State 的增量 |
| Edge | 节点之间的连接,表示正常流转 |
| Conditional Edge | 条件分支,根据 State 数据决定下一步走向哪个节点 |
| 子图 | 把一个复杂流程封装成独立图,主图可以调用它 |
| 持久化 | 保存 Agent 执行状态,支持断点续跑、人工审核、恢复执行 |
| 并行分支 | 多个节点同时执行,适合多个独立工具调用 |
5.2 LangGraph 条件路由示例
下面是一个简化示例,体现“先判断是否走 RAG,再生成回答”的流程。不同版本 API 可能有变动,请以官方文档为准。
from typing import TypedDict, Literal from langgraph.graph import StateGraph, START, END class AgentState(TypedDict): question: str need_rag: bool context: str answer: str def plan_node(state: AgentState) -> AgentState: # 实际项目中这里可以调用意图识别模型或规则判断 need_rag = "内部知识" in state["question"] or "文档" in state["question"] return {"need_rag": need_rag} def rag_node(state: AgentState) -> AgentState: # 调用向量检索,产出上下文 context = "这里是检索到的资料摘要" return {"context": context} def direct_node(state: AgentState) -> AgentState: # 不检索,直接回答 return {"context": ""} def answer_node(state: AgentState) -> AgentState: # 把问题和上下文一起交给大模型生成回答 answer = f"生成结果,上下文长度为 {len(state['context'])}" return {"answer": answer} def route(state: AgentState) -> Literal["rag_node", "direct_node"]: return "rag_node" if state["need_rag"] else "direct_node" graph = StateGraph(AgentState) graph.add_node("plan_node", plan_node) graph.add_node("rag_node", rag_node) graph.add_node("direct_node", direct_node) graph.add_node("answer_node", answer_node) graph.add_edge(START, "plan_node") graph.add_conditional_edges("plan_node", route) graph.add_edge("rag_node", "answer_node") graph.add_edge("direct_node", "answer_node") graph.add_edge("answer_node", END) app = graph.compile() # 实际运行 result = app.invoke({"question": "帮我查一下内部文档中的权限说明"}) print(result["answer"])这段代码体现的就是条件路由:根据need_rag的布尔值,把流程导向不同分支。企业级 Agent 里,route函数通常不是一个简单的关键词判断,而是由模型决策或者规则引擎触发的。
5.3 LangGraph 为什么适合企业级
企业级 Agent 和 Demo 最大的区别在于可控性和可恢复性。Demo 只需要跑通一次成功路径,企业级必须考虑失败情况。
LangGraph 提供的有状态执行模型,让每一步都有明确的输入输出和状态记录。Agent 执行到一半失败时,可以基于持久化状态恢复,而不是从头再来。对于需要人工审核的流程,比如财务报销、内容审批,可以在 Agent 执行到某个节点后暂停,等待人工确认再继续。
另外,LangGraph 的并行分支能力很适合多工具并行场景。例如在一个“客户服务 Agent”里,需要同时查订单状态、查物流信息、查售后政策,这三个检索相互独立,可以并行执行再汇总,显著降低整体延迟。
6. 企业级实战设计:用一个智能日志分析 Agent 打通全链路
前面几个模块单独都容易理解,但真正有价值的是把它们组合起来。这里设计一个案例:企业智能日志分析 Agent,用来演示 RAG、MCP、LangChain、LangGraph 如何在同一个项目里协同。
6.1 场景与目标
运维团队每天需要从 Elasticsearch 中查询大量应用日志,定位报错、分析趋势、排查根因。传统做法是人工写 DSL 查询,门槛高、效率低。我们希望做一个 Agent,让用户直接用自然语言提问,Agent 自动完成:
- 理解用户意图,判断是否需要查询 ES。
- 通过 MCP Server 调用 ES API,执行日志检索。
- 对检索结果做聚合分析。
- 结合团队内部的排障文档(RAG 知识库)给出结论与建议。
- 如果原始日志不足以判断,Agent 可以继续追问条件或扩大时间范围。
6.2 流程设计
用 LangGraph 来编排,这个 Agent 的流程可以设计为:
| 节点 | 输入 | 输出 | 说明 |
|---|---|---|---|
| 意图识别 | 用户问题、历史状态 | 是否查日志、目标索引、时间范围 | 用大模型或规则解析 |
| RAG 知识检索 | 用户问题 | 相关排障文档片段 | 查内部文档库 |
| MCP 日志查询 | 查询参数 | ES 返回的原始日志 | 走 MCP Server 调用 |
| 结果分析 | 原始日志、知识文档 | 根因建议、置信度 | 大模型综合判断 |
| 结果复核 | 分析结果 | 可执行答复 | 必要时进入人工审核节点 |
在这个流程里,RAG 负责提供“团队内部的排障经验和已知问题库”,MCP 负责把“ES 查询能力”安全地开放给 Agent,LangChain 负责组装 Prompt 和解析模型输出,LangGraph 负责把整个流程串成有状态、可恢复、可审核的图。
6.3 工程化要点
从 Demo 到这个项目,至少要多考虑下面几点:
- 权限控制:不是所有用户都能查询所有索引。MCP Server 层要按用户角色校验索引范围。
- 数据脱敏:日志中可能包含手机号、身份证、Token 等敏感信息,查询结果返回给模型前要脱敏。
- 查询审计:记录每一次 Agent 触发的 ES 查询,方便事后追溯。
- 失败重试:ES 超时、索引不存在、查询语法错误,都需要明确的重试和降级策略。
- 人工介入:对于“根因分析”这种高风险结论,默认走人工审核节点。
这样的设计也体现了 MCP 和 Agent Skill 的区别。MCP 更多是工具连接协议,解决“怎么连”;Agent Skill 更偏重封装“某个任务的完整做法”。实际项目里通常两者配合使用:MCP 提供原子能力,Skill 提供可复用的任务模板。
7. 环境准备与最小验证
学习这套技术栈,不建议一开始就上很重的生产架构。先用最小环境把链路跑通,再逐步加复杂度。
7.1 环境准备清单
建议按以下清单检查环境:
| 检查项 | 建议 |
|---|---|
| Python | 3.10 及以上,创建独立虚拟环境 |
| 大模型 API | 准备可用的 API Key,或本地部署推理服务 |
| Embedding 模型 | 准备中英文效果较好的模型,或调用远端 Embedding API |
| 向量数据库 | 可选,先跑通内存版或轻量级库,再上正式环境 |
| Node.js | 仅在使用部分 MCP 生态工具时需要 |
| Docker | 企业级部署建议准备,但不是本地学习必需 |
7.2 安装命令示例
下面是一个通用安装示例。LangChain、LangGraph 版本更新较快,建议先确定主版本,再按官方文档安装对应依赖。
python -m venv .venv source .venv/bin/activate # Windows 使用 .venv\Scripts\activate pip install langchain langchain-openai langchain-text-splitters pip install langgraph pip install mcp如果使用本地模型或者向量库,需要额外安装对应依赖,比如sentence-transformers、chromadb等。不要在全局环境里直接装,免得和其他项目冲突。
7.3 最小验证顺序
第一次跑通这套体系,建议按以下顺序验证:
- 验证 LangChain:用 Prompt 模板 + 大模型 API 跑通一个最简单的问答。
- 验证 RAG:准备一段文本,切分后手动检索,确认能召回正确内容。
- 验证 MCP:启动一个打印 Hello World 的 MCP Server,确认 Agent 能发现并调用它的 Tool。
- 验证 LangGraph:运行前面的条件路由示例,确认流程能按预期走到不同分支。
- 组合验证:把 RAG 检索节点和 MCP 工具节点放入同一个 LangGraph 图里,跑通端到端。
每步验证通过后再进入下一步,不要一次把所有组件全部接上。版本报错时,优先看官方文档的迁移说明,很多改动只是 API 路径变了,核心概念没变。
8. 常见问题与排查方法
学习这套技术栈时会遇到很多问题,下面整理高频问题:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 安装依赖失败 | Python 版本不兼容、依赖冲突 | 查看报错栈,确认 Python 版本 | 创建新虚拟环境,按官方文档指定版本安装 |
| 模型调用报 401/403 | API Key 无效或过期 | 检查环境变量和 Key 配置 | 重新配置 Key,确认网络可以访问模型服务 |
| RAG 检索效果差 | Chunk 切分不当、Embedding 模型不匹配 | 抽样检查召回结果 | 调整切分策略,替换 Embedding 模型,增加重排 |
| 向量库连接失败 | 服务没有启动、端口被占用 | 检查端口和日志 | 重启服务,更换端口 |
| LangGraph 报错 | 版本 API 变动、State 结构不匹配 | 查看官方文档迁移说明 | 按新版本 API 调整节点和边写法 |
| Agent 进入死循环 | 终止条件设计不当 | 查看状态流转日志 | 增加最大步数限制,设计明确的终止节点 |
| 工具调用参数错误 | 大模型生成的参数不符合 Tool Schema | 记录模型输出,检查 Tool 描述 | 优化 Tool 描述,增加参数校验 |
| 回答不忠实于知识库 | Prompt 没有约束模型只使用上下文 | 检查生成所用 Prompt | 强制要求“仅基于资料回答,资料不足请说明” |
| 上下文过长 | 检索结果太多或历史记录过长 | 统计 Token 消耗 | 限制召回数量,压缩历史记录 |
| 生产环境数据泄露风险 | 未做脱敏和权限控制 | 审计日志和接口权限 | 在 MCP 层做索引白名单,响应内容脱敏 |
排查问题的时候,先确认“当前是在验证哪个环节”,不要在一个混合链路里盲猜。建议每个节点都输出结构化日志,记录输入、输出、耗时和 Token 消耗。
9. 最佳实践与落地建议
把这套技术真正用到项目里,有几个工程习惯很关键。
9.1 先小参数验证,再放大规模
第一次跑 Agent 流程时,检索条数、模型温度、历史轮数都用保守参数。确认链路稳定后,再逐步放大。尤其是批量任务场景,先跑 3 到 5 条数据看结果,再决定是否全部放开。
9.2 用指标管理 RAG 和 Agent 效果
RAG 不要只靠“觉得回答不错”来验收。把真实问答对建成评测集,分别计算检索命中率和生成忠实度。Agent 也要记录“单次任务是否成功”“平均调用工具次数”“是否出现死循环”。有了这些数据,后续优化才有依据。
9.3 数据安全与合规优先
涉及企业日志、用户数据、知识库内容时,务必注意:
- 先在测试环境使用脱敏数据,确认流程无误再考虑真实数据。
- MCP Server 只暴露最小必要权限,不提供通用写接口。
- 外部工具调用要记录审计日志。
- 使用版权内容、内部文档、人脸和声音等素材前,确保有授权。
- 对外发布或商用前,对模型输出做人工复核。
9.4 保持可观测性
Agent 比普通接口更依赖可观测性。为每个节点记录状态变更、耗时和异常;条件路由的关键判断要输出原因;工具调用要记录请求参数和返回摘要。对于一个复杂的 LangGraph Agent,能回放执行轨迹比能“重新调用一次”重要得多。
9.5 不要把所有逻辑塞进 Prompt
Agent 能力强,但把业务规则全写在 Prompt 里会导致难以维护。稳定规则用代码实现,动态策略用 Prompt 控制,只有真正需要模型判断的内容才交给模型。这样既提高稳定性,也降低 Token 成本。
10. 总结与下一步
这套技术栈最值得投入的地方,不是某个 API 的写法,而是建立完整的工程视角。RAG 解决知识供给,MCP 解决工具接入,LangChain 解决组件组装,LangGraph 解决流程控制。把它们串起来,AI Agent 才能从“能聊天”走向“能干活”。
建议从三个动作开始:一是用 RAG 跑通一个私有知识库问答,二是用 MCP 接入一个真实工具,三是用 LangGraph 把这两个模块画进一张状态图。最容易踩的坑是版本兼容和边界混淆,碰到问题先定位技术栈层次,再查对应文档。
后续可以继续扩展的方向包括:多 Agent 协作与任务分配、Agent 执行结果自动评估、面向具体业务场景的 Agent Skill 封装、以及把 LangGraph 流程接入人工审核机制。建议把这些留到下一阶段逐步深入。