当前位置: 首页 > article >正文

LangChain【7】之工具创建和错误处理策略

文章目录

  • 一 LangChain 自定义工具概述
  • 二创建自定义工具的三种方法
    • 2.1 方法一:@tool 装饰器
      • 2.1.1 同步方法案例
      • 2.1.2 工具描述方式1:传参
      • 2.1.3 工具描述方式2:文档字符串
    • 2.2 方法二:StructuredTool类
      • 2.2.1 StructuredTool创建自定义工具
      • 2.2.2 StructuredTool配置信息
    • 2.3 方法三:BaseTool类
  • 三 异步工具的实现
  • 四 工具错误处理策略

一 LangChain 自定义工具概述

  • LangChain提供了一套工具、组件和接口,可简化创建由大型语言模型(LLM)和聊天模型提供支持的应用程序的过程。
  • 在构建智能代理时,为其提供合适的工具是确保其强大功能的关键,LangChain作为一个支持创建和管理工具的框架,能让开发者以模块化方式扩展代理的能力。

  • 当构建代理时,需要为其提供一组工具列表,代理可以使用这些工具。除了调用的实际函数之外,工具由几个组件组成:
    • name(str)是必需的,并且在提供给代理的工具集中必须是唯一的;
    • description(str)是可选的但建议的,因为代理使用它来确定工具的使用方式;
    • return_direct(bool)默认为False;
    • args_schema(PydanticBaseModel)是可选的但建议的,可以用于提供更多信息或用于验证预期参数。

二创建自定义工具的三种方法

  • LangChain为开发人员提供了不同的方式来创建工具,这些工具可以被智能代理或语言模型调用。
    • 第一种方法是使用@tool装饰器(定义自定义工具的最简单方法);
    • 第二种方法是使用StructuredTool类,允许更细粒度的配置而无需过多的代码;
    • 第三种方法是基于BaseTool类构造子类显式自定义工具,工具定义提供最大限度的把控,但需要做更多的工作。

2.1 方法一:@tool 装饰器

  • 使用@tool修饰符是自定义工具最简单的方法。默认情况下修饰符用函数的名字作为工具名称,但传字符串作为第一个参数可以重命名工具名称。例如,可以创建一个总是返回字符串"LangChain"的虚构搜索函数,或者将两个数字相乘的乘法函数。这些函数最大的区别是第一个函数只有一个输入,第二个函数需要多个输入。

2.1.1 同步方法案例

from langchain_core.tools import tool
@tool
def multiply(a:int,b:int)->int:"""Multiply two numbers"""return a*bprint(multiply.name) # multiply
print(multiply.description) # Multiply two numbers
print(multiply.args) # {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}

2.1.2 工具描述方式1:传参

  • 通过将工具名称和 JSON 参数传递给工具装饰器进行自定义
from langchain_core.tools import tool
from pydantic import BaseModel, Fieldclass CalculatorInput(BaseModel):a: int = Field(description="The first number")b: int = Field(description="The second number")@tool("multiplication-tool", args_schema=CalculatorInput, return_direct=True)
def multiply(a: int, b: int) -> int:"""Multiply two numbers"""return a * bprint(multiply.name)  # multiplication-tool
print(multiply.description)  # Multiply two numbers
print(multiply.args)  # {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}
print(multiply.return_direct)  # True

2.1.3 工具描述方式2:文档字符串

  • @tool 可以选择性地解析 Google 风格文档字符串,并将文档字符串组件(如参数描述)与工具模式的相关部分关联起来。
@tool(parse_docstring=True)
def foo(bar: str, baz: int) -> str:"""The foo.Args:bar: The bar.baz: The baz."""return bar
foo.args_schema.schema()
{'description': 'The foo.','properties': {'bar': {'description': 'The bar.','title': 'Bar','type': 'string'},'baz': {'description': 'The baz.', 'title': 'Baz', 'type': 'integer'}},'required': ['bar', 'baz'],'title': 'fooSchema','type': 'object'}

