语言模型工具 API

语言模型工具使您能够通过特定领域的功能来扩展大型语言模型 (LLM) 的聊天能力。为了处理用户的聊天提示,VS Code 中的代理 (agents) 可以自动调用这些工具,将专门的任务作为对话的一部分来执行。

通过在您的 VS Code 扩展中贡献语言模型工具,您可以扩展代理式编码工作流,同时与编辑器实现深度集成。在 VS Code 中,扩展工具与内置工具和 MCP 工具并列为三种可用工具类型之一。

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

您还可以通过贡献 MCP 服务器,利用专用工具来扩展聊天体验。有关不同选项以及如何决定使用哪种方法的详细信息,请参阅 AI 可扩展性概述

提示

有关作为最终用户使用工具的信息,请参阅在聊天中使用工具

什么是 LLM 中的工具调用?

语言模型工具是一个函数,可以作为语言模型请求的一部分被调用。例如,您可能拥有一个从数据库检索信息、执行某些计算或调用在线 API 的函数。当您在 VS Code 扩展中贡献一个工具时,代理模式便可以根据对话的上下文来调用该工具。

LLM 本身实际上并不会执行该工具,而是生成用于调用您工具的参数。清晰地描述工具的用途、功能和输入参数非常重要,这样工具才能在正确的上下文中被调用。

下图显示了 VS Code 代理模式下的工具调用流程。有关所涉及具体步骤的详细信息,请参阅工具调用流程

Diagram that shows the Copilot tool-calling flow

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

为什么要从您的扩展中实现语言模型工具?

在您的扩展中实现语言模型工具具有以下几个好处:

  • 扩展代理模式:使用特定的领域工具,这些工具会自动作为响应用户提示的一部分被调用。例如,启用数据库构建和查询,以动态地为 LLM 提供相关上下文。
  • 与 VS Code 深度集成:利用广泛的扩展 API。例如,使用 调试 API 获取当前的调试上下文,并将其作为工具功能的一部分使用。
  • 分发和部署:通过 Visual Studio Marketplace 分发工具,为用户提供可靠且无缝的体验。用户无需为您的工具进行单独的安装和更新过程。

在以下场景中,您可以考虑使用 MCP 服务器 实现语言模型工具:

  • 您已经拥有 MCP 服务器实现,并且也希望在 VS Code 中使用它。
  • 您希望在不同的开发环境和平台之间复用同一个工具。
  • 您的工具作为服务远程托管。
  • 您不需要访问 VS Code API。

了解有关 工具类型差异 的更多信息。

创建语言模型工具

实现语言模型工具主要包含两个部分:

  1. 在扩展的 package.json 文件中定义工具配置。
  2. 使用 语言模型 API 参考 在扩展代码中实现该工具。

您可以从一个 基础示例项目 开始。

1. package.json 中的静态配置

在扩展中定义语言模型工具的第一步是在扩展的 package.json 文件中进行定义。此配置包括工具名称、描述、输入模式 (schema) 以及其他元数据。

  1. 在扩展 package.json 文件的 contributes.languageModelTools 部分中为您的工具添加条目。

  2. 为工具提供唯一的名称

    属性 描述
    name 工具的唯一名称,用于在扩展实现代码中引用该工具。名称格式应为 {动词}_{名词}。请参阅 命名指南
    displayName (显示名称) 工具的用户友好名称,用于在 UI 中显示。
  3. 如果工具可以与 代理 一起使用,或在聊天提示中通过 # 引用,请添加以下属性:

    用户可以在聊天视图中启用或禁用该工具,这与 模型上下文协议 (MCP) 工具 的操作方式类似。

    属性 描述
    canBeReferencedInPrompt (可以在提示中引用) 如果该工具可以与 代理 一起使用或在聊天中被引用,请设置为 true
    toolReferenceName (工具引用名称) 用户在聊天提示中通过 # 引用该工具时使用的名称。
    icon (图标) 在 UI 中为工具显示的图标。
    userDescription (用户描述) 工具的用户友好描述,用于在 UI 中显示。
  4. modelDescription 中添加详细描述。此信息供 LLM 使用,以确定在什么上下文中应该使用您的工具。

    • 该工具具体做什么?
    • 它返回什么类型的信息?
    • 它应该在什么时候使用,什么时候不应该使用?
    • 描述工具的重要限制或约束。
  5. 如果工具需要输入参数,请添加一个 inputSchema 属性来描述工具的输入参数。

    此 JSON 模式描述了一个包含工具输入属性的对象,以及它们是否为必填项。文件路径应为绝对路径。

    描述每个参数的功能,以及它们如何与工具的功能相关联。

  6. 添加一个 when 子句来控制工具何时可用。

    languageModelTools 贡献点允许您通过使用 when 子句 来限制工具在代理模式下何时可用,或者在提示中何时可以被引用。例如,获取调试调用栈信息的工具,应该只在用户进行调试时可用。

    "contributes": {
        "languageModelTools": [
            {
                "name": "chat-tools-sample_tabCount",
                ...
                "when": "debugState == 'running'"
            }
        ]
    }
    
