news 2026/9/5 10:51:26

LangChain实战快速入门笔记(五)--LangChain使用之Tools

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain实战快速入门笔记(五)--LangChain使用之Tools

LangChain实战快速入门笔记(五)–LangChain使用之Tools

文章目录

  • LangChain实战快速入门笔记(五)--LangChain使用之Tools
  • 一、Tools概述
    • 1. 介绍
    • 2. Tool 的要素
  • 二、自定义工具
    • 1. 两种自定义方式
      • 第1种:使用@tool装饰器(自定义工具的最简单方式)
      • 第2种:使用StructuredTool.from_function类方法
    • 2. 几个常用属性
    • 3. 具体实现
      • 方式1:@tool 装饰器
        • 举例1:
        • 举例2:通过@tool的参数设置进行重置
      • 方式2:StructuredTool的from_function()
    • 4. 工具调用举例
      • 举例1:大模型分析调用工具
      • 调用工具说明
        • 情况1:大模型决定调用工具
        • 情况2:大模型不调用工具
        • 举例2:确定工具并调用
          • (1) 检查是否需要调用工具
          • (2) 实际执行工具调用
  • 总结

一、Tools概述

1. 介绍

要构建更强大的AI工程应用,只有生成文本这样的“纸上谈兵”能力自然是不够的。工具Tools不仅仅是“肢体”的延伸,更是为“大脑”插上了想象力的“翅膀”。借助工具,才能让AI应用的能力真正具备无限的可能,才能从“认识世界”走向“改变世界”。

Tools 用于扩展大语言模型(LLM)的能力,使其能够与外部系统、API 或自定义函数交互,从而完成
仅靠文本生成无法实现的任务(如搜索、计算、数据库查询等)。

特点:
增强 LLM 的功能:让 LLM 突破纯文本生成的限制,执行实际操作(如调用搜索引擎、查询数据
库、运行代码等)
支持智能决策:在Agent 工作流中,LLM 根据用户输入动态选择最合适的 Tool 完成任务。
模块化设计:每个 Tool 专注一个功能,便于复用和组合(例如:搜索工具 + 计算工具 + 天气查
询工具)

LangChain 拥有大量第三方工具。请访问工具集成查看可用工具列表。
https://python.langchain.com/v0.2/docs/integrations/tools/

2. Tool 的要素

Tools 本质上是封装了特定功能的可调用模块,是Agent、Chain或LLM可以用来与世界互动的接口。

Tool 通常包含如下几个要素:
name:工具的名称
description:工具的功能描述
• 该工具输入的JSON模式
• 要调用的函数
return_direct:是否应将工具结果直接返回给用户(仅对Agent相关)

实操步骤:
• 步骤1:将name、description 和 JSON模式作为上下文提供给LLM
• 步骤2:LLM会根据提示词推断出需要调用哪些工具,并提供具体的调用参数信息
• 步骤3:用户需要根据返回的工具调用信息,自行触发相关工具的回调

注意:
如果⼯具具有精心选择的名称、描述和JSON模式,则模型的性能将更好。
下⼀章内容我们可以看到⼯具的调⽤动作可以通过Agent⾃主接管。

二、自定义工具

1. 两种自定义方式

第1种:使用@tool装饰器(自定义工具的最简单方式)

装饰器默认使用函数名称作为工具名称,但可以通过参数name_or_callable来覆盖此设置。

同时,装饰器将使用函数的文档字符串作为工具的描述,因此函数必须提供文档字符串。

第2种:使用StructuredTool.from_function类方法

这类似于@tool装饰器,但允许更多配置和同步/异步实现的规范。

2. 几个常用属性

Tool由几个常用属性组成:

3. 具体实现

方式1:@tool 装饰器

举例1:
fromlangchain.toolsimporttool@tooldefadd_number(a:int,b:int)->int:"""两个整数相加"""returna+bprint(f'name ={add_number.name}')print(f'args ={add_number.args}')print(f'description ={add_number.description}')print(f'return_direct ={add_number.return_direct}')res=add_number.invoke({"a":10,"b":20})print(res)


说明:return_direct参数的默认值是False。当return_direct=False时,工具执行结果会返回给Agent,让Agent决定下一步操作;而return_direct=True则会中断这个循环,直接结束流程,返回结果给用户。

