语言模型工具 API

语言模型工具使你能够通过特定领域的功能来扩展大型语言模型 (LLM) 在聊天中的功能。为了处理用户的聊天提示词,VS Code 中的 智能体 可以在对话过程中自动调用这些工具来执行专门的任务。

通过在你的 VS Code 扩展中贡献语言模型工具,你可以扩展智能体编码工作流,同时提供与编辑器的深度集成。扩展工具是 VS Code 中可用的三种工具类型之一,另外两种是 内置工具和 MCP 工具

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

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

提示

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

什么是 LLM 中的工具调用?

语言模型工具是一个可以在语言模型请求中被调用的函数。例如,你可能有一个从数据库检索信息、执行某些计算或调用在线 API 的函数。当你通过 VS Code 扩展贡献一个工具时,智能体模式(agent mode)便可以根据对话上下文来调用该工具。

LLM 实际上从不自行执行该工具,而是由 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 工具的唯一名称,用于在扩展实现代码中引用该工具。请使用 {verb}_{noun} 格式命名。参见 命名规范
    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.json 中的 name 属性中指定的工具名称。

    如果你希望该工具对你的扩展保持私有,请跳过工具注册步骤。

    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 将最终响应返回给用户,其中可能包含来自多个工具的响应。

准则与约定

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

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

    • 参数名称:应该描述参数的用途。参数名称采用 {noun}(名词)的格式。例如,destination_locationtickerfile_name

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

    • 描述该工具的功能以及何时应该和不应该使用它。例如:“此工具检索指定位置的天气。”
    • 描述每个参数的作用以及它与工具功能的关系。例如:“destination_location 参数指定要检索其天气的地点。它应该是一个有效的地点名称或坐标。”
    • 描述该工具的重要局限性或约束。例如:“此工具仅检索美国境内地点的天气数据。对于其他地区可能无法正常工作。”
  • 用户确认:为工具调用提供确认消息。对于来自扩展的工具,系统总是会显示一个通用的确认对话框,但该工具可以自定义确认消息。向用户提供足够的上下文以了解该工具正在做什么。

  • 错误处理:当发生错误时,抛出一个对 LLM 而言有意义的错误消息。可选择性地提供关于 LLM 接下来应该做什么的说明,例如使用不同的参数重试,或执行不同的操作。

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

English 한국어 中文(简体) 中文(繁體)
© . This website operates independently and is not affiliated with or endorsed by Microsoft. All brand names, logos, and trademarks are the property of their respective owners.