现已发布!阅读关于 11 月的新功能和修复的详细信息。

LanguageModelTool API

在本扩展指南中,你将学习如何创建语言模型工具以及如何在聊天扩展中实现工具调用。

LLM 中的工具调用是什么?

工具调用使你能够通过将大型语言模型 (LLM) 连接到外部工具和系统来扩展其功能,以执行超出文本处理范围的任务。

语言模型工具是一个函数,可以作为语言模型请求的一部分调用。例如,你可能有一个从数据库检索信息、查找文件或执行某些计算的函数。你可以在扩展中实现语言模型工具,或者使用来自其他扩展的公共工具。

LLM 实际上从不执行工具本身,而是 LLM 生成可用于调用你的工具的参数,你的代码可以选择如何通过调用指定的函数来处理这些参数。你的扩展始终完全控制工具调用过程。

阅读 OpenAI 文档中有关函数调用的更多信息。

为什么要使用工具调用?

在聊天扩展中,你可能需要在多种情况下使用工具调用。一些示例包括

  • 让 LLM 动态请求更多上下文。例如,你可以使用工具从数据库检索信息,或查找相关文件。
  • 让 LLM 动态执行某些操作。LLM 本身无法执行计算或调用其他系统。例如,使用工具运行终端命令并将输出返回给 LLM。
  • 连接其他 VS Code 扩展贡献的一些上下文/行为。例如,你可能有一个使用 Git 扩展来检索有关当前存储库信息的工具。

工具调用流程

聊天扩展中的工具调用流程如下

  1. 检索相关工具列表

  2. 将请求发送到 LLM,提供要考虑的工具定义列表

  3. LLM 生成响应,其中可能包括一个或多个调用工具的请求

  4. 使用 LLM 响应中提供的参数值调用工具

  5. 将另一个请求发送到 LLM,包括工具结果

  6. LLM 生成最终用户响应,其中可能包含工具响应

    如果 LLM 响应包含更多工具调用请求,请重复步骤 4-6,直到没有更多工具请求。

使用聊天扩展库实现工具调用

你可以使用 @vscode/chat-extension-utils来简化在聊天扩展中调用工具的过程。

在你的聊天参与者vscode.ChatRequestHandler 函数中实现工具调用。

  1. 确定当前聊天上下文的相关工具。你可以使用 vscode.lm.tools 访问所有可用工具。

    以下代码片段显示了如何将工具筛选为仅包含特定标签的工具。

    const tools =
      request.command === 'all'
        ? vscode.lm.tools
        : vscode.lm.tools.filter(tool => tool.tags.includes('chat-tools-sample'));
    
  2. 使用 sendChatParticipantRequest 将请求和工具定义发送到 LLM。

    const libResult = chatUtils.sendChatParticipantRequest(
      request,
      chatContext,
      {
        prompt: 'You are a cat! Answer as a cat.',
        responseStreamOptions: {
          stream,
          references: true,
          responseText: true
        },
        tools
      },
      token
    );
    

    ChatHandlerOptions 对象具有以下属性

    • prompt:(可选) 聊天参与者提示的说明。
    • model:(可选) 用于请求的模型。如果未指定,则使用聊天上下文中的模型。
    • tools:(可选) 要考虑用于请求的工具列表。
    • requestJustification:(可选) 描述发起请求原因的字符串。
    • responseStreamOptions:(可选) 启用 sendChatParticipantRequest 将响应流回 VS Code。可选地,你还可以启用引用和/或响应文本。
  3. 返回来自 LLM 的结果。这可能包含错误详细信息或工具调用元数据。

    return await libResult.result;
    

工具调用示例的完整源代码可在 VS Code 扩展示例存储库中找到。

自己实现工具调用

对于更高级的场景,你也可以自己实现工具调用。可选地,你可以使用 @vscode/prompt-tsx 库来制作 LLM 提示。通过自己实现工具调用,你可以更好地控制工具调用过程。例如,在将工具响应发送到 LLM 之前执行其他验证或以特定方式处理工具响应。

在 VS Code 扩展示例存储库中查看使用 prompt-tsx 实现工具调用的完整源代码。

创建语言模型工具

调用工具时,你可以调用其他扩展贡献的公共语言模型工具,也可以创建自己的工具。当你创建工具时,你可以选择将其注册到 VS Code API,或者仅在你的扩展中将其用作私有工具。

当你使用 VS Code API 发布工具时,所有扩展都可以使用该工具。

决定注册工具还是将其用作私有工具