工具定义示例

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

"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 in VS Code.",
            "userDescription": "Count the number of active tabs in a tab group.",
            "canBeReferencedInPrompt": true,
            "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
                    }
                }
            }
        }
    ]
}

2. 工具实现

使用 语言模型 API 实现语言模型工具。这包括以下步骤:

  1. 在扩展激活时,使用 vscode.lm.registerTool 注册该工具。

    提供您在 package.jsonname 属性中指定的工具名称。

    如果您希望该工具仅供您的扩展私有,请跳过工具注册步骤。

    export function registerChatTools(context: vscode.ExtensionContext) {
      context.subscriptions.push(
        vscode.lm.registerTool('chat-tools-sample_tabCount', new TabCountTool())
      );
    }
    
  2. 创建一个实现 vscode.LanguageModelTool<> 接口的类。

  3. prepareInvocation 方法中添加工具确认消息。

    来自扩展的工具将始终显示一个通用的确认对话框,但该工具可以自定义确认消息。请为用户提供足够的上下文,以便其理解工具正在执行的操作。消息可以是包含代码块的 MarkdownString

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

    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,
        };
    }
    

    如果 prepareInvocation 返回 undefined,将显示通用的确认消息。请注意,用户也可以选择“总是允许”某个工具。

  4. 定义一个描述工具输入参数的接口。

    该接口用于 vscode.LanguageModelTool 类的 invoke 方法中。输入参数将根据您在 package.jsoninputSchema 定义的 JSON 模式进行验证。

    以下示例展示了选项卡统计工具的接口。

    export interface ITabCountParameters {
      tabGroup?: number;
    }
    
  5. 实现 invoke 方法。当在处理聊天提示时调用语言模型工具,此方法会被调用。

    invoke 方法在 options 参数中接收工具输入参数。这些参数会根据 package.jsoninputSchema 定义的 JSON 模式进行验证。

    当发生错误时,抛出一个对 LLM 有意义的错误消息。如有必要,提供有关 LLM 下一步应该做什么的说明,例如使用不同参数重试或执行其他操作。

    以下示例展示了选项卡统计工具的实现。工具的结果是 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 扩展示例仓库中查看实现 语言模型工具 的完整源代码。

工具调用流程

当用户发送聊天提示时,会发生以下步骤:

  1. Copilot 根据用户的配置确定可用工具列表。

    工具列表由内置工具、扩展注册的工具以及来自 MCP 服务器 的工具组成。您可以通过扩展或 MCP 服务器为代理模式做出贡献(图中以绿色显示)。

  2. Copilot 将请求发送给 LLM,并为其提供提示、聊天上下文以及需要考虑的工具定义列表。

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

  3. 如果需要,Copilot 会使用 LLM 提供的参数值调用建议的工具。

    工具响应可能会导致更多的工具调用请求。

  4. 如果存在错误或后续工具请求,Copilot 将会循环执行工具调用流程,直到所有工具请求都得到解决。

  5. Copilot 将最终响应返回给用户,其中可能包括来自多个工具的响应。

指南和约定

  • 命名:为工具和参数编写清晰且具有描述性的名称。

    • 工具名称:应该是唯一的,并清楚地描述其意图。工具名称格式应为 {动词}_{名词}。例如:get_weatherget_azure_deploymentget_terminal_output

    • 参数名称:应该描述参数的用途。参数名称格式应为 {名词}。例如:destination_locationtickerfile_name

  • 描述:为工具和参数编写详细的描述。

    • 描述工具的功能以及何时应该(或不应该)使用它。例如:“此工具检索指定地点的天气。”
    • 描述每个参数的功能以及它们如何与工具的功能相关联。例如:“destination_location 参数指定了要检索天气的地点。它应该是一个有效的地点名称或坐标。”
    • 描述工具的重要限制或约束。例如:“此工具仅检索美国境内的天气数据。它可能无法在其他地区生效。”
  • 用户确认:为工具调用提供确认消息。来自扩展的工具将始终显示一个通用的确认对话框,但该工具可以自定义确认消息。请为用户提供足够的上下文,以便其理解工具正在执行的操作。

  • 错误处理:当发生错误时,抛出一个对 LLM 有意义的错误消息。如有必要,提供有关 LLM 下一步应该做什么的说明,例如使用不同参数重试或执行其他操作。

OpenAI 文档Anthropic 文档 中获取更多关于创建工具的最佳实践。

© . This site is unofficial and not affiliated with Microsoft.