2026/2/19 7:37:37
网站建设
项目流程
下城区网站建设价格查询,华山游玩路线攻略,茶叶网站建设策划方案u001f,html网站源代码下载LangChain Tools深度解析#xff1a;让Agent拥有超能力
前言
这篇是 LangChain 系列的学习笔记#xff0c;这次整理的是第五章 Tools#xff08;工具#xff09;模块。
说到 Tools#xff0c;这可是 Agent 的核心能力。你想想#xff0c;大模型再强大也只是会说…LangChain Tools深度解析让Agent拥有超能力前言这篇是LangChain系列的学习笔记这次整理的是第五章Tools工具模块。说到Tools这可是Agent的核心能力。你想想大模型再强大也只是会说话而已它不能帮你移动文件、不能帮你查询天气、不能帮你计算复杂的数学公式。但有了Tools大模型就像获得了手一样可以真正做一些实际的操作了。本篇会详细介绍如何定义自定义工具、如何让大模型分析工具调用以及完整的工具调用流程。你会发现原来给Agent赋予超能力是这么简单的事儿。个人主页山沐与山文章目录一、什么是Tools二、自定义工具tool装饰器2.1 最基础的用法2.2 带参数的装饰器2.3 使用Pydantic精确控制参数三、StructuredTool.from_function()方式3.1 基础用法3.2 使用自定义参数描述3.3 tool vs StructuredTool该用哪个四、大模型如何分析工具调用4.1 工具转换为函数格式4.2 大模型的分析结果4.3 完整的工作流程五、实际调用工具5.1 解析function_call5.2 根据工具名称调用对应工具5.3 完整的调用流程六、常见问题七、总结热门专栏推荐一、什么是 Tools在LangChain中Tools工具是指可以被大模型调用的函数或接口。听起来有点抽象举个例子就明白了假设你问ChatGPT“帮我把桌面上的report.pdf移动到Documents文件夹”。ChatGPT会回答“我无法直接操作您的文件系统但您可以手动进行以下操作……”为什么它做不到因为它只是个语言模型没有操作系统权限。但在LangChain里我们可以给大模型定义一个移动文件的工具。当用户发出同样的请求时大模型会分析用户意图“哦用户想移动文件”选择对应的工具“我有一个MoveFileTool”提取参数“源路径是Desktop/report.pdf目标路径是Documents/”调用工具真正执行移动操作这就是Tools的作用。二、自定义工具tool 装饰器定义一个工具最简单的方式就是用tool装饰器。2.1 最基础的用法代码来自01-自定义工具.ipynbfromlangchain_core.toolsimporttooltooldefadd_numbers(a:int,b:int)-int:计算两个整数的和returnab# 看看这个工具的属性print(f工具名称:{add_numbers.name})print(f工具参数:{add_numbers.args})print(f工具描述:{add_numbers.description})print(f直接返回:{add_numbers.return_direct})输出工具名称: add_numbers 工具参数: {a: {title: A, type: integer}, b: {title: B, type: integer}} 工具描述: 计算两个整数的和 直接返回: False看到没有你只需要写一个普通函数加上类型注解a: int, b: int - int写个docstring三引号注释加个tool装饰器LangChain就会自动把它变成一个工具工具的描述会自动从docstring里提取参数信息会从类型注解里推断。2.2 带参数的装饰器如果你想自定义工具的名字、描述等属性可以给tool传参数tool(name_or_callableadd_two_numbers,# 自定义工具名称return_directTrue,# 是否直接返回结果description这是一个计算两个整数和的函数# 自定义描述)defadd_numbers(a:int,b:int)-int:计算两个整数的和returnabprint(f工具名称:{add_numbers.name})print(f直接返回:{add_numbers.return_direct})print(f工具描述:{add_numbers.description})输出工具名称: add_two_numbers 直接返回: True 工具描述: 这是一个计算两个整数和的函数这里的return_directTrue是个挺有意思的参数。如果设置为TrueAgent调用这个工具后会直接返回结果不会再做额外处理。如果是False默认值Agent可能会拿着结果继续思考、继续调用其他工具。2.3 使用 Pydantic 精确控制参数有时候你想给参数加更详细的说明让大模型更容易理解这个参数的含义。这时候可以用Pydantic的BaseModelfrompydanticimportBaseModel,FieldclassFieldInfo(BaseModel):a:intField(description第一个整型参数)b:intField(description第二个整型参数)tool(name_or_callableadd_two_numbers,return_directTrue,description这是一个计算两个整数和的函数,args_schemaFieldInfo# 使用 Pydantic 模型定义参数)defadd_numbers(a:int,b:int)-int:计算两个整数的和returnabprint(add_numbers.args)输出{ a: {description: 第一个整型参数, type: integer}, b: {description: 第二个整型参数, type: integer} }这样一来大模型在分析用户输入时会更清楚每个参数的含义调用工具的准确度也会提高。三、StructuredTool.from_function() 方式除了tool装饰器还有一种更灵活的方式StructuredTool.from_function()。3.1 基础用法代码来自01-自定义工具.ipynbfromlangchain_core.toolsimportStructuredTooldefsearch_engine(query:str):一个搜索引擎的模拟函数return最后查询到的结果# 用 StructuredTool 包装函数search_toolStructuredTool.from_function(funcsearch_engine,namesearch_engine,description一个搜索引擎的模拟函数,return_directTrue)# 调用工具resultsearch_tool.invoke({query:Python})print(result)# 输出: 最后查询到的结果这种方式的好处是你可以把函数定义和工具配置分开。如果你有一些现成的函数不想改比如来自第三方库用这种方式就很方便。3.2 使用自定义参数描述同样你也可以用Pydantic给参数加详细描述frompydanticimportBaseModel,FieldclassFieldInfo(BaseModel):query:strField(description搜索的关键词)search_tool01StructuredTool.from_function(funcsearch_engine,namesearch_engine,description一个搜索引擎的模拟函数,return_directTrue,args_schemaFieldInfo)print(search_tool01.args)输出{query: {description: 搜索的关键词, type: string}}3.3 tool vs StructuredTool该用哪个其实这俩没啥本质区别看你喜欢哪种风格tool装饰器写法简洁适合快速定义新工具StructuredTool.from_function()配置灵活适合包装已有函数我个人更喜欢tool因为看起来更简洁。但如果是要包装第三方库的函数还是StructuredTool更方便。四、大模型如何分析工具调用定义工具只是第一步更重要的是让大模型能够理解这些工具并在合适的时候调用它们。4.1 工具转换为函数格式大模型比如GPT-4本身支持Function Calling功能但它需要特定的格式。LangChain提供了一个工具函数来做转换代码来自02-大模型分析工具的调用.ipynbfromlangchain_core.utils.function_callingimportconvert_to_openai_functionfromlangchain_community.toolsimportMoveFileToolfromlangchain_core.messagesimportHumanMessagefromlangchain_openaiimportChatOpenAIimportosimportdotenv# 加载环境变量dotenv.load_dotenv()# 初始化大模型llmChatOpenAI(modelgpt-4o-mini,temperature0)# 创建工具列表tools[MoveFileTool()]# 转换为 OpenAI 函数格式functions[convert_to_openai_function(tool)fortoolintools]# 构造用户消息messages[HumanMessage(content将文件a移动到桌面)]# 调用大模型传入 functions 参数responsellm.invoke(inputmessages,functionsfunctions)print(response)注意这里的关键点使用convert_to_openai_function()把LangChain的工具转换成OpenAI的函数格式调用llm.invoke()时传入functions参数不是tools4.2 大模型的分析结果运行上面的代码大模型会返回一个AIMessage对象。这个对象有两种可能的情况情况 1找到匹配的工具AIMessage(content,# 内容为空因为大模型决定调用工具additional_kwargs{function_call:{name:move_file,arguments:{source_path:a,destination_path:/Users/YourUsername/Desktop/a}}})看到了吗content是空的因为大模型没有生成文本回复而是决定调用move_file这个工具。所有调用信息都在additional_kwargs[function_call]里name要调用的工具名称argumentsJSON格式的参数情况 2没找到匹配的工具如果用户问的是“查询上海明天的天气信息”但你只提供了MoveFileTool那么大模型会发现没有合适的工具于是直接返回文本回复messages[HumanMessage(content查询上海明天的天气信息)]responsellm.invoke(inputmessages,functionsfunctions)print(response)输出AIMessage(content抱歉我无法提供实时的天气信息。建议您查看天气预报网站或使用天气应用程序获取上海明天的天气信息。,additional_kwargs{}# 没有 function_call)所以判断大模型是否要调用工具只需要检查additional_kwargs里是否有function_call字段。4.3 完整的工作流程让我用图示表示一下整个流程用户输入: 将文件 a 移动到桌面 ↓ 传给大模型 (附带 functions 列表) ↓ 大模型分析: - 用户想做什么移动文件 - 我有什么工具MoveFileTool - 匹配吗匹配 - 需要什么参数source_path 和 destination_path ↓ 返回 AIMessage: - content: (空) - function_call: { name: move_file, arguments: {source_path:a, destination_path:/Users/.../Desktop/a} }五、实际调用工具前面我们说了大模型只是分析出要调用哪个工具但工具并没有真正执行。这是大模型和Agent的区别大模型只负责分析生成function_call指令Agent不仅分析还会真正执行工具在这个章节我们先手动执行工具下一章讲Agent时就能自动执行了。5.1 解析 function_call代码来自02-大模型分析工具的调用.ipynbimportjson# 检查是否有 function_calliffunction_callinresponse.additional_kwargs:# 提取工具名称和参数tool_nameresponse.additional_kwargs[function_call][name]tool_argsjson.loads(response.additional_kwargs[function_call][arguments])print(f函数名/工具名:{tool_name})print(f函数参数:{tool_args})else:# 没有 function_call说明大模型直接回复了print(f模型回复:{response.content})输出函数名/工具名: move_file 函数参数: {source_path: a.txt, destination_path: C:\\Users\\Chenxr\\Desktop\\a.txt}这里用json.loads()把arguments字符串解析成Python字典方便后续使用。5.2 根据工具名称调用对应工具有了工具名称和参数接下来就是调用真正的工具了ifmove_fileinresponse.additional_kwargs[function_call][name]:# 创建工具实例toolMoveFileTool()# 调用工具resulttool.run(tool_args)print(f工具调用结果:{result})输出工具调用结果: File moved successfully from a.txt to C:\Users\Chenxr\Desktop\a.txt.这样文件就真的被移动了5.3 完整的调用流程把前面的代码串起来完整的流程是这样的fromlangchain_core.utils.function_callingimportconvert_to_openai_functionfromlangchain_community.toolsimportMoveFileToolfromlangchain_core.messagesimportHumanMessagefromlangchain_openaiimportChatOpenAIimportjsonimportdotenv dotenv.load_dotenv()# 1. 准备工具tools[MoveFileTool()]functions[convert_to_openai_function(tool)fortoolintools]# 2. 初始化大模型llmChatOpenAI(modelgpt-4o-mini,temperature0)# 3. 用户输入messages[HumanMessage(content将文件a.txt移动到桌面)]# 4. 大模型分析responsellm.invoke(inputmessages,functionsfunctions)# 5. 检查是否需要调用工具iffunction_callinresponse.additional_kwargs:tool_nameresponse.additional_kwargs[function_call][name]tool_argsjson.loads(response.additional_kwargs[function_call][arguments])print(f工具名:{tool_name})print(f参数:{tool_args})# 6. 调用工具iftool_namemove_file:toolMoveFileTool()resulttool.run(tool_args)print(f结果:{result})else:# 没有匹配的工具输出大模型的回复print(f模型回复:{response.content})这就是Tools的完整工作流程。虽然这里是手动调用但这正是Agent内部的运行逻辑。六、常见问题学Tools过程中这几个问题经常被问到6.1 tool 和 StructuredTool 该用哪个看场景选择场景推荐原因新写的函数tool装饰器简洁、直观代码更清晰包装已有函数如第三方库StructuredTool.from_function()不需要修改原函数需要复杂参数验证都可以 Pydantic通过args_schema精确控制6.2 为什么给参数加 description 这么重要因为大模型是靠理解来调用工具的。没有描述时大模型只能通过参数名猜测含义容易出错。比如参数名是path大模型不知道是源路径还是目标路径。# ❌ 不好大模型不知道 path 是什么defmove_file(path:str):pass# ✅ 好清楚明确classMoveFileArgs(BaseModel):source_path:strField(description要移动的文件的原始路径)dest_path:strField(description文件的目标位置路径)通过Pydantic的Field()给参数加详细描述可以显著提高调用准确率。6.3 大模型调用工具和 Agent 有什么区别关键区别谁来执行工具。对比项大模型 functions参数Agent分析用户意图✅✅生成function_call✅✅实际执行工具❌ 需要手动执行✅ 自动执行多轮调用❌✅大模型只是建议调用什么工具返回function_call指令。而Agent会真的去调用工具还能根据结果决定是否继续调用其他工具。6.4 调用工具时报错 “function_call not found” 怎么办检查这几点传参名称错误应该是functions不是tools# ❌ 错误responsellm.invoke(messages,toolsfunctions)# ✅ 正确responsellm.invoke(messages,functionsfunctions)模型不支持确保使用支持Function Calling的模型如gpt-4o-mini、gpt-4等工具格式转换确保使用了convert_to_openai_function()进行转换functions[convert_to_openai_function(tool)fortoolintools]七、总结这篇文章介绍了LangChain的Tools模块核心内容包括什么是 Tools可以被大模型调用的函数或接口让大模型拥有实际操作能力定义工具的方式tool装饰器和StructuredTool.from_function()两种方式参数精确控制通过Pydantic的Field()给参数加详细描述工具调用流程定义工具 → 转换格式 → 大模型分析 → 解析结果 → 执行工具关键区别大模型只做分析Agent会真正执行工具关键要点总结表概念说明适用场景注意事项tool装饰器最简单的定义方式新写的工具函数需要类型注解和docstringStructuredTool灵活的包装方式包装已有函数适合第三方库函数Pydantic参数描述精确控制参数信息参数含义不明确时显著提高调用准确率Function CallingOpenAI的工具调用机制所有需要调用工具的场景传参名是functions不是tools下一步有了Tools接下来就是Agent了。Agent可以自动完成工具的分析和执行还能进行多轮的工具调用实现计划 → 执行 → 观察 → 再计划的循环。热门专栏推荐Agent小册服务器部署Java基础合集Python基础合集Go基础合集大数据合集前端小册数据库合集Redis 合集Spring 全家桶微服务全家桶数据结构与算法合集设计模式小册消息队列合集等等等还有许多优秀的合集在主页等着大家的光顾感谢大家的支持文章到这里就结束了如果有什么疑问的地方请指出诸佬们一起来评论区一起讨论希望能和诸佬们一起努力今后我们一起观看感谢您的阅读如果帮助到您不妨3连支持一下创造不易您们的支持是我的动力