VS Codeのエージェントモードを拡張するには、を試してください!

言語モデルAPI

Language Model API を使用すると、言語モデルを使用し、AI 駆動の機能と自然言語処理を Visual Studio Code 拡張機能に統合できます。

Language Model API は、さまざまな種類の拡張機能で使用できます。この API の典型的な用途は、チャット拡張機能で、言語モデルを使用してユーザーのリクエストを解釈し、回答を提供するのに役立ちます。ただし、Language Model API の使用はこのシナリオに限定されません。言語またはデバッガー拡張機能、あるいはカスタム拡張機能のコマンドまたはタスクの一部として言語モデルを使用する場合があります。たとえば、Rust 拡張機能は Language Model を使用して、名前変更エクスペリエンスを向上させるためのデフォルト名を提供できます。

Language Model API を使用するプロセスは、次のステップで構成されます。

  1. 言語モデルのプロンプトを構築する
  2. 言語モデルのリクエストを送信する
  3. 応答を解釈する

以下のセクションでは、これらのステップを拡張機能に実装する方法について詳しく説明します。

まず、チャット拡張機能のサンプルを参照してください。

言語モデルのプロンプトを構築する

言語モデルと対話するには、拡張機能はまずプロンプトを作成し、次に言語モデルにリクエストを送信する必要があります。プロンプトを使用して、モデルを使用する広範なタスクについて言語モデルに指示を提供できます。プロンプトは、ユーザーメッセージが解釈されるコンテキストを定義することもできます。

Language Model API は、言語モデルのプロンプトを構築する際に、2種類のメッセージをサポートしています。

  • ユーザー - 指示とユーザーのリクエストを提供するために使用されます。
  • アシスタント - 以前の言語モデルの応答履歴をプロンプトのコンテキストとして追加するために使用されます。

: 現在、Language Model API はシステムメッセージの使用をサポートしていません。

言語モデルのプロンプトを構築するには、2つのアプローチを使用できます。

  • LanguageModelChatMessage - 1つ以上のメッセージを文字列として提供してプロンプトを作成します。Language Model API を使い始めたばかりの場合は、このアプローチを使用するかもしれません。
  • @vscode/prompt-tsx - TSX 構文を使用してプロンプトを宣言します。

言語モデルのプロンプトの構成方法をより詳細に制御したい場合は、prompt-tsx ライブラリを使用できます。たとえば、このライブラリは、プロンプトの長さを各言語モデルのコンテキストウィンドウサイズに動的に適応させるのに役立ちます。@vscode/prompt-tsx の詳細を確認するか、チャット拡張機能のサンプルを参照して開始してください。

プロンプトエンジニアリングの概念について詳しく学ぶには、OpenAI の素晴らしいプロンプトエンジニアリングのガイドラインを読むことをお勧めします。

ヒント: 豊富な VS Code 拡張機能 API を活用して、最も関連性の高いコンテキストを取得し、プロンプトに含めるようにしましょう。たとえば、エディターのアクティブなファイルの内容を含める場合などです。

LanguageModelChatMessage クラスを使用する

Language Model API は、チャットメッセージを表現および作成するための LanguageModelChatMessage クラスを提供します。LanguageModelChatMessage.User または LanguageModelChatMessage.Assistant メソッドを使用して、それぞれユーザーメッセージまたはアシスタントメッセージを作成できます。

次の例では、最初のメッセージがプロンプトのコンテキストを提供します。

  • モデルが応答に使用するペルソナ (この場合は猫)
  • モデルが応答を生成する際に従うべきルール (この場合は、猫の比喩を使ってコンピュータサイエンスの概念を面白く説明する)

2番目のメッセージは、ユーザーからの特定のリクエストまたは指示を提供します。これは、最初のメッセージによって提供されたコンテキストに基づいて、達成すべき特定のタスクを決定します。

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 メソッドを使用して言語モデルにリクエストを送信します。

言語モデルを選択するには、vendoridfamily、または version のプロパティを指定できます。これらのプロパティを使用して、特定のベンダーまたはファミリーのすべてのモデルを広範に一致させるか、ID で特定のモデルを1つ選択します。これらのプロパティの詳細については、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 メソッドを呼び出すことで言語モデルにリクエストを送信できます。以前に作成したプロンプトを、追加のオプションやキャンセル トークンと共に渡します。

Language Model API にリクエストを行うと、リクエストが失敗する可能性があります。たとえば、モデルが存在しない、ユーザーが Language Model 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 からの応答を処理する必要があります。使用シナリオに応じて、応答をユーザーに直接渡すことも、応答を解釈して追加のロジックを実行することもできます。

Language Model API からの応答 (LanguageModelChatResponse) はストリーミングベースであり、スムーズなユーザーエクスペリエンスを提供できます。たとえば、API をチャット 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 トークンの制限があります。selectChatModels 呼び出しから返されるモデルオブジェクトには、トークン制限を示す maxInputTokens 属性があります。これらの制限は、拡張機能が言語モデルをどのように使用しているかについてさらに学ぶにつれて、拡大される予定です。

レート制限

拡張機能は、言語モデルを責任を持って使用し、レート制限を認識する必要があります。VS Code は、拡張機能が言語モデルをどのように使用しているか、各拡張機能が送信しているリクエストの数、そしてそれがそれぞれのクォータにどのように影響するかについて、ユーザーに対して透過的です。

拡張機能は、レート制限のため、統合テストに Language Model API を使用すべきではありません。内部的には、VS Code はシミュレーションテスト用に専用の非生産言語モデルを使用しており、現在、拡張機能向けにスケーラブルな言語モデルテストソリューションを提供する方法を検討しています。

拡張機能をテストする

Language Model API が提供する応答は非決定的であり、同じリクエストに対しても異なる応答が得られる可能性があります。この動作は、拡張機能のテストにおいて課題となる可能性があります。

プロンプトの構築と言語モデルの応答の解釈に関する拡張機能の部分は決定的であり、実際の言語モデルを使用せずにユニットテストが可能です。しかし、言語モデル自体との対話や応答の取得は非決定的であり、簡単にテストすることはできません。テスト可能な特定の部分をユニットテストできるように、拡張機能のコードをモジュール式に設計することを検討してください。

拡張機能を公開する

AI 拡張機能を作成したら、Visual Studio Marketplace に拡張機能を公開できます。

  • VS Marketplace に公開する前に、Microsoft AI ツールと実践ガイドラインを読むことをお勧めします。これらのガイドラインは、AI 技術の責任ある開発と使用に関するベストプラクティスを提供します。
  • VS Marketplace に公開することで、あなたの拡張機能はGitHub Copilot 拡張機能の許容可能な開発および使用ポリシーに準拠していることになります。
  • 拡張機能が Language Model API の使用以外の機能にすでに貢献している場合、拡張機能マニフェストで GitHub Copilot への拡張機能の依存関係を導入しないことをお勧めします。これにより、GitHub Copilot を使用しない拡張機能ユーザーでも、GitHub Copilot をインストールすることなく、言語モデル以外の機能を使用できるようになります。この場合、言語モデルにアクセスする際には適切なエラー処理を必ず行ってください。
  • 拡張機能の公開に記載されているように、Marketplace にアップロードしてください。