– 代理会话日,2月19日

语言模型 API

语言模型 API 使您能够 使用语言模型并将 AI 驱动的功能和自然语言处理集成到您的 Visual Studio Code 扩展中。

您可以在不同类型的扩展中使用语言模型 API。此 API 的典型用途是在 聊天扩展中,您可以使用语言模型来解释用户的请求并帮助提供答案。但是,语言模型 API 的使用不限于此场景。您可能在 语言调试器扩展中使用语言模型,或者将其作为自定义扩展中的 命令任务的一部分。例如,Rust 扩展可以使用语言模型提供默认名称以改进其重命名体验。

使用语言模型 API 的过程包括以下步骤

  1. 构建语言模型提示
  2. 发送语言模型请求
  3. 解释响应

以下部分将提供有关如何在您的扩展中实现这些步骤的更多详细信息。

要开始使用,您可以探索 聊天扩展示例

构建语言模型提示

要与语言模型交互,扩展首先应构建其提示,然后将请求发送到语言模型。您可以使用提示向语言模型提供有关您使用该模型的广泛任务的说明。提示还可以定义用户消息的解释上下文。

语言模型 API 在构建语言模型提示时支持两种类型的消息

  • 用户 - 用于提供指令和用户的请求
  • 助手 - 用于将先前语言模型响应的历史记录作为上下文添加到提示中

注意:目前,语言模型 API 不支持使用系统消息。

您可以使用两种方法来构建语言模型提示

  • LanguageModelChatMessage - 通过提供一个或多个字符串消息来创建提示。如果您刚开始使用语言模型 API,可以使用这种方法。
  • @vscode/prompt-tsx - 使用 TSX 语法声明提示。

如果您希望更精细地控制语言模型提示的组成方式,可以使用 prompt-tsx 库。例如,该库可以帮助动态调整提示的长度以适应每个语言模型的上下文窗口大小。了解更多关于 @vscode/prompt-tsx的信息或探索 聊天扩展示例以开始使用。

要了解更多关于提示工程的概念,我们建议阅读 OpenAI 的优秀 提示工程指南

提示:充分利用丰富的 VS Code 扩展 API 来获取最相关的上下文并将其包含在您的提示中。例如,包含编辑器中活动文件的内容。

使用 LanguageModelChatMessage

语言模型 API 提供了 LanguageModelChatMessage 类来表示和创建聊天消息。您可以使用 LanguageModelChatMessage.UserLanguageModelChatMessage.Assistant 方法分别创建用户或助手消息。

在以下示例中,第一条消息为提示提供上下文

  • 模型在其回复中使用的角色(在本例中为猫)
  • 模型在生成响应时应遵循的规则(在本例中,使用猫隐喻以有趣的方式解释计算机科学概念)

然后,第二条消息提供来自用户的特定请求或指令。它确定在第一条消息提供的上下文中要完成的特定任务。

const craftedPrompt = [
  vscode.LanguageModelChatMessage.User(
    'You are a cat! Think carefully and step by step like a cat would. Your job is to explain computer science concepts in the funny manner of a cat, using cat metaphors. Always start your response by stating what concept you are explaining. Always include code samples.'
  ),
  vscode.LanguageModelChatMessage.User('I want to understand recursion')
];

发送语言模型请求

构建了语言模型的提示后,您首先使用 selectChatModels 方法选择要使用的语言模型。此方法返回匹配指定标准的语言模型数组。如果您正在实现聊天参与者,我们建议您使用作为聊天请求处理程序中的 request 对象的一部分传递的模型。这样可以确保您的扩展尊重用户在聊天模型下拉列表中选择的模型。然后,您使用 sendRequest 方法将请求发送到语言模型。

要选择语言模型,您可以指定以下属性:vendoridfamilyversion。使用这些属性可以广泛匹配给定供应商或系列的所有模型,或者通过其 ID 选择一个特定模型。在 API 参考中了解有关这些属性的更多信息。

注意:目前,gpt-4ogpt-4o-minio1o1-miniclaude-3.5-sonnet 受到语言模型系列的支持。如果您不确定使用哪个模型,我们建议使用 gpt-4o,因为它具有性能和质量。对于直接在编辑器中进行的交互,我们建议使用 gpt-4o-mini,因为它具有性能。

如果没有任何模型匹配指定的标准,则 selectChatModels 方法将返回一个空数组。您的扩展必须适当地处理这种情况。

以下示例显示了如何选择所有 Copilot 模型,无论其系列或版本如何

const models = await vscode.lm.selectChatModels({
  vendor: 'copilot'
});

// No models available
if (models.length === 0) {
  // TODO: handle the case when no models are available
}

重要提示:Copilot 的语言模型在使用它们之前需要用户的同意。同意以身份验证对话框的形式实现。因此,应将 selectChatModels 作为用户发起的动作(例如命令)的一部分进行调用。

选择模型后,您可以通过在模型实例上调用 sendRequest 方法来向语言模型发送请求。您传递之前构建的 提示,以及任何其他选项和取消令牌。

当您向语言模型 API 发出请求时,该请求可能会失败。例如,因为模型不存在,或者用户没有同意使用语言模型 API,或者因为超过了配额限制。使用 LanguageModelError 来区分不同类型的错误。

以下代码片段显示了如何发出语言模型请求

try {
  const [model] = await vscode.lm.selectChatModels({ vendor: 'copilot', family: 'gpt-4o' });
  const request = model.sendRequest(craftedPrompt, {}, token);
} catch (err) {
  // Making the chat request might fail because
  // - model does not exist
  // - user consent not given
  // - quota limits were exceeded
  if (err instanceof vscode.LanguageModelError) {
    console.log(err.message, err.code, err.cause);
    if (err.cause instanceof Error && err.cause.message.includes('off_topic')) {
      stream.markdown(
        vscode.l10n.t("I'm sorry, I can only explain computer science concepts.")
      );
    }
  } else {
    // add other error handling logic
    throw err;
  }
}