举例2:通过@tool的参数设置进行重置
fromlangchain.toolsimporttool@tool(name_or_callable="add_two_number",description="two number add",return_direct=True)defadd_number(a:int,b:int)->int:"""两个整数相加"""returna+bprint(f'name ={add_number.name}')print(f'description ={add_number.description}')print(f'args ={add_number.args}')print(f'return_direct ={add_number.return_direct}')res=add_number.invoke({"a":10,"b":20})print(res)


补充:还可以修改参数的说明

fromlangchain.toolsimporttoolfrompydanticimportBaseModel,FieldclassFieldInfo(BaseModel):a:int=Field(description="第1个参数")b:int=Field(description="第2个参数")@tool(name_or_callable="add_two_number",description="two number add",args_schema=FieldInfo,return_direct=True)defadd_number(a:int,b:int)->int:"""两个整数相加"""returna+bprint(f'name ={add_number.name}')print(f'description ={add_number.description}')print(f'args ={add_number.args}')print(f'return_direct ={add_number.return_direct}')res=add_number.invoke({"a":10,"b":20})print(res)

方式2:StructuredTool的from_function()

StructuredTool.from_function类方法提供了比**@tool**装饰器更多的可配置性,而无需太多额外的代
码。

举例1:

fromlangchain_core.toolsimportStructuredTooldefsearch_function(query:str):return"LangChain"search1=StructuredTool.from_function(func=search_function,name="Search",description="useful for when you need to answer questions about current events")print(f'name ={search1.name}')print(f'description ={search1.description}')print(f'args ={search1.args}')search1.invoke("hello")


举例2:

fromlangchain_core.toolsimportStructuredToolfrompydanticimportField,BaseModelclassFieldInfo(BaseModel):query:str=Field(description="要检索的关键词")defsearch_function(query:str):return"LangChain"search1=StructuredTool.from_function(func=search_function,name="Search",description="useful for when you need to answer questions about current events",args_schema=FieldInfo,return_direct=True,)print(f'name ={search1.name}')print(f'description ={search1.description}')print(f'args ={search1.args}')print(f'return_direct ={search1.return_direct}')search1.invoke("hello")

4. 工具调用举例

我们通过大模型分析用户需求,判断是否需要调用指定工具。

举例1:大模型分析调用工具

#1.导入相关依赖fromlangchain_community.toolsimportMoveFileToolfromlangchain_core.messagesimportHumanMessagefromlangchain_core.utils.function_callingimportconvert_to_openai_functionimportosimportdotenvfromlangchain_openaiimportChatOpenAI dotenv.load_dotenv()os.environ["OPENAI_API_KEY"]=os.getenv("OPENAI_API_KEY")os.environ["OPENAI_BASE_URL"]=os.getenv("OPENAI_BASE_URL")#2.定义LLM模型chat_model=ChatOpenAI(model="gpt-4o-mini",temperature=0)#3.定义工具tools=[MoveFileTool()]#4.这里需要将工具转换为openai函数,后续再将函数传入模型调用functions=[convert_to_openai_function(t)fortintools]#print(functions[0])#5.提供大模型调用的消息列表messages=[HumanMessage(content="将文件a移动到桌面")]#6.模型使用函数response=chat_model.invoke(input=messages,functions=functions)print(response)


模型绑定工具,调用模型,传入Message对象。

作为对照,修改代码:

response=chat_model.invoke([HumanMessage(content="今天的天气怎么样?")],functions=functions)print(response)


调用工具说明

两种情况:

情况1:大模型决定调用工具

如果模型认为需要调用工具(如MoveFileTool),返回的message会包含:
• content : 通常为空(因为模型选择调用工具,而非生成自然语言回复)。
• additional_kwargs : 包含工具调用的详细信息:

