Language Model 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) はストリーミングベースであり、スムーズなユーザーエクスペリエンスを提供できます。たとえば、Chat 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 にアップロードします。