解释响应

发送请求后,您必须处理来自语言模型 API 的响应。根据您的使用场景,您可以将响应直接传递给用户,或者解释响应并执行额外的逻辑。

语言模型 API 的响应是基于流的 (LanguageModelChatResponse),这使您能够提供流畅的用户体验。例如,当您将 API 与 Chat API 结合使用时,通过连续报告结果和进度。

在处理流式响应时可能会发生错误,例如网络连接问题。请确保在您的代码中添加适当的错误处理来处理这些错误。

以下代码片段显示了一个扩展如何注册一个命令,该命令使用语言模型将活动编辑器中的所有变量名更改为有趣的猫名。请注意,扩展将代码流回编辑器以提供流畅的用户体验。

vscode.commands.registerTextEditorCommand(
  'cat.namesInEditor',
  async (textEditor: vscode.TextEditor) => {
    // Replace all variables in active editor with cat names and words

    const [model] = await vscode.lm.selectChatModels({
      vendor: 'copilot',
      family: 'gpt-4o'
    });
    let chatResponse: vscode.LanguageModelChatResponse | undefined;

    const text = textEditor.document.getText();

    const messages = [
      vscode.LanguageModelChatMessage
        .User(`You are a cat! Think carefully and step by step like a cat would.
        Your job is to replace all variable names in the following code with funny cat variable names. Be creative. IMPORTANT respond just with code. Do not use markdown!`),
      vscode.LanguageModelChatMessage.User(text)
    ];

    try {
      chatResponse = await model.sendRequest(
        messages,
        {},
        new vscode.CancellationTokenSource().token
      );
    } catch (err) {
      if (err instanceof vscode.LanguageModelError) {
        console.log(err.message, err.code, err.cause);
      } else {
        throw err;
      }
      return;
    }

    // Clear the editor content before inserting new content
    await textEditor.edit(edit => {
      const start = new vscode.Position(0, 0);
      const end = new vscode.Position(
        textEditor.document.lineCount - 1,
        textEditor.document.lineAt(textEditor.document.lineCount - 1).text.length
      );
      edit.delete(new vscode.Range(start, end));
    });

    try {
      // Stream the code into the editor as it is coming in from the Language Model
      for await (const fragment of chatResponse.text) {
        await textEditor.edit(edit => {
          const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1);
          const position = new vscode.Position(lastLine.lineNumber, lastLine.text.length);
          edit.insert(position, fragment);
        });
      }
    } catch (err) {
      // async response stream may fail, e.g network interruption or server side error
      await textEditor.edit(edit => {
        const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1);
        const position = new vscode.Position(lastLine.lineNumber, lastLine.text.length);
        edit.insert(position, (<Error>err).message);
      });
    }
  }
);

注意事项

模型可用性

我们不期望特定的模型永远受到支持。当您在扩展中引用语言模型时,请确保在向该语言模型发送请求时采取“防御性”方法。这意味着您应该优雅地处理无法访问特定模型的情况。

选择合适的模型

扩展作者可以选择最适合其扩展的模型。我们建议使用 gpt-4o,因为它具有性能和质量。要获取可用模型的完整列表,您可以使用以下代码片段

const allModels = await vscode.lm.selectChatModels(MODEL_SELECTOR);
注意

推荐的 GPT-4o 模型限制为 64K 个 token。从 selectChatModels 调用返回的模型对象具有一个 maxInputTokens 属性,显示 token 限制。我们将根据我们对扩展如何使用语言模型所了解的更多信息来扩展这些限制。

速率限制

扩展应负责任地使用语言模型,并注意速率限制。VS Code 会向用户公开扩展如何使用语言模型以及每个扩展发送了多少请求以及这如何影响各自配额的信息。

由于速率限制,扩展不应将语言模型 API 用于集成测试。在内部,VS Code 使用一个专用的非生产语言模型进行模拟测试,并且我们目前正在考虑如何为扩展提供可扩展的语言模型测试解决方案。

测试您的扩展

语言模型 API 提供的响应是非确定性的,这意味着您可能会对相同的请求获得不同的响应。这种行为可能会给测试您的扩展带来挑战。

扩展中用于构建提示和解释语言模型响应的部分是确定性的,因此无需使用实际语言模型即可对其进行单元测试。但是,与语言模型交互并获取响应本身是非确定性的,并且难以测试。考虑以模块化的方式设计您的扩展代码,以便您可以单元测试可以测试的特定部分。

发布您的扩展

创建 AI 扩展后,您可以将其发布到 Visual Studio Marketplace

  • 在发布到 VS Marketplace 之前,我们建议您阅读 Microsoft AI 工具和实践指南。这些指南提供了负责任地开发和使用 AI 技术的最佳实践。
  • 通过发布到 VS Marketplace,您的扩展将遵守 GitHub Copilot 可扩展性可接受的开发和使用策略
  • 如果您的扩展已经贡献了语言模型 API 以外的功能,我们建议您不要在 扩展清单中引入对 GitHub Copilot 的扩展依赖项。这样可以确保不使用 GitHub Copilot 的扩展用户可以使用非语言模型功能,而无需安装 GitHub Copilot。请确保在这种情况下进行适当的错误处理。
  • 发布扩展中所述,上传到 Marketplace。
© . This site is unofficial and not affiliated with Microsoft.