AIMessage(content="",# 无自然语言回复additional_kwargs={'function_call':{'name':'move_file',# 工具名称'arguments':'{"source_path": "a", "destination_path": "/Users/YourUsername/Desktop/a"}'# 工具参数}})
情况2:大模型不调用工具

如果模型认为无需调用工具(例如用户输入与工具无关),返回的message会是普通文本回复:

AIMessage(content="我没有找到需要移动的文件。",# 自然语言回复additional_kwargs={"refusal":None}# 无工具调用)
举例2:确定工具并调用
# 定义LLM模型chat_model=ChatOpenAI(model="gpt-4o-mini",temperature=0)# 定义工具tools=[MoveFileTool()]# 将工具转换为openai函数functions=[convert_to_openai_function(t)fortintools]# 提供消息列表messages=[HumanMessage(content="将本目录下的abc.txt文件移动到C:\\Users\\shkst\\Desktop")]# 模型调用response=chat_model.invoke(input=messages,functions=functions)print(response)

(1) 检查是否需要调用工具
importjsonif"function_call"inresponse.additional_kwargs:tool_name=response.additional_kwargs["function_call"]["name"]tool_args=json.loads(message.additional_kwargs["function_call"]["arguments"])print(f"调用工具:{tool_name}, 参数:{tool_args}")else:print("模型回复: ",response.content)

(2) 实际执行工具调用
fromlangchain.toolsimportMoveFileToolif"move_file"inresponse.additional_kwargs["function_call"]["name"]:tool=MoveFileTool()result=tool.run(tool_args)# 执行工具print("工具执行结果: ",result)

大模型与 Agent 的核心区别:是否涉及到工具的调用

针对大模型:仅能分析出要调用的工具,但是此工具(或函数)不能真正的执行

针对 Agent:除了分析出要调用的工具之外,还可以执行具体的工具(或函数)

总结

记得关注么么哒

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 5:41:19

【PHP性能优化关键一步】:深入PHP 8.6内存泄漏监控与自动预警方案

第一章:PHP 8.6 内存泄漏检测概述在现代Web应用开发中,PHP 8.6 引入了多项性能优化与内存管理改进,但复杂的应用逻辑仍可能导致内存泄漏问题。内存泄漏会逐渐消耗系统资源,最终导致脚本执行失败或服务器响应变慢。因此&#xff0c…

作者头像 李华
网站建设 2026/9/5 15:09:28

PHP 8.6兼容性测试实战(资深架构师亲授迁移经验)

第一章:PHP 8.6兼容性测试概述随着 PHP 8.6 的发布临近,开发者社区对新版本的期待与关注持续升温。该版本预计将引入多项性能优化、语法增强以及底层引擎改进,因此在升级前进行全面的兼容性测试显得尤为关键。兼容性测试不仅确保现有项目能在…

作者头像 李华
网站建设 2026/9/5 19:28:47

从入门到精通:用R Shiny打造可交互的多维度数据仪表盘

第一章:R Shiny 的多模态图表交互控件在构建数据驱动的 Web 应用时,R Shiny 提供了强大的交互能力,尤其在多模态图表控件的集成方面表现突出。通过结合输入控件与动态渲染函数,开发者能够实现用户操作与可视化输出的实时联动。基础…

作者头像 李华
网站建设 2026/9/5 14:19:51

光伏阵列遇到局部阴影就像吃火锅被隔壁桌抢肉——憋屈得很。今天咱们用Python整活,搞个3×3电池板的阴影仿真模型,重点观察串联结构在阴影下的输出曲线怎么抽风

3行3列的太阳能电池板局部遮阴仿真模型 可自己更改光照强度,十分方便 由于光伏电池的非线性受控电流源的特性,串联光伏阵列和并联光伏阵列在阴影条件下的输出特性是不同的。 当串联光伏阵列处于强阴影遮蔽时,即部分光伏电池辐照度严重降低时&…

作者头像 李华
网站建设 2026/9/5 14:32:41

你还不知道HTTP/3的这5个性能秘密?:资深架构师20年经验倾囊相授

第一章:HTTP/3 性能革命的底层逻辑HTTP/3 并非简单地对前代协议进行功能叠加,而是一次基于传输层重构的性能跃迁。其核心变革在于放弃沿用多年的 TCP 协议,转而采用基于 UDP 的 QUIC 协议作为传输基础。这一转变从根本上解决了队头阻塞问题—…

作者头像 李华
网站建设 2026/9/5 21:40:12

如何将EF Core响应时间降低80%?一线大厂都在用的4种策略

第一章:EF Core 的性能 Entity Framework Core(EF Core)作为 .NET 平台主流的 ORM 框架,在提供开发便利性的同时,其性能表现直接影响应用的响应速度与资源消耗。合理使用 EF Core 的特性可以显著提升数据访问效率&…

作者头像 李华