如何使用LangGraph搭建一个智能体应用,需要mcp和工具调用

📅 2026/8/14 13:13:40
如何使用LangGraph搭建一个智能体应用,需要mcp和工具调用
下面是一份从零开始、基于LangGraph 框架开发智能问答系统的完整实战教程涵盖API 工具调用和MCP 服务调用两大核心能力。一、什么是 LangGraphLangGraph 是由 LangChain 团队开发的低级别编排框架专门用于构建、管理和部署长期运行、有状态的 AI 智能体工作流。核心设计理念传统 LangChain 的 Chain 是线性链式调用A→B→C而 LangGraph 采用有向图结构支持循环、条件分支、并行执行更贴合真实业务中反复推理-执行-判断的 Agent 行为。四大核心组件组件作用类比State状态贯穿整个工作流的共享数据结构全局变量Node节点工作流中的原子执行单元纯函数函数Edge边定义节点间的流转逻辑普通/条件/并行if-else / 路由Graph图将节点和边组装成可执行的工作流程序入口为什么用 LangGraph 而不是 LangChain Agent精细控制可以精确控制每一步的流转逻辑而非黑盒执行状态持久化内置 Checkpoint 机制支持断点续传和故障恢复人机协同支持在任意节点暂停等待人工审核多智能体协作支持子图嵌套实现复杂的多 Agent 编排二、整体架构设计用户提问 │ ▼ ┌──────────────────────────────────────────┐ │ LangGraph 智能体图工作流 │ │ │ │ ┌─────────┐ ┌──────────┐ │ │ │ LLM节点 │◄──►│ 工具节点 │ ← 循环调用 │ │ └─────────┘ └────┬─────┘ │ │ │ │ │ ┌────────────┼────────────┐ │ │ ▼ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ ┌────────┐ │ │ │自定义工具 │ │ RAG检索 │ │MCP工具 │ │ │ │(API调用) │ │(知识库) │ │(外部) │ │ │ └──────────┘ └──────────┘ └────────┘ │ └──────────────────────────────────────────┘ │ ▼ 输出回答三、环境搭建3.1 创建项目mkdirlanggraph-qa-systemcdlanggraph-qa-system python-mvenv venv# Windowsvenv\Scripts\activate# macOS/Linuxsourcevenv/bin/activate3.2 安装依赖# LangGraph 核心框架pipinstalllanggraph langchain-core langchain-openai# MCP 集成pipinstalllangchain-mcp-adapters mcp fastmcp# 向量数据库RAGpipinstallchromadb langchain-chroma# 文档加载pipinstallpypdf python-docx# HTTP 请求pipinstallhttpx# 环境变量pipinstallpython-dotenv3.3 配置环境变量创建.env文件OPENAI_API_KEYsk-xxx # 如使用通义千问等国内模型 # DASHSCOPE_API_KEYyour_key四、接入大语言模型importosfromdotenvimportload_dotenv load_dotenv()fromlangchain_openaiimportChatOpenAI# 方式一OpenAIllmChatOpenAI(modelgpt-4o,temperature0)# 方式二通义千问兼容 OpenAI 接口# llm ChatOpenAI(# modelqwen-plus,# api_keyos.getenv(DASHSCOPE_API_KEY),# base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1# )五、定义自定义工具API 调用工具是智能体的手脚让它能执行搜索、计算、调用外部 API 等操作。fromlangchain_core.toolsimporttoolfromdatetimeimportdatetimeimporthttpxtooldefget_current_time(city:str)-str:获取指定城市的当前时间。当用户询问时间、几点钟等问题时调用。nowdatetime.now().strftime(%Y-%m-%d %H:%M:%S)returnf{city}当前时间是{now}tooldefquery_weather_api(city:str)-str:通过 API 查询指定城市的天气信息。当用户询问天气时调用。geocode_urlhttps://geocoding-api.open-meteo.com/v1/searchweather_urlhttps://api.open-meteo.com/v1/forecastwithhttpx.Client(timeout10)asclient:rclient.get(geocode_url,params{name:city,count:1,language:zh})r.raise_for_status()datar.json()[results][0]lat,londata[latitude],data[longitude]rclient.get(weather_url,params{latitude:lat,longitude:lon,current_weather:true})r.raise_for_status()weatherr.json()[current_weather]returnf{city}当前温度{weather[temperature]}°C风速{weather[windspeed]}km/htooldefcalculate(expression:str)-str:计算数学表达式。当用户需要数学计算时调用。try:resulteval(expression,{__builtins__:{}},{})returnf{expression}{result}exceptExceptionase:returnf计算出错:{e}custom_tools[get_current_time,query_weather_api,calculate] 工具的docstring 非常关键大模型依赖它来判断何时调用哪个工具。六、构建 RAG 知识库fromlangchain_community.document_loadersimportPyPDFLoaderfromlangchain.text_splitterimportRecursiveCharacterTextSplitterfromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_chromaimportChroma# 加载文档loaderPyPDFLoader(your_document.pdf)documentsloader.load()# 切割文本text_splitterRecursiveCharacterTextSplitter(chunk_size500,chunk_overlap50)chunkstext_splitter.split_documents(documents)# 向量化存储embeddingsOpenAIEmbeddings()vectorstoreChroma.from_documents(documentschunks,embeddingembeddings,persist_directory./chroma_db)retrievervectorstore.as_retriever(search_kwargs{k:3})# 封装为工具tooldefsearch_knowledge_base(query:str)-str:从私有知识库中检索相关信息。当用户询问专业知识、文档内容时调用。docsretriever.invoke(query)ifnotdocs:return知识库中未找到相关信息。return\n\n.join([doc.page_contentfordocindocs])七、编写 MCP Server外部服务调用7.1 创建 MCP Server创建文件news_mcp_server.pyfrommcp.server.fastmcpimportFastMCP mcpFastMCP(NewsService)mcp.tool()defsearch_news(keyword:str)-str:根据关键词搜索最新新闻。当用户询问新闻资讯时调用。# 示例实际项目中替换为真实 API 调用mock_news[{title:f关于{keyword}的最新报道1,summary:这是第一条新闻摘要...},{title:f关于{keyword}的最新报道2,summary:这是第二条新闻摘要...},]return\n.join([f{n[title]}:{n[summary]}forninmock_news])mcp.tool()defget_stock_price(symbol:str)-str:查询股票实时价格。当用户询问股价、行情时调用。returnf{symbol}当前价格为 150.25 元涨幅 2.3%if__name____main__:# stdio 模式本地开发mcp.run(transportstdio)# 生产环境改用 HTTP 模式# mcp.run(transportstreamable-http, host0.0.0.0, port8005)八、用 LangGraph 构建智能体核心这是整个教程的核心部分。LangGraph 提供两种构建方式预构建快捷方式和手动图编排。方式一使用预构建的create_react_agent推荐入门importasynciofromlangchain_openaiimportChatOpenAIfromlangchain_mcp_adapters.clientimportMultiServerMCPClientfromlanggraph.prebuiltimportcreate_react_agentasyncdefmain():# 1. 加载 MCP 工具mcp_config{news-server:{transport:stdio,command:python,args:[/你的绝对路径/news_mcp_server.py]# 必须用绝对路径}}clientMultiServerMCPClient(mcp_config)mcp_toolsawaitclient.get_tools()# 2. 合并所有工具all_toolscustom_tools[search_knowledge_base]mcp_toolsprint(f共加载{len(all_tools)}个工具:{[t.namefortinall_tools]})# 3. 创建 ReAct 智能体LangGraph 预构建agentcreate_react_agent(modelllm,toolsall_tools,prompt你是一个智能问答助手能够查询天气、计算数学、搜索新闻和检索知识库。)# 4. 执行问答resultawaitagent.ainvoke({messages:[{role:user,content:北京现在天气怎么样}]})print(result[messages][-1].content)if__name____main__:asyncio.run(main())create_react_agent内部就是一个 LangGraph 图遵循 ReAct推理-行动-观察循环。方式二手动构建 StateGraph完全掌控流程这是 LangGraph 的精髓——你可以精确控制每一步的流转逻辑importasyncioimportjsonfromtypingimportAnnotatedfromtyping_extensionsimportTypedDictfromlangchain_openaiimportChatOpenAIfromlangchain_core.messagesimportToolMessagefromlanggraph.graphimportStateGraph,START,ENDfromlanggraph.graph.messageimportadd_messagesfromlanggraph.prebuiltimportToolNode,tools_conditionfromlangchain_mcp_adapters.clientimportMultiServerMCPClient# 1. 定义状态State classState(TypedDict):messages:Annotated[list,add_messages]# 消息列表自动追加# 2. 定义节点函数 defchatbot(state:State,llm_with_tools):LLM 节点接收消息决定是否调用工具responsellm_with_tools.invoke(state[messages])return{messages:[response]}# 3. 构建图 asyncdefbuild_graph():# 加载 MCP 工具mcp_config{news-server:{transport:stdio,command:python,args:[/你的绝对路径/news_mcp_server.py]}}clientMultiServerMCPClient(mcp_config)mcp_toolsawaitclient.get_tools()# 合并所有工具all_toolscustom_tools[search_knowledge_base]mcp_tools# 绑定工具到 LLMllm_with_toolsllm.bind_tools(all_tools)# 创建图graphStateGraph(State)# 添加节点# 节点1LLM 推理节点graph.add_node(chatbot,lambdastate:chatbot(state,llm_with_tools))# 节点2工具执行节点LangGraph 预构建tool_nodeToolNode(toolsall_tools)graph.add_node(tools,tool_node)# 添加边定义流转逻辑# 入口 → LLM 节点graph.add_edge(START,chatbot)# LLM 节点 → 条件判断# - 如果 LLM 决定调用工具 → 跳转到 tools 节点# - 如果 LLM 直接回答 → 跳转到 ENDgraph.add_conditional_edges(chatbot,tools_condition)# 工具执行完 → 回到 LLM 节点形成循环graph.add_edge(tools,chatbot)# 编译图appgraph.compile()returnapp# 4. 运行 asyncdefmain():appawaitbuild_graph()# 交互式对话messages[]whileTrue:user_inputinput(\n‍: )ifuser_input.lower()in[quit,exit,q]:breakmessages.append({role:user,content:user_input})resultawaitapp.ainvoke({messages:messages})messagesresult[messages]print(f:{messages[-1].content})if__name____main__:asyncio.run(main())图的执行流程解析START │ ▼ ┌─────────┐ │ chatbot │ ← LLM 推理决定是否调工具 └────┬────┘ │ ├── 需要调工具──► tools 节点执行工具──► 回到 chatbot循环 │ └── 不需要──► END输出最终回答这就是 LangGraph 的核心价值循环 条件分支让 Agent 能反复推理直到得出最终答案。九、添加多轮记忆状态持久化fromlanggraph.checkpoint.memoryimportMemorySaver# 创建记忆存储memoryMemorySaver()# 编译时注入 checkpointerappgraph.compile(checkpointermemory)# 通过 thread_id 区分不同会话config{configurable:{thread_id:user_001}}# 第一轮awaitapp.ainvoke({messages:[{role:user,content:我叫小明帮我查一下北京天气}]},configconfig)# 第二轮智能体会记住小明resultawaitapp.ainvoke({messages:[{role:user,content:我叫什么名字}]},configconfig)十、添加人机协同Human-in-the-Loop# 在工具执行前暂停等待人工确认appgraph.compile(checkpointermemory,interrupt_before[tools]# 在执行工具前中断)# 执行到工具节点前会暂停resultawaitapp.ainvoke({messages:[{role:user,content:帮我发邮件给老板}]},configconfig)# 人工审核后更新状态并继续awaitapp.aupdate_state(config,{messages:[ToolMessage(...)]})awaitapp.ainvoke(None,configconfig)# 继续执行十一、生产部署建议容器化使用langgraph build构建 Docker 镜像持久化存储生产环境用PostgresSaver替代MemorySaver监控追踪集成 LangSmith 可视化追踪每一步推理过程MCP Server 独立部署使用streamable-http传输模式独立部署为微服务异常处理设置max_iterations防止无限循环 常见踩坑点总结问题原因解决方案MCP Server 启动失败使用了相对路径args中必须写绝对路径工具列表为空忘记awaitget_tools()必须异步调用返回 coroutine 对象用了同步invoke改用ainvoke()工具不被调用docstring 描述不清写清楚工具用途和参数含义无限循环LLM 反复判断需要调工具设置max_iterations工具返回太长上下文被冲淡工具只返回摘要信息整体开发流程总结环境搭建 → 模型接入 → 自定义工具API调用→ RAG知识库构建 → MCP Server编写 → LangGraph图编排节点边状态 → 工具合并注入 → 记忆集成 → 人机协同 → 测试部署建议从create_react_agent预构建方式开始跑通流程理解原理后再切换到手动StateGraph编排逐步掌握 LangGraph 的图控制能力。