【langgraph 从入门到精通graphApi 篇】消息处理与工具集成
文章目录第 4 章消息处理与工具集成4.1 本章目标4.2 核心概念四种消息类型工具调用完整流程4.3 实战实战 1搜索工具 Agent实战 2手动构建工具调用循环深入理解底层4.4 API 速查4.5 错误与避坑指南坑 1ToolMessage 缺少 tool_call_id坑 2工具函数返回值类型不兼容坑 3忘记 bind_tools坑 4工具调用死循环4.6 最佳实践总结第 4 章消息处理与工具集成4.1 本章目标学完本章你将能够理解 LangChain 消息体系HumanMessage / AIMessage / ToolMessage / SystemMessage掌握tool装饰器定义工具函数学会 ToolNode 的集成方式和工作原理理解工具调用回环agent → tools → agent 循环4.2 核心概念四种消息类型消息类型角色使用场景示例HumanMessage用户用户输入HumanMessage(content今天天气怎么样)AIMessageAILLM 的回复AIMessage(content今天晴25°C)ToolMessage工具工具执行结果ToolMessage(content25°C, tool_call_id...)SystemMessage系统系统提示词/角色设定SystemMessage(content你是一个有用的助手)工具调用完整流程工具函数ToolNodetools_conditionAgent 节点 (LLM)用户工具函数ToolNodetools_conditionAgent 节点 (LLM)用户北京今天天气怎么样LLM 决策需要调用 get_weather 工具返回 AIMessage(含 tool_calls)检测到 tool_calls路由到 tools 节点调用 get_weather(北京)返回 25°C晴返回 ToolMessage(结果)LLM 基于工具结果生成最终回复北京今天天气晴温度 25°C4.3 实战实战 1搜索工具 AgentfromtypingimportTypedDict,Annotated,Literalfromlanggraph.graphimportStateGraph,START,END,add_messagesfromlanggraph.prebuiltimportToolNode,tools_conditionfromlangchain_core.messagesimportBaseMessage,HumanMessage,SystemMessagefromlangchain_core.toolsimporttoolfromlangchain_openaiimportChatOpenAI# # 定义工具使用 tool 装饰器# tooldefsearch_knowledge(query:str)-str: 在知识库中搜索信息。当用户询问事实性问题时使用此工具。 Args: query: 搜索关键词 # 模拟搜索实际项目中替换为数据库查询或搜索引擎 APIknowledge_base{天气:今天北京天气晴温度 25°C湿度 40%,Python:Python 是一种高级编程语言由 Guido van Rossum 于 1991 年创建,LangGraph:LangGraph 是 LangChain 团队开发的有状态多步骤 AI 应用编排框架,}forkey,valueinknowledge_base.items():ifkeyinquery:returnvaluereturnf未找到关于「{query}」的信息tooldefcalculate(expression:str)-str: 执行数学计算。当用户需要进行数学运算时使用此工具。 Args: expression: 数学表达式如 2 3 * 4 try:# 安全计算仅允许数字和基本运算符resulteval(expression,{__builtins__:{}},{})returnf计算结果:{expression}{result}exceptExceptionase:returnf计算错误:{str(e)}# # 定义 State# classState(TypedDict):messages:Annotated[list[BaseMessage],add_messages]# # 定义节点# # 初始化 LLM 并绑定工具llmChatOpenAI(modelgpt-4o,temperature0)tools[search_knowledge,calculate]# 注意llm.bind_tools() 让 LLM 知道有哪些工具可用llm_with_toolsllm.bind_tools(tools)defagent(state:State)-dict: Agent 节点调用 LLMLLM 决定是直接回复还是调用工具。 # 添加系统提示词messagesstate[messages]ifnotmessagesornotisinstance(messages[0],SystemMessage):messages[SystemMessage(content你是一个有用的助手可以使用工具来回答问题。)]list(messages)responsellm_with_tools.invoke(messages)return{messages:[response]}# # 构建图# builderStateGraph(State)# 注册节点builder.add_node(agent,agent)builder.add_node(tools,ToolNode(tools))# ToolNode 自动处理工具调用# 添加边builder.add_edge(START,agent)# 条件边如果 agent 返回了 tool_calls则路由到 tools 节点# 否则结束tools_condition 是内置路由函数builder.add_conditional_edges(agent,tools_condition,# 内置函数检查 AIMessage 是否有 tool_calls# tools_condition 返回值tools 或 __end__)# tools 执行完后回到 agent继续生成回复builder.add_edge(tools,agent)graphbuilder.compile()# # 测试# defask(question:str):辅助函数发送问题并打印结果print(f\n{*50})print(f用户:{question})resultgraph.invoke({messages:[HumanMessage(contentquestion)]})last_msgresult[messages][-1]print(fAI:{last_msg.content})# 测试需要工具的问题ask(今天天气怎么样)ask(Python 是什么)ask(计算 15 * 8 20)ask(你好今天心情好吗)# 不需要工具的问题实战 2手动构建工具调用循环深入理解底层fromtypingimportTypedDict,Annotated,Literalfromlanggraph.graphimportStateGraph,START,END,add_messagesfromlangchain_core.messagesimportBaseMessage,HumanMessage,AIMessage,ToolMessage,SystemMessagefromlangchain_core.toolsimporttoolfromlangchain_openaiimportChatOpenAI# # 定义工具# tooldefget_weather(city:str)-str:获取指定城市的天气returnf{city}今天天气晴25°Ctooldefget_time()-str:获取当前时间fromdatetimeimportdatetimereturndatetime.now().strftime(%Y-%m-%d %H:%M:%S)# # 准备工作# tools[get_weather,get_time]tools_by_name{t.name:tfortintools}# 工具名 → 工具对象llmChatOpenAI(modelgpt-4o,temperature0)llm_with_toolsllm.bind_tools(tools)# # 定义 State# classState(TypedDict):messages:Annotated[list[BaseMessage],add_messages]# # 定义节点# defagent(state:State)-dict:Agent 节点调用 LLMresponsellm_with_tools.invoke([SystemMessage(content你是一个有用的助手)]list(state[messages]))return{messages:[response]}deftool_executor(state:State)-dict: 手动执行工具调用不依赖 ToolNode。 这样你可以完全控制工具执行逻辑。 last_messagestate[messages][-1]# 获取最后一条 AIMessage 中的 tool_callstool_callslast_message.tool_calls tool_messages[]fortool_callintool_calls:tool_nametool_call[name]tool_argstool_call[args]tool_call_idtool_call[id]print(f 调用工具:{tool_name}({tool_args}))# 找到对应的工具并执行iftool_nameintools_by_name:tool_functools_by_name[tool_name]resulttool_func.invoke(tool_args)else:resultf未知工具:{tool_name}# 创建 ToolMessage必须包含 tool_call_idtool_messages.append(ToolMessage(contentstr(result),tool_call_idtool_call_id))print(f 结果:{result})return{messages:tool_messages}defshould_continue(state:State)-Literal[tools,END]:判断是否需要继续调用工具last_messagestate[messages][-1]ifhasattr(last_message,tool_calls)andlast_message.tool_calls:returntoolsreturnEND# # 构建图# builderStateGraph(State)builder.add_node(agent,agent)builder.add_node(tools,tool_executor)builder.add_edge(START,agent)builder.add_conditional_edges(agent,should_continue)builder.add_edge(tools,agent)graphbuilder.compile()# 测试resultgraph.invoke({messages:[HumanMessage(content北京天气怎么样现在几点了)]})print(f\n最终回复:{result[messages][-1].content})4.4 API 速查API完整签名入参说明返回值说明HumanMessage(content)HumanMessage(content: str)content: 文本内容HumanMessage用户消息AIMessage(content)AIMessage(content: str | None)content: 文本内容AIMessageAI 回复ToolMessage(content, tool_call_id)ToolMessage(content: str, tool_call_id: str)content: 工具结果;tool_call_id: 调用 IDToolMessage工具执行结果SystemMessage(content)SystemMessage(content: str)content: 系统提示词SystemMessage系统提示tool装饰器tool函数必须包含 docstring带 tool 元数据的函数将函数标记为工具ToolNode(tools)ToolNode(tools: list)tools: 工具列表可调用节点自动处理工具调用tools_condition内置函数无路由函数判断 AIMessage 是否有 tool_callsllm.bind_tools(tools)bind_tools(tools: list)tools: 工具列表Runnable绑定工具的 LLM让 LLM 知道可用工具4.5 错误与避坑指南坑 1ToolMessage 缺少 tool_call_id# ❌ 错误写法ToolMessage(content结果,tool_call_id)# 空 ID 或错误 ID# → LLM 无法将工具结果与调用关联导致混淆# ✅ 正确写法从 AIMessage.tool_calls 中获取 tool_call_idfortool_callinlast_message.tool_calls:resultexecute_tool(tool_call)tool_messages.append(ToolMessage(contentresult,tool_call_idtool_call[id]))坑 2工具函数返回值类型不兼容# ❌ 错误写法tooldefbad_tool(query:str)-dict:# 返回 dict → LLM 可能无法理解return{status:ok,data:[...]}# ✅ 正确写法tooldefgood_tool(query:str)-str:# 返回 str → LLM 可以理解returnf查询结果找到 3 条相关记录坑 3忘记 bind_tools# ❌ 错误写法llmChatOpenAI(modelgpt-4o)# 直接使用 llmLLM 不知道有哪些工具可用# → LLM 不会生成 tool_calls工具永远不会被调用# ✅ 正确写法llmChatOpenAI(modelgpt-4o)llm_with_toolsllm.bind_tools(tools)# 必须绑定工具坑 4工具调用死循环# ❌ 错误tools_condition 未正确路由builder.add_conditional_edges(agent,tools_condition)# 如果 tools_condition 始终返回 tools会无限循环# ✅ 正确tools → agent 后agent 检查是否还有 tool_callsbuilder.add_conditional_edges(agent,tools_condition)builder.add_edge(tools,agent)# tools_condition 在 agent 没有 tool_calls 时返回 END4.6 最佳实践总结工具函数添加详细的 docstringLLM 根据 docstring 决定何时调用哪个工具描述越清晰调用越准确使用handle_tool_errorsTrueToolNode(tools, handle_tool_errorsTrue)优雅处理工具执行异常工具返回字符串LLM 更容易理解文本格式的工具结果复杂场景用create_react_agent简单场景手写 StateGraph不要过度设计工具设计遵循单一职责每个工具只做一件事多个简单工具胜过一个大而全的工具

