工具调用
概述
许多人工智能应用直接与人类交互。在这些情况下,模型以自然语言响应是合适的。但是,如果我们希望模型也与系统直接交互,例如数据库或 API,该怎么办?这些系统通常具有特定的输入模式;例如,API 通常具有必需的有效负载结构。这种需求促生了工具调用的概念。您可以使用工具调用来请求与特定模式匹配的模型响应。
您有时会听到术语 function calling
(函数调用)。我们交替使用该术语和 tool calling
(工具调用)。
关键概念
(1) 工具创建: 使用 tool 函数创建一个工具。工具是函数及其模式之间的关联。(2) 工具绑定: 工具需要连接到支持工具调用的模型。这使模型了解工具以及工具所需的关联输入模式。(3) 工具调用: 在适当的时候,模型可以决定调用工具并确保其响应符合工具的输入模式。(4) 工具执行: 可以使用模型提供的参数执行工具。
推荐用法
此伪代码说明了使用工具调用的推荐工作流程。创建的工具作为列表传递给 .bindTools()
方法。可以像往常一样调用此模型。如果进行工具调用,则模型的响应将包含工具调用参数。工具调用参数可以直接传递给工具。
// Tool creation
const tools = [myTool];
// Tool binding
const modelWithTools = model.bindTools(tools);
// Tool calling
const response = await modelWithTools.invoke(userInput);
工具创建
创建工具的推荐方法是使用 tool
函数。
import { tool } from "@langchain/core/tools";
const multiply = tool(
({ a, b }: { a: number; b: number }): number => {
/**
* Multiply a and b.
*/
return a * b;
},
{
name: "multiply",
description: "Multiply two numbers",
schema: z.object({
a: z.number(),
b: z.number(),
}),
}
);
对于不需要执行函数的工具调用,您也可以仅定义工具模式
const multiplyTool = {
name: "multiply",
description: "Multiply two numbers",
schema: z.object({
a: z.number(),
b: z.number(),
}),
};
工具绑定
请参阅我们的模型集成页面,以获取支持工具调用的提供商列表。
要理解的核心概念是 LangChain 提供了一个标准化的接口,用于将工具连接到模型。 .bindTools()
方法可用于指定模型可以调用的工具。
const modelWithTools = model.bindTools([toolsList]);
作为一个具体示例,让我们以函数 multiply
为例,并将其作为工具绑定到支持工具调用的模型。
const multiply = tool(
({ a, b }: { a: number; b: number }): number => {
/**
* Multiply a and b.
*
* @param a - first number
* @param b - second number
* @returns The product of a and b
*/
return a * b;
},
{
name: "multiply",
description: "Multiply two numbers",
schema: z.object({
a: z.number(),
b: z.number(),
}),
}
);
const llmWithTools = toolCallingModel.bindTools([multiply]);
工具调用
工具调用的一个关键原则是,模型根据输入的关联性决定何时使用工具。模型并不总是需要调用工具。例如,给定一个不相关的输入,模型将不会调用该工具
const result = await llmWithTools.invoke("Hello world!");
结果将是一个 AIMessage
,其中包含模型以自然语言进行的响应(例如,“Hello!”)。但是,如果我们传递与工具相关的输入,则模型应选择调用它
const result = await llmWithTools.invoke("What is 2 multiplied by 3?");
和以前一样,输出 result
将是一个 AIMessage
。但是,如果调用了工具,则 result
将具有 tool_calls
属性。此属性包括执行工具所需的一切,包括工具名称和输入参数
result.tool_calls
{'name': 'multiply', 'args': {'a': 2, 'b': 3}, 'id': 'xxx', 'type': 'tool_call'}
有关更多使用详情,请参阅我们的操作指南!
工具执行
工具实现了Runnable 接口,这意味着它们可以直接被调用(例如,tool.invoke(args)
)。
LangGraph 提供了预构建组件(例如,ToolNode
),这些组件通常会代表用户调用工具。
- 请参阅我们的工具调用操作指南。
- 请参阅 LangGraph 文档,了解如何使用 ToolNode。
最佳实践
在设计供模型使用的工具时,请务必记住:
- 具有显式工具调用 API 的模型在工具调用方面比非微调模型更好。
- 如果工具具有精心选择的名称和描述,则模型将表现更好。
- 与复杂工具相比,简单、范围狭窄的工具更易于模型使用。
- 要求模型从大量工具列表中进行选择对模型提出了挑战。