コードリーディングでGitHub Copilot Extensionsの仕組みを理解する(1)
(マガジンは有料設定ですが、この記事は無料で読むことができます)。
はじめに
GitHub社が提供するAIコーディング支援サービスGitHub Copilotには、その機能を拡張するためのGitHub Copilot Extensionsという仕組みがあります。(2024年11月時点ではパブリックプレビュー段階。2025年初頭に一般公開予定)。
Extensionsには以下の二通りの拡張方法があります。
GitHub Apps
VS Code拡張
GitHub AppsはGitHubのサービス側機能を拡張するための仕組みです。VS Code拡張は、コードエディターのVS Codeに拡張機能を組み込む仕組みですね。
本記事では後者の拡張方法を取り上げます。VS Code拡張の仕組みは元々存在するもので、Copilotだからといって何かが変わるわけではありません。GitHub Copilotが提供する大規模言語モデル(LLM)を利用したり、AIチャットボットを開発したりすることが可能なAPIが公開されたというのがポイントです。
公式ドキュメント:
https://docs.github.com/ja/copilot/building-copilot-extensions/about-building-copilot-extensions
APIドキュメントも用意されていますが、プレビュー段階ということで内容も網羅的とは言えず、未翻訳の部分も多いです。そこで、VS Code拡張のサンプルを動かしてみて、対応するコードを読んでAPIの使い方や拡張機能の実装を学んでいくというのが本記事の主旨です。
なお筆者自身も勉強過程であるため、もし内容に不正確な箇所があった場合はご容赦ください。適宜改訂してまいります。また、一般公開時にはAPI仕様に変更が入る可能性もある点はご留意願います。
環境準備
サンプルが公開されているリポジトリは以下です。
クローンしたら、chat-sampleというサブディレクトリへ移動し、npm installを実行後VS Codeを立ち上げます。
% git clone https://github.com/microsoft/vscode-extension-samples.git
% cd vscode-extension-samples/chat-sample
% npm install
% code .
チャットエージェントを動かす
chat-sampleには、以下二つのサンプルが入っています
@cat チャット参加者
@tools チャット参加者
チャット参加者(chat paticipant)とは、AIエージェントを指すものと考えてください。デフォルトで利用可能な @workspace や @vscode もチャット参加者です。特定の知識をコンテキストに持っていて、専門家として自律的にユーザーを支援することが可能なエージェントです。
今回の記事では@catを確認してみます。
VS Codeを立ち上げたらF5を押します。するとデバッグ機能が起動し、別プロセスでもう一つVS Codeが立ち上がるので、任意のプロジェクトフォルダを開きましょう。
Copilot Chatビューを開き、チャット欄に@を入力すると、利用可能なチャット参加者が候補に表示されます。@catが、サンプルで組み込まれたチャット参加者です。@cat /play や @cat /randomTeach というように、コマンドも用意されていることがわかります。
で、@catというチャット参加者は何をしてくれるのかというと、にゃんこ口調で技術的なトピックについて教えてくれるというものです。
試しに「@cat JavaScriptのクロージャについて教えて」と入力すると、以下のような回答が返ってきました。
@cat randomTeach とコマンドを打つと、ランダムなトピックで回答を返すように実装されています。
コードリーディング
package.json
VS Code拡張プロジェクトのpackage.jsonでは、"contributes"要素配下にチャット参加者に関するメタ情報を定義します。
"name"に指定したcat が、@catに対応します。"commands"には、このチャット参加者に対して利用可能なコマンドの一覧を配列で記述します。
extension.ts
extension.tsはエントリポイントとなるプログラムです。シンプルなチャットアプリであればこのファイル内に全て記述することも可能ですが、このサンプルプログラムでは部品が分割されています。
@catチャット参加者の処理は、7行目で呼び出されるregisterSimpleParticipant関数に記述されているので、それが格納されているsimple.tsを見てみましょう。
simple.ts
registerSimpleParticipant関数の全体構造は下図のようになっています(詳細実装部分は折り畳んでいます)。
(17行目〜):ハンドラー(vscode.ChatRequesthandler型)を作成
(94行目〜):チャット参加者(vscode.ChatParticipant型)を作成
(106行目〜):テレメトリー用のロガーを作成
(119行目〜):テレメトリー用のイベント購読
(127行目〜):チャット応答用のイベント購読
テレメトリー関連の処理は本質ではないため割愛し、その他の処理を見ていきます。
さてハンドラーですが、ユーザーからのチャットリクエストに応答する処理を記述します。ユーザーが指定したコマンドによって条件分岐するように記述されていますが、未指定の場合(elseブロック)を見てみましょう。
69行目の定数messagesには、プロンプトの配列が入っています。一つ目がカスタムプロンプトになっていて、猫のように答えろといった指示が書かれています。二つ目にはユーザーが入力したプロンプトをそのまま入れています。
75行目でrequest.model.sendRequestをコールしてサーバー(GitHub Copilotサービス)からの応答をawaitします。
応答は、ストリームで少しずつ返ってくるので、76行目からのfor awaitループにて逐次的に処理をします。stream(vscode.ChatResponseStream型)はユーザーに返すチャット応答を表すオブジェクトです。マークダウンで書き出します(73行目)。
次にチャット参加者です。チャット参加者を一意に識別するキー(package.jsonで指定したID)と、ハンドラーを紐づけてオブジェクトを生成します。アイコン画像やフォローアッププロバイダも指定しています。
フォローアッププロバイダは詳細は割愛しますが、チャット応答の下部に表示される、次の質問の候補を表示する役割のものです。
最後にサブスクリプション登録です。context.subscription.pushの引数には、vscode.Disposable型のオブジェクトを可変長で複数指定できます。
1つ目のcatは、先ほど作成した@chatチャット参加者で、この登録により実際にCopilot Chatのチャット欄から利用可能となります。
2つ目のvscode.commands.registerTextEditorCommandeで生成したオブジェクトについては、次回記事にて取り上げたいと思います。
※この先有料記事指定となっていますが、予告が書かれているだけです。(もしサポート頂ける方はマガジン購入をお願いします)
次回予告
ここから先は
コード生成AIマガジン Vol.1
ソフトウェア開発者向けに、コード生成AIに特化した記事を書いていきます。 2024年11月から12月にかけて投稿する記事をマガジンとしてセ…
この記事が気に入ったらチップで応援してみませんか?