2.2 方法二:StructuredTool类

  • 使用StructuredTool类,允许更细粒度的配置而无需过多的代码

2.2.1 StructuredTool创建自定义工具

  • 使用StructuredToolfrom_function可以创建自定义工具,包含两个参数func,coroutine,分别指定同步方法和异步方法。
import asyncio
from langchain_core.tools import StructuredTooldef multiply(a:int,b:int)->int:"""Multiply two numbers"""return a*b
async def a_multiply(a:int,b:int)->int:"""Multiply two numbers"""return a*basync def main():calculator=StructuredTool.from_function(func=multiply,coroutine=a_multiply)print(calculator.run({"a":2, "b":3}))print(calculator.invoke({"a":2, "b":3}))print(await calculator.ainvoke({"a":2, "b":5}))asyncio.run(main())

2.2.2 StructuredTool配置信息

import asyncio
from langchain_core.tools import StructuredTool
from pydantic import Field, BaseModelclass CalculatorInput(BaseModel):a: int = Field(description="The first number")b: int = Field(description="The second number")#创建同步、异步包装器函数
def multiply(a:int,b:int)->int:"""Multiply two numbers"""return a*b
async def async_multiply(a:int,b:int)->int:"""Multiply two numbers"""return a*basync def main():calculator=StructuredTool.from_function(func=multiply,name="calculator",description="Multiply two numbers",args_schema=CalculatorInput,coroutine=async_multiply,return_direct=True)print(calculator.name)print(calculator.description)print(calculator.args)asyncio.run(main())

2.3 方法三:BaseTool类

  • 接受字符串或 dict 输入的 LangChain Runnables 可以使用 as_tool 方法转换为工具,该方法允许为参数指定名称、描述和其他模式信息。
# 导入所需的模块
from langchain_core.language_models import GenericFakeChatModel  # 导入一个假的聊天模型,用于测试
from langchain_core.output_parsers import StrOutputParser  # 导入字符串输出解析器
from langchain_core.prompts import ChatPromptTemplate  # 导入聊天提示模板# 创建一个聊天提示模板,包含一个占位符 {answer_style}
prompt = ChatPromptTemplate.from_messages([("human", "Hello. Please respond in the style of {answer_style}.")]
)# 创建一个假的聊天模型实例,并提供一个固定的响应
llm = GenericFakeChatModel(messages=iter(["hello matey"]))# 构建一个链式调用:先应用提示模板,然后调用 LLM,最后解析输出为字符串
chain = prompt | llm | StrOutputParser()# 将 chain 转换为一个工具(Tool),并指定名称和描述
as_tool = chain.as_tool(name="Style responder", description="Description of when to use tool."
)# 打印工具的参数信息
print(as_tool.args) # {'answer_style': {'title': 'Answer Style', 'type': 'string'}}

三 异步工具的实现

  • LangChain的工具可以实现异步版本,以节省计算资源和提高效率。在定义异步工具时,需要使用async/await语法,并确保函数和工具名准确反映功能,提供详细的文档字符串。对于涉及外部API调用的工具,建议使用API代理服务来提高访问的稳定性,并确保异步工具充分利用并发优势,避免阻塞操作。
from langchain_core.tools import tool@tool
async def multiply(a:int,b:int)->int:"""Multiply two numbers"""return a*bprint(multiply.name) # multiply
print(multiply.description) # Multiply two numbers
print(multiply.args) # {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}

四 工具错误处理策略

  • 为了让代理能从错误中恢复并继续执行,需要特定的错误处理策略。可以抛出ToolException并定义错误处理函数,设置handle_tool_error属性来定义工具错误的应对策略,可以是字符串、布尔值或函数。需要注意的是仅引发ToolException是无效的,需要先设置该工具的handle_tool_error,因为它的默认值为False
from langchain_core.tools import StructuredTool
from langchain_core.tools import ToolExceptiondef get_weather(city: str) -> str:"""获取给定城市的天气。"""raise ToolException(f"错误:没有名为{city}的城市。")get_weather_tool = StructuredTool.from_function(func=get_weather,# 默认情况下,如果函数抛出TooLException,则将TooLException的message作为响应。# 如果设置为True,则将返回TooLException异常文本,False将会抛出TooLExceptionhandle_tool_error=True,
)response = get_weather_tool.invoke({"city":"天京"})
print(response) # 错误:没有名为天京的城市。
  • 定义异常处理
from langchain_core.tools import StructuredTool
from langchain_core.tools import ToolExceptiondef get_weather(city: str) -> str:"""获取给定城市的天气。"""raise ToolException(f"错误:没有名为{city}的城市。")get_weather_tool = StructuredTool.from_function(func=get_weather,handle_tool_error="没有找到这个城市",
)response = get_weather_tool.invoke({"city":"天京"})
print(response) # 没有找到这个城市
  • 异常个性化处理
from langchain_core.tools import StructuredTool
from langchain_core.tools import ToolExceptiondef get_weather(city: str) -> str:"""获取给定城市的天气。"""raise ToolException(f"错误:没有名为{city}的城市。")def _handle_tool_error(error: ToolException) -> str:"""处理工具错误。"""return f"工具执行期间发生以下错误:`{error.args[0]}`"get_weather_tool = StructuredTool.from_function(func=get_weather,handle_tool_error=_handle_tool_error
)response = get_weather_tool.invoke({"city":"天京"})
print(response) # 工具执行期间发生以下错误:`错误:没有名为天京的城市。`

相关文章:

LangChain【7】之工具创建和错误处理策略

文章目录 一 LangChain 自定义工具概述二创建自定义工具的三种方法2.1 方法一:tool 装饰器2.1.1 同步方法案例2.1.2 工具描述方式1:传参2.1.3 工具描述方式2:文档字符串 2.2 方法二:StructuredTool类2.2.1 StructuredTool创建自定…...

如何在电脑上轻松访问 iPhone 文件

我需要将 iPhone 下载文件夹中的文件传输到 Windows 11 电脑上。我该怎么做?我可以在 Windows 11 上访问 iPhone 下载吗? 由于 iOS 和 Windows 系统之间的差异,在 PC 上访问 iPhone 文件似乎颇具挑战性。然而,只要使用正确的工具…...

Eureka REST 相关接口

可供非 Java 应用程序使用的 Eureka REST 操作。 appID 是应用程序的名称,instanceID 是与实例关联的唯一标识符。在 AWS 云中,instanceID 是实例的实例 ID;在其他数据中心,它是实例的主机名。 对于 XML/JSON,HTTP 的…...

C语言字符数组输入输出方法大全(附带实例)

在 C语言中,字符数组是一种特殊的数组,用于存储和处理字符串。理解字符数组的输入和输出操作对于初学者来说至关重要,因为这是处理文本数据的基础。 字符数组的定义与初始化 在讨论输入输出之前,我们先来回顾一下字符数组的定义…...

短视频矩阵SaaS系统:开源部署与核心功能架构指南

一、系统架构概述 短视频矩阵系统是基于SaaS(软件即服务)模式的多平台内容管理解决方案,通过开源技术实现账号聚合、智能创作、跨平台分发及数据闭环。系统采用微服务架构,支持高并发场景下的弹性扩展。 二、核心功能模块开发逻辑…...

每日算法 -【Swift 算法】电话号码字母组合

🚀 LeetCode 字符串数字映射(Swift)——电话号码字母组合 在日常刷题或面试中,我们经常会遇到字符串 回溯组合的问题。这道经典题——电话号码的字母组合 就是典型代表。本文将带你用 Swift 实现这道题,思路清晰&…...

深入解析YUM与DNF:RPM包管理器的架构演进与功能对比

在Linux系统管理中,软件包管理器是连接用户与底层RPM(Red Hat Package Manager)包的核心工具。作为RPM生态的两大代表性工具,YUM(Yellowdog Updater Modified)与DNF(Dandified YUM)的…...

解决cocos 2dx/creator2.4在ios18下openURL无法调用的问题

由于ios18废弃了旧的openURL接口,我们需要修改CCApplication-ios.mm文件的Application::openURL方法: //修复openURL在ios18下无法调用的问题 bool Application::openURL(const std::string &url) {// NSString* msg [NSString stringWithCString:…...

精益数据分析(94/126):30/10/10用户参与法则与定价策略的科学制定

精益数据分析(九十四):30/10/10用户参与法则与定价策略的科学制定 在创业过程中,如何衡量用户参与度是否健康?又该如何制定科学的定价策略实现营收最大化?今天,我们将深入解析Union Square Ven…...

oss:上传图片到阿里云403 Forbidden

访问图片出现403Forbidden问题,我们可以直接登录oss账号,查看对应权限是否开通,是否存在跨域问题...

Windows系统中如何使用符号链接将.vscode等配置文件夹迁移到D盘(附 CMD PowerShell 双版本命令)

在日常开发和使用中,很多应用程序都会在 Windows 用户目录(如 C:\Users\你的用户名\)下创建一些以点开头的隐藏配置文件夹,例如: .vscode — Visual Studio Code 的设置和插件数据.cursor — Cursor 编辑器的缓存和设…...

4. 数据类型

4.1 数据类型分类 分类 数据类型 说明 数值类型 BIT(M) 位类型。M指定位数,默认值1,范围1 - 64 TINYINT [UNSIGNED] 带符号的范围 -128 ~ 127,无符号范围0 ~ 255,默认有符号 BOOL 使用0和1表示真和假 SMALLINT [UNSIGNED] 带符号是…...

MySQL基础(二)SQL语言、客户端工具

目录 三、SQL语言 3.1 概念 3.2 基本操作 四、客户端工具 三、SQL语言 3.1 概念 SQL(Structured Query Language)结构化查询语言。SQL用于对存储数据,更新,查询和管理关系型数据库的程序设计语言。 通常执行对数据库的增删改…...

【贪心、DP、线段树优化】Leetcode 376. 摆动序列

贪心算法:选 “关键转折点” 初始状态:把数组第一个元素当作起点,此时前一个差值符号设为平坡(即差值为0)。遍历数组:从第二个元素开始,依次计算当前元素和前一个元素的差值。差值符号判断&…...

CppCon 2015 学习:C++ in the audio industry

实时编程(real-time programming):音频处理对延迟极度敏感,要求代码必须非常高效且稳定。无锁线程同步(lock-free thread synchronization):避免阻塞,提高性能,尤其是在多…...

C++算法-动态规划2

第 4 题 字符串分割 (Word Break) 难度: Medium备注:出自 leetcode题目描述 Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words. For example, given s "l…...

软信天成:数据驱动型背后的人工智能,基于机器学习的数据管理

在数字化转型浪潮中,当代企业如同逆水行舟,不进则退。无数企业希望通过数字化转型捕获全新的市场机遇,改善财政状况,在未来市场竞争中占据一席之地。要想获得成功的数字化转型,关键因素在于具备可靠、及时的数据用以支…...

MySQL提升

事务 事务:在多个操作合在一起视为一个整体。要么就不做、要么就做完。 事务应该满足ACID A : 原子性。不可分割。C : 一致性。追求的目标,在开始到结束没有发生预定外的情况。I : 隔离性。不同的事务是独立的。D : 持久性。系统崩溃,数据依然…...

hbase资源和数据权限控制

hbase适合大数据量下点查 https://zhuanlan.zhihu.com/p/471133280 HBase支持对User、NameSpace和Table进行请求数和流量配额限制,限制频率可以按sec、min、hour、day 对于请求大小限制示例(5K/sec,10M/min等),请求大小限制单位如…...

VMWare下设置共享文件,/mnt/hgfs下却不显示共享文件的解决方法

