如何创建自定义工具

在构建代理时,你需要提供一组工具(Tools)供其使用。工具不仅仅是一个函数,它包括多个组件,如下所述:

AttributeTypeDescription
namestr必须在提供给一个LLM或代理的一组工具中唯一。
descriptionstr描述工具的功能。用于LLM或代理的上下文。
args_schemaPydantic BaseModel可选但推荐,可以用来提供更多信息(如少样例)或验证预期参数。
return_directboolean仅对代理相关。如果为True,调用给定的工具后,代理将停止并直接将结果返回给用户。

LangChain 支持从以下几种方式创建工具:

  1. Functions;
  2. LangChainRunnables;
  3. 通过继承 BaseTool – 这种方法最灵活,提供最大的控制权,但需要更多的努力和代码。

对于大多数使用场景,使用函数创建工具就足够了,可以通过简单的 @tool 装饰器实现。如果需要更多配置,例如同步和异步实现,可以使用 StructuredTool.from_function 方法。

创建工具的不同方法

从函数创建工具
@tool 装饰器

@tool 装饰器是定义自定义工具的最简单方式。装饰器默认使用函数名作为工具名,但可以通过传递字符串作为第一个参数来覆盖此默认行为。此外,装饰器将使用函数的文档字符串作为工具的描述,因此必须提供文档字符串。

from langchain_core.tools import tool

@tool
def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

# 检查工具的属性
print(multiply.name)
print(multiply.description)
print(multiply.args)

异步实现:

from langchain_core.tools import tool

@tool
async def amultiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b
使用结构化工具 (StructuredTool)

StructuredTool.from_function 方法提供了比 @tool 装饰器稍微多一点的可配置性,而无需额外的代码。

from langchain_core.tools import StructuredTool
from pydantic import BaseModel, Field

class CalculatorInput(BaseModel):
    a: int = Field(description="first number")
    b: int = Field(description="second number")

def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

calculator = StructuredTool.from_function(
    func=multiply,
    name="Calculator",
    description="multiply numbers",
    args_schema=CalculatorInput,
    return_direct=True,
)

print(calculator.invoke({"a": 2, "b": 3}))
print(calculator.name)
print(calculator.description)
print(calculator.args)

创建异步工具

LangChain 工具实现了 Runnable 接口。所有的 Runnable 都暴露了 invokeainvoke 方法(以及其他方法如 batch, abatch, astream 等)。

如果你只提供了同步实现的工具,仍然可以使用 ainvoke 接口,但需要注意以下几点:

  • LangChain 默认提供一个假定函数计算开销较大的异步实现,因此会将执行委托给另一个线程。
  • 如果你在异步代码库中工作,应创建异步工具,以避免因线程带来的小开销。
  • 同时需要同步和异步实现时,使用StructuredTool.from_function 或继承 BaseTool
from langchain_core.tools import StructuredTool

def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

async def amultiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

calculator = StructuredTool.from_function(func=multiply, coroutine=amultiply)

print(calculator.invoke({"a": 2, "b": 3}))
print(await calculator.ainvoke({"a": 2, "b": 5}))

错误处理

如果你要使用工具与代理交互,可能需要一个错误处理策略,以便代理能够从错误中恢复并继续执行。一个简单的策略是从工具内部抛出 ToolException 并使用 handle_tool_error 指定错误处理程序。

from langchain_core.tools import ToolException, StructuredTool

def get_weather(city: str) -> int:
    """Get weather for the given city."""
    raise ToolException(f"Error: There is no city by the name of {city}.")

get_weather_tool = StructuredTool.from_function(
    func=get_weather,
    handle_tool_error=True,
)

get_weather_tool.invoke({"city": "foobar"})

实践建议

  1. 命名和描述:选择适当的名称和描述,提高模型的性能。
  2. 文档字符串:提供详细的文档字符串,用于自动生成的工具描述。
  3. 错误处理:确保对工具中的潜在错误进行处理,以使代理能够继续正常运行。

通过这些方法,你可以创建功能齐全且健壮的定制工具,并在你的应用程序中高效地利用LangChain工具的力量。

如果遇到问题欢迎在评论区交流。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值