0 关于Tools

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

即大模型本质上相当于一个大脑,单纯靠大脑是做不成事的,还需要“手臂”等“身体器官”组合才能完成一个现实中的人物,单纯的大模型我们称为LLM,而加上工具调用后即可称为Agent

1 Tools的组成

Tool由几个常用属性组成:

属性 类型 描述
name str 必选,工具名,在提供给LLM或Agent的工具集中必须是唯一的
description str 可选,描述工具的功能。LLM或Agent将使用此描述作 为上下文,使用它确定工具的使用
args_schema Pydantic BaseModel 可选,用于描述参数的类型以及作用描述
return_direct boolean 仅对Agent相关。当为True时,在调用给定工具后,Agent将 停止并将结果直接返回给用户。

2 自定义Tools方式

一共有两种,一个是使用**@Tool装饰器的方式,另一个是使用构造器类方法StructuredTool.from_function**的方式。

2.1 使用@Tool装饰器的方式

装饰器默认使用函数名称作为工具名称,但可以通过参数name_or_callable来覆盖此设置。 同时,装饰器将使用函数的文档字符串作为工具的描述 ,因此函数必须提供文档字符串。

2.1.1 示例代码1

示例使用装饰器方式构造了一个两数之和的工具,本质是一个函数,其中函数的文档字符串会作为工具的描述

from langchain.tools import tool

@tool
def add_two_numbers(number1:int, number2:int)->int:
    """两个整数相加"""
    return number1 + number2

print(f"name={add_two_numbers.name}")
print(f"args={add_two_numbers.args}")
print(f"description={add_two_numbers.description}")
print(f"return_direct={add_two_numbers.return_direct}")

result = add_two_numbers.invoke(({"number1": 1, "number2": 2}))
print(f"result={result}")


2.1.2 运行效果1

输出构造出的工具的各个属性以及工具被运行正确输出两数之和
请添加图片描述

2.1.3 示例代码2

以下示例代码是在原来的装饰器方式的基础上修改其参数(工具名、描述、参数模板等)

from langchain.tools import tool
from pydantic import BaseModel, Field


class FieldInfo(BaseModel):
    number1: int = Field(description="第一个参数")
    number2: int = Field(description="第二个参数")

@tool(name_or_callable="add_two_numbers", description="计算两数之和", args_schema=FieldInfo)
def add_two_numbers(number1:int, number2:int)->int:
    return number1 + number2

print(f"name={add_two_numbers.name}")
print(f"args={add_two_numbers.args}")
print(f"description={add_two_numbers.description}")
print(f"return_direct={add_two_numbers.return_direct}")

result = add_two_numbers.invoke(({"number1": 1, "number2": 2}))
print(f"result={result}")


2.1.4 运行效果2

根据修改的参数输出工具各个属性
请添加图片描述

2.2 使用StructuredTool的from_function()

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

2.2.1 示例代码
from langchain_core.tools import StructuredTool
from pydantic import BaseModel, Field


class FieldInfo(BaseModel):
    number1: int = Field(description="第一个参数")
    number2: int = Field(description="第二个参数")

def add_two_numbers(number1, number2):
    return number1 + number2

addTool = StructuredTool.from_function(
    func=add_two_numbers,
    name="add_two_numbers",
    description="add two numbers",
    args_schema=FieldInfo
)

print(f"name={addTool.name}")
print(f"args={addTool.args}")
print(f"description={addTool.description}")
print(f"return_direct={addTool.return_direct}")

result = addTool.invoke(({"number1": 1, "number2": 2}))
print(f"result={result}")


2.2.2 运行效果

运行效果和上面的@tool方式的效果一致就不截图了

3 实现大模型调用工具

3.1 大模型判断是否要调用工具及输出格式

普通模型调用,即不没有在大模型上加入functions或者大模型判断没有可以调用的工具时输出格式如下,即不出现function_call 字段

# 模型调用
response = chat_model.invoke(
    input=[HumanMessage(content="1加6等于多少呀")],
    # functions=functions
)

运行效果如下:
请添加图片描述

如果大模型选择调用工具则输出格式如下,此时content为空,出现function_call字段,里面包含工具名以及参数
请添加图片描述

3.2 大模型调用工具

上述已经得到大模型调用工具时的输出,此时只需要在大模型需要调用工具时调用对应的工具,将大模型判断得到的参数填入该工具函数中即可,完整代码示例如下,该示例提问大模型一个两数相加问题,大模型会自主调用两数相加工具。

import json
from langchain.tools import tool
from langchain_core.messages import HumanMessage
from langchain_core.utils.function_calling import convert_to_openai_function
from pydantic import BaseModel, Field
import os
import dotenv
from langchain_openai import ChatOpenAI

dotenv.load_dotenv()

os.environ["OPENAI_BASE_URL"] = os.getenv("QWEN_BASE_URL")
os.environ["OPENAI_API_KEY"] = os.getenv("QWEN_API_KEY")

# 获取对话模型
chat_model = ChatOpenAI(
    model="qwen-plus"
)

# 参数模板
class FieldInfo(BaseModel):
    number1: int = Field(description="第一个参数")
    number2: int = Field(description="第二个参数")

# 工具定义
@tool(name_or_callable="add_two_numbers", description="计算两数之和", args_schema=FieldInfo)
def add_two_numbers(number1:int, number2:int)->int:
    return number1 + number2

# 加入工具列表
tools = [add_two_numbers]

# 工具转openai函数
functions = [convert_to_openai_function(t) for t in tools]

# 模型调用
response = chat_model.invoke(
    input=[HumanMessage(content="1加6等于多少呀")],
    functions=functions
)

print(response)

if "function_call" in response.additional_kwargs:
    tool_name = response.additional_kwargs["function_call"]["name"]
    tool_args = json.loads(response.additional_kwargs["function_call"]["arguments"])
    if tool_name == "add_two_numbers":
        result = add_two_numbers.invoke(tool_args)
        print("工具执行结果", result)
else:
    print("模型回复", response.content)



运行效果:
大模型进行工具调用最后执行工具对提问的两数之和进行了计算得到正确答案
请添加图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