相关新闻

Premium 推广卡片:金色边框 + 阴影 + 立即开通按钮

Premium 推广卡片:金色边框 + 阴影 + 立即开通按钮

前言 “海风日记“的“我的“页面中,Premium 推广卡片以金色边框和阴影突出显示,引导用户开通高级订阅。 本文将从源码出发,深入讲解 Premium 推广卡片的实现。 一、Premium 卡片 Row({ space: 16 }) {Column({ space: 4 }) {Row({ space:…

2026/10/17 22:38:12 阅读更多 →
Claude 连不上数据库?MCP 服务器 30 分钟从零搭一个

Claude 连不上数据库?MCP 服务器 30 分钟从零搭一个

14:00 痛点先摆在台面上 Claude 只能读写文件,连个数据库都查不了,这怎么当生产力工具? 我下午被这事儿卡了快二十分钟。想让 Claude 帮我跑一段用户留存分析,数据在远端,结果它一句"我没有数据库访问能力"把…

2026/10/18 5:47:01 阅读更多 →
多声道音频下混算法原理:5.1 环绕转双声道人声不丢失的工程落地

多声道音频下混算法原理:5.1 环绕转双声道人声不丢失的工程落地

1. 引言:为何需要下混? 在数字音频处理领域,多声道音频(如 5.1、7.1 环绕声)与双声道立体声(Stereo)的兼容性是一个经典且关键的工程问题。无论是流媒体平台的内容分发、游戏音频的实时渲染,还是家庭影院系统的播放,我们常常需要将制作精良的 5.1 环绕声内容“下混”…

2026/10/18 5:47:02 阅读更多 →

最新新闻

URL Protocol自定义协议:从注册表到网页唤起本地程序全攻略

URL Protocol自定义协议:从注册表到网页唤起本地程序全攻略

你有没有遇到过这样的需求:网页上某个按钮,点击后最好直接唤起本地安装的客户端程序,而不是让用户自己去安装目录找快捷方式。比如网盘网页版点“打开客户端”、在线文档点“编辑”,几乎所有主流的桌面软件都在用这种交互。实现这…

2026/10/18 14:14:23 阅读更多 →
豆瓣电影Top250爬虫+Flask后台+PyEcharts可视化全流程

豆瓣电影Top250爬虫+Flask后台+PyEcharts可视化全流程

简介:这是一套面向计算机专业本科生的毕业设计与课程大作业实战项目,基于PythonFlask构建豆瓣电影数据的全链路处理系统,涵盖网络爬虫采集、SQLite本地存储、后端业务逻辑开发及前端可视化展示四大核心环节,适合中等难度项目实践与…

2026/10/18 14:14:23 阅读更多 →
SpeedTree 10到UE5 Nanite:告别纸片树冠的透射与季节重构

SpeedTree 10到UE5 Nanite:告别纸片树冠的透射与季节重构

“纸片树冠”这个说法,干这行的人一听就懂。就是那种树干做得挺像样,树冠却靠几张交叉面片硬撑,远看还行,一走近或者镜头稍微压低,立刻露馅的植被资产。2023年以后再拿这种东西放到Nanite工作流里,其实已经…

2026/10/18 14:14:23 阅读更多 →
Unity自动化构建与SVN自动提交:构建产物一键发布方案

Unity自动化构建与SVN自动提交:构建产物一键发布方案

Unity打包后自动复制到指定位置并SVN提交做项目做久了就会发现,真正消耗时间的不一定是写代码,而是那些"重复但必须做"的收尾工作。尤其多人在线协作的项目里,每次出包测试版,要么手动把构建产物拖到共享目录&#xff0…

2026/10/18 14:14:23 阅读更多 →
网页看板娘实战指南:从Live2D部署到性能优化

网页看板娘实战指南:从Live2D部署到性能优化

1. 为什么网页需要一个"会动"的看板娘如果你做过几年前端或者个人站点的维护,应该对这样一类现象不陌生:一个功能完善、内容扎实的博客或产品页,上线后总感觉少了点什么。少了"活气"。静态页面再精致,用户打开…

2026/10/18 14:14:23 阅读更多 →
谷歌AI Agent白皮书核心解读:从编排层到工具调用的落地实践

谷歌AI Agent白皮书核心解读:从编排层到工具调用的落地实践

简介:谷歌《2025谷歌AI Agent白皮书》系统梳理了生成式人工智能代理的设计蓝图,面向人工智能工程师、架构师与技术决策者,帮助读者理解代理与传统模型的本质差异,以及如何借助数据库检索、API调用等外部工具自主规划并执行任务。这…

2026/10/18 14:13:22 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →