在构建智能代理时,需要为其提供可使用的工具列表。工具不仅仅是某个函数的调用,它包含多个组件:
- name: 工具的唯一名称。
- description: 描述工具的功能。这些信息会被用于语言模型或代理的上下文。
- args_schema: 可选但推荐,用于提供更多的信息或验证预期的参数。
- return_direct: 仅对代理相关。如果为True,调用工具后代理会直接返回结果给用户。
LangChain支持从以下几种方式创建工具:
- 函数
- LangChain Runnables
- 通过继承BaseTool类 —— 这种方法提供了最高的灵活性,但要求更多的代码和努力。
本文将详细介绍这些方法。
使用函数创建工具
使用@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) # 输出:multiply
print(multiply.description) # 输出:Multiply two numbers.
print(multiply.args) # 输出参数描述
异步实现
可以创建异步实现的工具,如下:
from langchain_core.tools import tool
@tool
async def amultiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
高级用法
可以解析注解、嵌套模式和其他特性:
from typing import Annotated, List
from langchain_core.tools import tool
@tool
def multiply_by_max(
a: Annotated[str, "scale factor"],
b: Annotated[List[int], "list of ints over which to take maximum"],
) -> int:
"""Multiply a by the maximum of b."""
return a * max(b)
multiply_by_max.args_schema.schema()
从LangChain Runnables创建工具
可以将LangChain Runnables转换为工具,示例如下:
from langchain_core.language_models import GenericFakeChatModel
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages(
[("human", "Hello. Please respond in the style of {answer_style}.")]
)
# Placeholder LLM
llm = GenericFakeChatModel(messages=iter(["hello matey"]))
chain = prompt | llm | StrOutputParser()
as_tool = chain.as_tool(
name="Style responder", description="Description of when to use tool."
)
print(as_tool.args)
通过继承BaseTool创建工具
通过继承BaseTool类,可以定义自定义工具,示例如下:
from typing import Optional, Type
from langchain.pydantic_v1 import BaseModel
from langchain_core.callbacks import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain_core.tools import BaseTool
class CalculatorInput(BaseModel):
a: int = Field(description="first number")
b: int = Field(description="second number")
class CustomCalculatorTool(BaseTool):
name = "Calculator"
description = "useful for when you need to answer questions about math"
args_schema: Type[BaseModel] = CalculatorInput
return_direct: bool = True
def _run(
self, a: int, b: int, run_manager: Optional[CallbackManagerForToolRun] = None
) -> str:
"""Use the tool."""
return a * b
async def _arun(
self,
a: int,
b: int,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
return self._run(a, b, run_manager=run_manager.get_sync())
multiply = CustomCalculatorTool()
print(multiply.name)
print(multiply.description)
print(multiply.args)
print(multiply.return_direct)
print(multiply.invoke({"a": 2, "b": 3}))
错误处理
在使用工具与代理时,可能需要处理错误。最简单的策略是在工具内部抛出ToolException
并指定错误处理程序handle_tool_error
。
示例代码如下:
from langchain_core.tools import ToolException
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,
)
print(get_weather_tool.invoke({"city": "foobar"}))
通过以上方法,您可以创建多种类型的自定义工具并集成到智能代理中,大大增强了智能系统的功能。
如果遇到问题欢迎在评论区交流。
—END—