如果工具对其他扩展有意义,并且可以在不针对特定工具进行特殊处理的情况下使用,则使用 VS Code API 注册工具

  • 该工具对其他扩展有意义,并且可以在不针对特定工具进行特殊处理的情况下使用
  • 扩展需要提供进度消息和确认

如果出现以下情况,请使用私有工具

  • 该工具无法公开,例如因为它特定于你的公司或检索非公开数据
  • 该工具需要一些特殊处理,并且特定于你的扩展

实现语言模型工具

要实现语言模型工具

  1. package.json 中的 contributes 属性中定义该工具

    以下示例显示了如何定义一个计算选项卡组中活动选项卡数量的工具。

    "contributes": {
        "languageModelTools": [
            {
                "name": "chat-tools-sample_tabCount",
                "tags": [
                    "editors",
                    "chat-tools-sample"
                ],
                "toolReferenceName": "tabCount",
                "displayName": "Tab Count",
                "modelDescription": "The number of active tabs in a tab group",
                "icon": "$(files)",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "tabGroup": {
                            "type": "number",
                            "description": "The index of the tab group to check. This is optional- if not specified, the active tab group will be checked.",
                            "default": 0
                        }
                    }
                }
            }
        ]
    }
    

    语言模型工具具有以下属性

    • name:工具的唯一名称。这用于在扩展实现代码中引用该工具。
    • tags:描述工具的标签数组。这用于筛选与特定请求相关的工具列表。
    • toolReferenceName:如果启用,用户可以通过 # 在聊天提示中引用该工具的名称。
    • displayName:工具的用户友好名称,用于在 UI 中显示。
    • modelDescription:工具的描述,语言模型可以使用它来选择它。
    • icon:要在 UI 中为工具显示的图标。
    • inputSchema:描述工具输入参数的 JSON 架构。语言模型使用它为工具调用提供参数值。
  2. (可选) 使用 vscode.lm.registerTool 注册工具

    如果你想发布该工具以供其他扩展使用,你必须使用 vscode.lm.registerTool API 注册该工具。提供你在 package.json 文件中指定的工具名称。

    export function registerChatTools(context: vscode.ExtensionContext) {
      context.subscriptions.push(
        vscode.lm.registerTool('chat-tools-sample_tabCount', new TabCountTool())
      );
    }
    
  3. 通过实现 vscode.LanguageModelTool<> 接口来实现语言模型工具。

    • 实现 prepareInvocation 以提供工具调用的确认消息。

      以下示例显示了如何为选项卡计数工具提供确认消息。

      async prepareInvocation(
          options: vscode.LanguageModelToolInvocationPrepareOptions<ITabCountParameters>,
          _token: vscode.CancellationToken
      ) {
          const confirmationMessages = {
              title: 'Count the number of open tabs',
              message: new vscode.MarkdownString(
                  `Count the number of open tabs?` +
                  (options.input.tabGroup !== undefined
                      ? ` in tab group ${options.input.tabGroup}`
                      : '')
              ),
          };
      
          return {
              invocationMessage: 'Counting the number of tabs',
              confirmationMessages,
          };
      }
      
    • 定义一个描述工具输入参数的接口。此接口在 invoke 方法中使用。

      以下示例显示了选项卡计数工具的接口。

      export interface ITabCountParameters {
        tabGroup?: number;
      }
      
    • 实现 invoke,该方法在调用工具时被调用。它在 options 参数中接收工具输入参数。

      以下示例显示了选项卡计数工具的实现。工具的结果是 vscode.LanguageModelToolResult 类型的实例。

      async invoke(
          options: vscode.LanguageModelToolInvocationOptions<ITabCountParameters>,
          _token: vscode.CancellationToken
      ) {
          const params = options.input;
          if (typeof params.tabGroup === 'number') {
              const group = vscode.window.tabGroups.all[Math.max(params.tabGroup - 1, 0)];
              const nth =
                  params.tabGroup === 1
                      ? '1st'
                      : params.tabGroup === 2
                          ? '2nd'
                          : params.tabGroup === 3
                              ? '3rd'
                              : `${params.tabGroup}th`;
              return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(`There are ${group.tabs.length} tabs open in the ${nth} tab group.`)]);
          } else {
              const group = vscode.window.tabGroups.activeTabGroup;
              return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(`There are ${group.tabs.length} tabs open.`)]);
          }
      }
      

在 VS Code 扩展示例存储库中查看实现语言模型工具的完整源代码。

开始使用