チュートリアル: Chat API を使用したコードチュートリアルチャット参加者の構築
このチュートリアルでは、GitHub Copilot Chat エクスペリエンスと統合する Visual Studio Code 拡張機能の作成方法を学習します。Chat 拡張機能 API を使用して、チャット参加者を貢献させます。あなたの参加者は、プログラミングの概念に関する説明とサンプル演習を提供できるコードチューターになります。
前提条件
このチュートリアルを完了するには、次のツールとアカウントが必要です。
ステップ 1: プロジェクトのセットアップ
まず、Yeoman と VS Code Extension Generator を使用して拡張機能プロジェクトを生成します。
npx --package yo --package generator-code -- yo code
セットアップを完了するには、次のオプションを選択します。
# ? What type of extension do you want to create? New Extension (TypeScript)
# ? What's the name of your extension? Code Tutor
### Press <Enter> to choose default for all options below ###
# ? What's the identifier of your extension? code-tutor
# ? What's the description of your extension? LEAVE BLANK
# ? Initialize a git repository? Yes
# ? Bundle the source code with webpack? No
# ? Which package manager to use? npm
# ? Do you want to open the new folder with Visual Studio Code? Open with `code`
拡張機能プロジェクトが生成されたら、extension.ts
と package.json
の 2 つのファイルで作業を行います。詳細については、拡張機能の構造に関するドキュメントを参照してください。簡単な概要として
extension.ts
は拡張機能のメインエントリポイントであり、チャット参加者のロジックが含まれています。package.json
には、参加者の名前や説明など、拡張機能のメタデータが含まれています。
extension.ts
の activate()
メソッドで自動生成されたコードを削除します。ここにチャット参加者のロジックを配置します。
ステップ 2: チャット参加者の登録
package.json
ファイルで、自動生成された contributes
セクションを次の内容に置き換えます。
"contributes":{
"chatParticipants": [
{
"id": "chat-tutorial.code-tutor",
"fullName": "Code Tutor",
"name": "tutor",
"description": "What can I teach you?",
"isSticky": true
}
]
}
このコードは、次の属性を持つチャット参加者を登録します。
- コードで参照される一意の ID
chat-tutorial.code-tutor
- 参加者からの応答のタイトル領域に表示されるフルネーム
Code Tutor
- チャットビューで
@tutor
としてチャット参加者を参照するために使用される名前tutor
- チャット入力フィールドにプレースホルダーテキストとして表示される説明 "何を教えましょうか?"
最後に、isSticky: true
を設定すると、ユーザーが参加者との対話を開始した後、チャット入力フィールドに自動的に参加者名が先頭に追加されます。
ステップ 3: プロンプトの作成
参加者が登録されたので、コードチューターのロジックの実装を開始できます。extension.ts
ファイルで、リクエストのプロンプトを定義します。
優れたプロンプトを作成することは、参加者から最適な応答を得るための鍵です。プロンプトエンジニアリングのヒントについては、この記事を参照してください。
あなたのコードチューターは、直接的な答えを提供するのではなく、概念を理解するために学生を導くことで、現実世界のチューターをエミュレートする必要があります。さらに、チューターはトピックに焦点を当て続け、プログラミング以外の質問に答えるのを控える必要があります。
次の 2 つのプロンプトを検討してください。どちらが指定された動作をする可能性が高いですか?
-
あなたは親切なコードチューターです。あなたの仕事は、ユーザーに概念の簡単な説明とサンプルコードを教えてあげることです。
-
あなたは親切なコードチューターです。あなたの仕事は、ユーザーに概念の簡単な説明とサンプルコードを教えてあげることです。一連のメッセージで概念のガイド付き概要で応答します。ユーザーに直接答えを与えるのではなく、自分で答えを見つけるように導きます。ユーザーがプログラミング以外の質問をした場合は、丁寧に応答を拒否してください。
2 番目のプロンプトはより具体的であり、参加者にどのように応答するかについて明確な指示を与えます。このプロンプトを extension.ts
ファイルに追加します。
const BASE_PROMPT =
'You are a helpful code tutor. Your job is to teach the user with simple descriptions and sample code of the concept. Respond with a guided overview of the concept in a series of messages. Do not give the user the answer directly, but guide them to find the answer themselves. If the user asks a non-programming question, politely decline to respond.';
ステップ 4: リクエストハンドラーの実装
プロンプトが選択されたので、リクエストハンドラーを実装する必要があります。これは、ユーザーのチャットリクエストを処理するものです。リクエストハンドラーを定義し、リクエストを処理するためのロジックを実行し、ユーザーに応答を返します。
まず、ハンドラーを定義します。
// define a chat handler
const handler: vscode.ChatRequestHandler = async (
request: vscode.ChatRequest,
context: vscode.ChatContext,
stream: vscode.ChatResponseStream,
token: vscode.CancellationToken
) => {
return;
};
このハンドラーの本文内で、プロンプトとプロンプトを含む messages
配列を初期化します。次に、ユーザーがチャットボックスに入力した内容を送信します。これは request.prompt
を介してアクセスできます。
request.model.sendRequest
を使用してリクエストを送信します。これにより、現在選択されているモデルを使用してリクエストが送信されます。最後に、応答をユーザーにストリーミングします。
// define a chat handler
const handler: vscode.ChatRequestHandler = async (
request: vscode.ChatRequest,
context: vscode.ChatContext,
stream: vscode.ChatResponseStream,
token: vscode.CancellationToken
) => {
// initialize the prompt
let prompt = BASE_PROMPT;
// initialize the messages array with the prompt
const messages = [vscode.LanguageModelChatMessage.User(prompt)];
// add in the user's message
messages.push(vscode.LanguageModelChatMessage.User(request.prompt));
// send the request
const chatResponse = await request.model.sendRequest(messages, {}, token);
// stream the response
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
return;
};
ステップ 5: チャット参加者の作成
ハンドラーが実装されたら、最後のステップは、Chat 拡張機能 API の createChatParticipant
メソッドを使用してチャット参加者を作成することです。package.json
で使用したのと同じ ID を使用してください。
参加者のアイコンを追加して、参加者をさらにカスタマイズする必要があります。これは、参加者と対話するときにチャットビューに表示されます。
// define a chat handler
const handler: vscode.ChatRequestHandler = async (
request: vscode.ChatRequest,
context: vscode.ChatContext,
stream: vscode.ChatResponseStream,
token: vscode.CancellationToken
) => {
// initialize the prompt
let prompt = BASE_PROMPT;
// initialize the messages array with the prompt
const messages = [vscode.LanguageModelChatMessage.User(prompt)];
// add in the user's message
messages.push(vscode.LanguageModelChatMessage.User(request.prompt));
// send the request
const chatResponse = await request.model.sendRequest(messages, {}, token);
// stream the response
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
return;
};
// create participant
const tutor = vscode.chat.createChatParticipant('chat-tutorial.code-tutor', handler);
// add icon to participant
tutor.iconPath = vscode.Uri.joinPath(context.extensionUri, 'tutor.jpeg');
ステップ 6: コードの実行
これで、チャット参加者を試す準備ができました! F5 キーを押してコードを実行します。VS Code の新しいウィンドウがチャット参加者とともに開きます。
Copilot Chat ペインで、@tutor
と入力して参加者を呼び出すことができるようになりました!
学習したい内容を入力して試してみてください。概念の概要を示す応答が表示されるはずです!
会話を続けるために関連するメッセージを入力すると、参加者が会話に基づいてフォローアップ応答をしないことに気付くでしょう。それは、現在の参加者がユーザーの現在のメッセージのみを送信しており、参加者のメッセージ履歴を送信していないためです。
下のスクリーンショットでは、チューターはスタックの開始説明で正しく応答しています。ただし、フォローアップでは、ユーザーが Python でのスタックの実装を見るために会話を続けていることを理解していないため、代わりに Python に関する一般的な応答を返しています。
ステップ 7: より多くのコンテキストのためのメッセージ履歴の追加
Copilot Chat の最大の価値の 1 つは、最適な応答を得るために複数のメッセージを反復処理できることです。これを行うには、参加者のメッセージ履歴をチャットリクエストに送信する必要があります。これは context.history
を介してアクセスできます。
その履歴を取得し、messages
配列に追加する必要があります。これは、request.prompt
が追加される前に行う必要があります。
// define a chat handler
const handler: vscode.ChatRequestHandler = async (
request: vscode.ChatRequest,
context: vscode.ChatContext,
stream: vscode.ChatResponseStream,
token: vscode.CancellationToken
) => {
// initialize the prompt
let prompt = BASE_PROMPT;
// initialize the messages array with the prompt
const messages = [vscode.LanguageModelChatMessage.User(prompt)];
// get all the previous participant messages
const previousMessages = context.history.filter(
h => h instanceof vscode.ChatResponseTurn
);
// add the previous messages to the messages array
previousMessages.forEach(m => {
let fullMessage = '';
m.response.forEach(r => {
const mdPart = r as vscode.ChatResponseMarkdownPart;
fullMessage += mdPart.value.value;
});
messages.push(vscode.LanguageModelChatMessage.Assistant(fullMessage));
});
// add in the user's message
messages.push(vscode.LanguageModelChatMessage.User(request.prompt));
// send the request
const chatResponse = await request.model.sendRequest(messages, {}, token);
// stream the response
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
return;
};
コードを実行すると、以前のメッセージのすべてのコンテキストを含む参加者と会話できるようになりました! 下のスクリーンショットでは、参加者はユーザーが Python でのスタックの実装を見るように要求していることを正しく理解しています。
ステップ 8: コマンドの追加
基本的な参加者が実装されたので、コマンドを追加して拡張できます。コマンドは、一般的なユーザーの意図に対する省略記法であり、/
記号で示されます。次に、拡張機能はコマンドを使用して、言語モデルに適切にプロンプトを出すことができます。
チューターに概念の練習問題を出すように促すコマンドを追加すると便利です。package.json
ファイルにコマンドを登録し、extension.ts
にロジックを実装する必要があります。コマンドに exercise
という名前を付けて、/exercise
と入力して呼び出せるようにすることができます。
package.json
で、commands
プロパティを chatParticipants
プロパティに追加します。ここで、コマンドの名前と簡単な説明を指定します。
"contributes": {
"chatParticipants": [
{
"id": "chat-tutorial.code-tutor",
"fullName": "Code Tutor",
"name": "tutor",
"description": "What can I teach you?",
"isSticky": true,
"commands": [
{
"name": "exercise",
"description": "Provide exercises to practice a concept."
}
]
}
]
},
チューターからサンプル演習を取得するロジックを実装する最も簡単な方法は、リクエストに送信するプロンプトを変更することです。参加者にサンプル演習を返すように求める新しいプロンプト EXERCISES_PROMPT
を作成します。これがどのようなものになるかの例を次に示します。
const EXERCISES_PROMPT =
'You are a helpful tutor. Your job is to teach the user with fun, simple exercises that they can complete in the editor. Your exercises should start simple and get more complex as the user progresses. Move one concept at a time, and do not move on to the next concept until the user provides the correct answer. Give hints in your exercises to help the user learn. If the user is stuck, you can provide the answer and explain why it is the answer. If the user asks a non-programming question, politely decline to respond.';
リクエストハンドラーで、ユーザーがコマンドを参照したことを検出するロジックを追加する必要があります。これは、request.command
プロパティを介して行うことができます。
コマンドが参照されている場合は、プロンプトを新しく作成した EXERCISES_PROMPT
に更新します。
// define a chat handler
const handler: vscode.ChatRequestHandler = async (
request: vscode.ChatRequest,
context: vscode.ChatContext,
stream: vscode.ChatResponseStream,
token: vscode.CancellationToken
) => {
// initialize the prompt
let prompt = BASE_PROMPT;
if (request.command === 'exercise') {
prompt = EXERCISES_PROMPT;
}
// initialize the messages array with the prompt
const messages = [vscode.LanguageModelChatMessage.User(prompt)];
// get all the previous participant messages
const previousMessages = context.history.filter(
h => h instanceof vscode.ChatResponseTurn
);
// add the previous messages to the messages array
previousMessages.forEach(m => {
let fullMessage = '';
m.response.forEach(r => {
const mdPart = r as vscode.ChatResponseMarkdownPart;
fullMessage += mdPart.value.value;
});
messages.push(vscode.LanguageModelChatMessage.Assistant(fullMessage));
});
// add in the user's message
messages.push(vscode.LanguageModelChatMessage.User(request.prompt));
// send the request
const chatResponse = await request.model.sendRequest(messages, {}, token);
// stream the response
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
return;
};
そして、追加する必要があるのはそれだけです! メッセージ履歴を取得し、リクエストを送信し、リクエストをストリーミングする残りのロジックはすべて同じままです。
これで、/exercise
と入力すると、チャット参加者が表示され、コーディングを練習するためのインタラクティブな演習を入手できます!
次のステップ
おめでとうございます! プログラミングの概念に関する説明とサンプル演習を提供できるチャット参加者を正常に作成しました。プロンプトを微調整したり、スラッシュコマンドを追加したり、言語モデル API などの他の API を活用したりすることで、参加者をさらに拡張できます。準備ができたら、Visual Studio Code Marketplace に拡張機能を公開することもできます。
このチュートリアルの完全なソースコードは、vscode-extensions-sample リポジトリにあります。