一、共享文件夹设置步骤 打开虚拟机设置:右键点击虚拟机 → 选择 “设置” → 切换到 “选项” 标签页 → 点击 “共享文件夹”启用共享功能:选择 “总是启用”(确保虚拟机已关闭或处于运行状态)添加共享文件夹: 点击…...

go语言的锁

本篇文章主要讲锁,主要会涉及go的sync.Mutex和sync.RWMutex。 一.锁的概念和发展 1.1 锁的概念 所谓的加锁和解锁其实就是指一个数据是否被占用了,通过Mutex内的一个状态来表示。 例如,取 0 表示未加锁,1 表示已加锁&#xff…...

C++11完美转发

在 C11 之前,泛型函数在传递参数时无法保证参数的原始类型(左值或右值)导致额外的拷贝或移动操作,完美转发是一种高效传递技术,能够保持参数的原始特性,避免额外的性能开销 完美转发是指在泛型编程中以参数…...

VUE解决页面请求接口大规模并发的问题(请求队列)

方案1: 请求队列 // RequestQueue.js export default class RequestQueue {constructor(maxConcurrent) {this.maxConcurrent maxConcurrent; // 最大并发请求数this.currentConcurrent 0; // 当前并发请求数this.queue []; // 请求队列this.requestId 0; // …...

IDEA安装迁移IDEA配置数据位置

需求 因为C盘有清空风险,需要把IDEA(2025)安装位置以及配置数据都挪到D盘。 安装 到官网下载安装包 安装,这里可以改下安装位置 这几个选项随意,然后一直下一步就好 完成后重启或不重启都随意 迁移数据 初次安…...

Blazor-表单提交的艺术:如何优雅地实现 (下)

在上一章节中我们使用HTML的方式介绍了如何在Blazor框架下进行表单的提交&#xff0c;而在Blazor框架中也为我们内置了<EditForm>组件来代替原始的HTML,<form>&#xff0c;下面我们将对<EditForm>的用法进行讲解&#xff0c;并将两种表单方式进行对比&#x…...

五子棋网络对战游戏的设计与实现设计与实现【源码+文档】

五子棋网络对战游戏的设计与实现 摘 要 在现代社会中,及其它无线设备越来越多的走进普通老百姓的工作和生活。随着3G技术的普及与应用&#xff0c;基于Java开发的软件在上的使用非常的广泛&#xff0c;增值服务的内容也是越来越多&#xff0c;对丰富人们的生活内容、提供快…...

Vue基础(14)_列表过滤、列表排序

Array.prototype.filter()【ES5】 filter() 方法创建给定数组一部分的浅拷贝&#xff0c;其包含通过所提供函数实现的测试的所有元素。 语法&#xff1a; filter(callbackFn) filter(callbackFn, thisArg) 参数&#xff1a; callbackFn(回调函数)&#xff1a;为数组中的每个元…...

Spring Boot项目中JSON解析库的深度解析与应用实践

在现代Web开发中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;作为轻量级的数据交换格式&#xff0c;已成为前后端通信的核心桥梁。Spring Boot作为Java生态中最流行的微服务框架&#xff0c;提供了对多种JSON库的无缝集成支持。本文将深入探讨Spring B…...

我用Amazon Q写了一个Docker客户端,并上架了懒猫微服商店

自从接触了Amazon Q&#xff0c;我陆陆续续写了不少小软件&#xff0c;其中这个项目是一个典型的例子&#xff0c;自己平时来使用&#xff0c;也分享给一些 NAS 爱好者来用。 故事还要用上次折腾黑群晖说起&#xff0c;本意想把 NAS 和打印机共享二合一的&#xff0c;所以把闲着…...

Django CMS 的 Demo

以下是关于 Django CMS 的 Demo 示例及相关资源的整理 安装与运行 Django CMS 示例 使用 djangocms-installer 快速创建 Django CMS 项目&#xff1a; pip install django_cms djangocms -p . mysite安装记录 pip install django-cms Looking in indexes: https://pypi.tun…...