参加你附近的 ,了解 VS Code 中的 AI 辅助开发。

语言模型工具 API

语言模型工具使您能够通过特定领域的功能扩展大型语言模型 (LLM) 在聊天中的功能。为了处理用户的聊天提示,VS Code 中的代理模式可以自动调用这些工具,作为对话的一部分执行专门任务。通过在 VS Code 扩展中贡献语言模型工具,您可以扩展代理编码工作流,同时还提供与编辑器的深度集成。

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

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

LLM 中的工具调用是什么?

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

LLM 实际上从不执行工具本身,而是生成用于调用您的工具的参数。清楚地描述工具的用途、功能和输入参数非常重要,以便可以在正确的上下文中调用该工具。

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

Diagram that shows the Copilot tool-calling flow

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

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

在扩展中实现语言模型工具具有以下几个优点:

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

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

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

创建语言模型工具

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

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

您可以从基本示例项目开始。

1. package.json 中的静态配置

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

  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 文档中获取更多创建工具的最佳实践。