工具调用

工具调用(也称为函数调用)是一种结构化方式, LLM 能够向调用它的应用发回请求。您 定义要提供给模型的工具,然后模型 必要时向您的应用发出工具请求,以完成您提供的提示。

工具调用的用例通常分为以下几个主题:

让 LLM 能够访问未经训练的信息

  • 经常变化的信息,如餐馆的每日菜单或 商店的商品目录状态
  • 您的应用网域特有的信息,例如产品信息。

请注意与检索增强生成 (RAG) 的重叠部分,RAG 也 一种让 LLM 将事实信息整合到其世代中的方法。RAG 是 最适合您的工作负载 或与提示最相关的信息模糊不清。已开启 另一方面,如果检索 LLM 所需的信息是一个简单的函数, 调用或数据库查询,工具调用更合适。

在 LLM 工作流中引入一定程度的确定性

  • 执行 LLM 无法可靠地自行完成的计算。
  • 强制 LLM 在特定情况下生成逐字文本,例如 。

在 LLM 发起某项操作后

  • 使用 LLM 赋能的家居助理来开灯和关灯
  • 在由 LLM 提供支持的餐厅代理中预订桌位

准备工作

如果您要运行此页面上的代码示例,请先完成 使用入门指南。所有示例都假定您 已经设置了安装了 Genkit 依赖项的项目。

本页面介绍了 Genkit 模型抽象的一个高级功能, generate() 函数,因此在深入了解之前,您应该先熟悉 使用 AI 模型生成内容页面上的内容。您应该 也熟悉 Genkit 系统,用于定义输入和输出架构, 有关详情,请参阅页面。

工具调用概览

概括来讲,这是工具调用与 LLM 之间的典型交互。 如下所示:

  1. 发起调用的应用向 LLM 发出一个请求提示,并且还会向 LLM 发出一个请求, 列出 LLM 可用于生成回答的工具列表。
  2. LLM 生成完整回答或生成工具调用 特定格式的请求
  3. 如果调用方收到完整的响应,则请求已实现,且 互动结束;但是,如果调用方收到工具调用,它会执行 然后向 LLM 发送包含以下内容的新请求: 生成提示, 工具调用。
  4. LLM 会按照第 2 步中的说明处理新提示。

要实现此功能,需要满足以下几项要求:

  • 模型必须经过训练,才能在需要时发出工具请求,以完成 提示。通过 Web API 提供的大多数大型模型,例如 Gemini 和 Claude 可以做到这一点,但规模更小、更专业的模型通常无法做到。 如果您尝试为无法提供工具的模型提供工具,Genkit 会报错 提供支持。
  • 调用应用必须在 所需的格式
  • 调用应用必须提示模型生成工具调用 请求采用应用预期的格式。

使用 Genkit 进行工具调用

Genkit 会提供一个接口,以便使用支持它的模型调用工具。 每个模型插件都会确保满足上述条件中的后两个条件, generate() 函数会自动执行工具调用循环 。

模型支持

对工具调用的支持取决于模型、模型 API 和 Genkit 插件。 请查阅相关文档,确定是否可能会 支持。此外:

  • 如果您尝试为无法提供工具的模型提供工具,Genkit 会报错 提供支持。
  • 如果插件导出模型引用,info.supports.tools 属性 会指明它是否支持工具调用。

定义工具

使用 defineTool() 函数编写工具定义:

const specialToolInputSchema = z.object({ meal: z.enum(["breakfast", "lunch", "dinner"]) });
const specialTool = defineTool(
  {
    name: "specialTool",
    description: "Retrieves today's special for the given meal",
    inputSchema: specialToolInputSchema,
    outputSchema: z.string(),
  },
  async ({ meal }): Promise<string> => {
    // Retrieve up-to-date information and return it. Here, we just return a
    // fixed value.
    return "Baked beans on toast";
  }
);

此处的语法与 defineFlow() 语法类似;然而, namedescriptioninputSchemaoutputSchema 参数 必填字段。 在撰写工具定义时,请特别注意措辞和 这些参数的描述性,因为它们对于 LLM 而言至关重要 从而有效利用提供的工具

在提示中加入工具

定义完工具后,请在 generate():

const llmResponse = await generate({
  model: gemini15Flash,
  prompt,
  tools: [specialTool],
});

您可以提供多种工具:LLM 会根据需要调用工具 以完成提示。

显式处理工具调用

默认情况下,Genkit 会反复调用 LLM,直到完成每个工具调用 已解决。如果您希望更好地控制此工具调用循环,例如 应用更复杂的逻辑,请将 returnToolRequests 参数设置为 true。 现在,您有责任确保所有工具请求都得到满足:

let generateOptions: GenerateOptions = {
  model: gemini15Flash,
  prompt,
  tools: [specialTool],
  returnToolRequests: true,
};
let llmResponse;
while (true) {
  llmResponse = await generate(generateOptions);
  const toolRequests = llmResponse.toolRequests();
  if (toolRequests.length < 1) {
    break;
  }
  const toolResponses: ToolResponsePart[] = await Promise.all(
    toolRequests.map(async (part) => {
      switch (part.toolRequest.name) {
        case "specialTool":
          return {
            toolResponse: {
              name: part.toolRequest.name,
              ref: part.toolRequest.ref,
              output: await specialTool(specialToolInputSchema.parse(part.toolRequest?.input)),
            },
          };
        default:
          throw Error('Tool not found');
        }
      }));
    generateOptions.history = llmResponse.toHistory();
    generateOptions.prompt = toolResponses;
}