(.NET) チャットボットの作成方法
チャットボットとは何ですか ? これは、独自のチャットチャネルで Space ユーザーと通信する Space アプリケーションです。最低限実行可能なボットは次のことを行う必要があります。
ユーザーがチャネルに
/
(スラッシュ) を入力すると、使用可能なコマンドのリストが表示されます。少なくとも 1 つのコマンドを指定します。ユーザーがこのコマンドをチャネルに送信した後、ボットは何かを実行してからメッセージで応答する必要があります。
何をしたらいいでしょう
まずはチャットボットを作ってみましょう ! ようこそ – 「リマインダー」ボットです。
ボットは、一定時間が経過するとユーザーにリマインダーを送信します。例: ユーザーが remind 60 take a nap
コマンドをボットに送信すると、60 秒後にボットは take a nap
メッセージで応答します。また、ボットには、要求されたときに help
を提供するコマンドがあります。
このチュートリアルでは、チャットボットを作成するプロセス全体を説明します。結果のソースコード(英語)をダウンロードすることもできます。
チャットボット作成用スターターキット
旅の途中で何が必要になるでしょうか?
ボットは C# と .NET で作成します。.NET アプリケーションの構築に使用できる IDE は多数あるため、推奨する IDE を使用できます。このチュートリアルでは、JetBrains Rider を使用します。 | |
アプリケーションの開発トピックで学んだように、アプリケーションは Space HTTP API を使用して Space と通信する必要があります。Space アプリの開発を容易にするために、Kotlin および .NET 用の Space SDK を提供しています。SDK には、Space での認証と通信を簡単に行うことができる HTTP API クライアントが含まれています。NuGet パッケージの依存関係をプロジェクトに追加して、Space SDK を使用します。 | |
トンネリングサービス このようなサービスは、ローカルサーバーを公共のインターネットに公開します。これにより、チャットボットをローカルで実行し、パブリック URL (チャットボットのエンドポイントとして指定します) を介して Space からアクセスできるようになります。例: この目的には、ngrok(英語) トンネリングサービスを使用できます。ngrok の使用を開始するには、ngrok クライアント(英語)をダウンロードする必要があります。今回の目的では、ngrok の無料プランで十分です。 |
ステップ 1. ASP.NET アプリケーションを作成する
JetBrains Rider を開きます。
ウェルカム画面で、新規ソリューションを使用して新しいソリューションの作成を開始します。
テンプレートのリストで、ASP.NET CoreWeb アプリケーションを選択します。
タイプで空を選択します。このテンプレートは、必要最小限の構成でプロジェクトをセットアップします。
ソリューション名とプロジェクト名 (例:
RemindMeBot
) を指定し、作成をクリックします。以上です ! これで、ボットの構築を開始できる Web アプリケーションが完成しました。
ステップ 2. Space SDK を入手する
RemindMeBot プロジェクトのコンテキストメニューを使用し、NuGet パッケージの管理を選択します。これにより、Rider で NuGet ツールウィンドウが開きます。
JetBrains.Space.AspNetCore
パッケージを検索します。このパッケージには、構築しているチャットボットなどの Space アプリケーションを作成するためのヘルパーが含まれています。終わり ! これで、プロジェクトに Space SDK が追加されたため、「リマインドミー」ボットの構築を開始できます。
ステップ 3. トンネリングサービスを実行する
Space にチャットボットを登録する前に、そのチャットボットの公開 URL を取得する必要があります。開発環境はおそらく NAT の背後にあるため、URL を取得する最も簡単な方法はトンネリングサービスを使用することです。この例では、ngrok を使用します。
ngrok クライアント(英語)をダウンロードして解凍します。
ターミナル (macOS または Linux) またはコマンドライン (Windows) で、ngrok ディレクトリを開きます。
デフォルトでは、プロジェクトはポート 5001 で HTTP サーバーを実行するように構成されています (これは
Properties/launchSettings.json
ファイルで確認できます)。このポートに対してトンネリングを実行します。./ngrok http 5001ngrok サービスが開始されます。次のようになります。
Session Status online Account user@example.com (Plan: Free) Version 3.0.6 Region United States (us) Latency - Web Interface http://127.0.0.1:4040 Forwarding https://98af-94-158-242-146.ngrok.io -> http://localhost:8080 Connections ttl opn rt1 rt5 p50 p90 0 0 0.00 0.00 0.00 0.00ここで注目するのは
Forwarding
行です。これにはパブリック URL が含まれています。ngrok は、トンネリングサービスを使用して、この URL からのリクエストをローカルホストにリダイレクトします。上記の例では、アドレスはhttps://98af-94-158-242-146.ngrok.io
ですが、ngrok がこれらのランダムな URL を動的に生成するため、あなたの場合は別のものになります。よくやった ! これで、トンネリングサービスが実行され、将来のチャットボットのパブリック URL が完成しました。
ステップ 4. Space にチャットボットを登録する
Space とチャットボットが相互に通信できるようにするには、ボットを Space に登録する必要があります。
アプリケーションを開発するときは、次の 2 つの重要なことを決定する必要があります。
単一組織アプリケーションは、単一の Space 組織のみを対象としています。Space ユーザーは、Space UI で単一組織アプリケーションを手動で登録および構成します。
複数組織のアプリケーションは複数の Space 組織を対象としています。複数組織アプリケーションは、API 呼び出しを使用して、特定の Space インスタンスに自身を登録し、構成します。
練習しているだけなので、複数組織アプリケーションの構成の複雑さに気を取られても意味がありません。代わりに、Space UI を使用してアプリケーションを登録し、構成します。そこで、単一組織アプリケーションを作成します。
認可主体 : アプリケーションが Space 内でどのように動作するかを決定します。アプリケーション自体に代わって、特定の Space ユーザーに代わって、またはその両方で動作します。これにより、アプリケーションがどの認証フローを使用するかが決まります。
この例では、チャットボットは自分自身に代わって、独自のチャットチャネルで通知を送信します。OAuth 2.0 フローとして、クライアント資格情報フローを使用します。これにより、アプリケーションはクライアント ID とクライアントシークレットを使用して Space で認証できるようになります。
要約すると、私たちのチャットボットは、クライアント資格情報認証フローを使用する単一組織アプリケーションです。それでは、ボットを Space に登録しましょう。
Space インスタンスを開きます。
メインメニューで、「 拡張」をクリックし、「インストール済み」を選択します。
新しいアプリをクリックします。
アプリケーションに一意の名前 (
remind-me-bot
など) を付け、「作成」をクリックします。概要タブで、チャットボットを選択します。これにより、アプリケーションのチャットチャネルが有効になります。
「許可」タブを開きます。このボットはシンプルであり、Space からデータを取得しないため、このタブでは何も変更しません。
このタブは、それがいかに重要であるかを示すためだけに表示されています。アプリがさまざまな Space モジュールにアクセスする必要がある場合は、対応するアクセス許可を提供する必要があります。権限のリクエストについて詳しくは、こちらを参照します。
「認証」タブを開きます。クライアント資格情報フローはデフォルトですべてのアプリケーションに対して有効になっていることに注意してください。アプリケーションのクライアント ID およびクライアントシークレットを取得する必要があります。私たちのチャットボットはそれらを使用して Space アクセストークンを取得します。
ユーザーがチャットボットチャネルに何かを入力すると、Space はユーザー入力をアプリケーションに送信します。次のステップは、アプリケーションエンドポイントの URL を指定し、Space からのリクエストを検証する方法を選択することです。
エンドポイントタブを開きます。
エンドポイント URI で、ボットのトンネリングサービスによって生成されたパブリック URL を指定します。このエンドポイントの汎用性を低くし、URL に接尾辞 (例:
api/space
) を追加しましょう。最終エンドポイントはhttps://{random_string_from_ngrok}.ngrok.io/api/space
になります。デフォルトでは、Space は公開鍵検証方法を使用することを推奨します。デフォルトのままにして、「保存」をクリックします。
よくやった ! これで、ボットが Space に登録され、必要な認証データがすべて揃ったため、ボットの開発を開始する準備が整いました。
ステップ 5. Web フックハンドラーを登録する
準備完了、セット、コード ! まず、アプリケーションの構成ファイルを更新します。次に、Space からの受信メッセージに応答し、応答を送り返すことができる RemindMeBotHandler
クラスを作成して登録します。
プロジェクト内の
appsettings.json
ファイルを編集します。それに
Space
要素を追加します。ファイルは次のようになります。{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "Space": { "ServerUrl": "https://organization.jetbrains.space", "ClientId": "value-of-client-id", "ClientSecret": "value-of-client-secret", "VerifySigningKey": { "IsEnabled": false, "EndpointSigningKey": "value-of-endpoint-signing-key" }, "VerifyHttpBearerToken": { "IsEnabled": false, "BearerToken": "value-of-bearer-token}" }, "VerifyHttpBasicAuthentication": { "IsEnabled": false, "Username": "value-of-username", "Password": "value-of-password" }, "VerifyVerificationToken": { "IsEnabled": false, "EndpointVerificationToken": "value-of-endpoint-verification-token" } } }要素の値をいくつか更新する必要があります。ServerUrl
は、Space インスタンスの URL です。ClientId
、ClientSecret
は、アプリケーションの登録時に取得した ID とシークレットです。アプリケーションの登録時に、選択した認証方法の
IsEnabled
オプションをtrue
に設定します。他のオプションも必ず更新してください。たとえば、必要に応じてEndpointSigningKey
またはEndpointVerificationToken
を設定します。
プロジェクトに
RemindMeBotHandler
クラスを作成し、コードを追加します。using JetBrains.Space.AspNetCore.Experimental.WebHooks; namespace RemindMeBot; public class RemindMeBotHandler : SpaceWebHookHandler { }RemindMeBotHandler
クラスは Space SDK のSpaceWebHookHandler
クラスを継承していることに注意してください。これは私たちのためにさまざまなことを処理します。メッセージペイロードを取得し、受信トークンを EndpointVerificationToken 構成値と比較することにより、ボットがリクエストを受信する Space インスタンスを検証します。
EndpointSigningKey を使用し、メッセージ署名を計算することで、メッセージペイロードが改ざんされていないことを保証します。
接続してみましょう。
Program.cs
のコードを更新し、Space のアプリケーションヘルパーを登録します。var builder = WebApplication.CreateBuilder(args);
を読み取る行の直後に、次のコードを追加します。// Space client API builder.Services.AddSingleton<Connection>(provider => new ClientCredentialsConnection( new Uri(builder.Configuration["Space:ServerUrl"]), builder.Configuration["Space:ClientId"], builder.Configuration["Space:ClientSecret"], provider.GetService<IHttpClientFactory>().CreateClient())); builder.Services.AddSpaceClientApi(); // Space webhook handler builder.Services.AddSpaceWebHookHandler<RemindMeBotHandler>(options => builder.Configuration.Bind("Space", options));注意すべき点:
AddHttpClient()
は、Space SDK によって使用される .NETHttpClient
を登録し、サービスとして利用できるようにします。AddSingleton<Connection>(...)
は、前に作成した構成を使用して、Space と連携するための接続を登録します。AddSpaceClientApi()
は Space API クライアントを登録し、サービスとして利用できるようにします。このチュートリアルの後半では、これを利用してボットのユーザーにチャットメッセージを送信できます。AddSpaceWebHookHandler<RemindMeBotHandler>(...)
は、RemindMeBotHandler
クラスを Web フックハンドラーとして登録します。このクラスはまだ存在しません。このクラスには「リマインダー」ボットのロジックが含まれますが、これはまだ実装する必要があります。
さらに
Program.cs
ファイルのvar app = builder.Build();
という行の直後に、次のコードを追加します。app.MapSpaceWebHookHandler<RemindMeBotHandler>("/api/myapp"); app.MapGet("/", () => "Space app is running.");注意すべき点:
app.MapSpaceWebHookHandler<RemindMeBotHandler>
は、/api/myapp
パス上の Web サーバー上で「リマインダー」ボットを利用できるようにします。これは、アプリケーションの登録時に入力したパスと一致する必要があります。app.MapGet("/", ...
は、誰かがブラウザーから「リマインダー」ボットにアクセスしたときにサーバーが返すデフォルトの応答を登録します。このようなデフォルトの応答を Space ボットに追加することをお勧めします。
終わり ! 最初のコマンドの追加を開始できる
RemindMeBotHandler
クラスを作成し、Space SDK を使用して登録しました。
ステップ 6. 最初のコマンドを作成する
まずは簡単なことから始めましょう。チャットボットの使用方法のヒントを表示する help
コマンドです。
RemindMeBotHandler
クラスを更新し、そのコードを次のコードで上書きします。using System.Threading.Tasks; using JetBrains.Space.AspNetCore.Experimental.WebHooks; using JetBrains.Space.Client; namespace RemindMeBot; public class RemindMeBotHandler : SpaceWebHookHandler { private readonly ChatClient _chatClient; public RemindMeBotHandler(ChatClient chatClient) { _chatClient = chatClient; } public override async Task HandleMessageAsync(MessagePayload payload) { var messageText = payload.Message.Body as ChatMessageText; if (string.IsNullOrEmpty(messageText?.Text)) return; await HandleHelpAsync(payload); } private async Task HandleHelpAsync(MessagePayload payload) { await _chatClient.Messages.SendMessageAsync( recipient: MessageRecipient.Member(ProfileIdentifier.Id(payload.UserId)), content: ChatMessage.Text("Soon the help will be shown here!")); } }注:
ASP.NET ランタイムは、
RemindMeBotHandler
クラスを作成するときに、そのコンストラクターにChatClient
を挿入します。ChatClient
はプライベートフィールドに保存されるため、後でユーザーにチャットメッセージを送信するために使用できます。HandleMessageAsync(MessagePayload payload)
メソッドは Space SDK から継承され、ボットが Space からメッセージを受信したときに呼び出されます。後で、このメソッドを使用してさまざまなコマンドを処理します。現時点では、メッセージを受信するたびにHandleHelpAsync
メソッドが呼び出されます。HandleHelpAsync(MessagePayload payload)
メソッドでは、_chatClient
フィールドを通じて以前にインジェクションされたChatClient
を利用します。SendMessageAsync
メソッドを使用すると、Space 内の任意の受信者にメッセージを送信できます。受信者は、チャットチャネル、コメントの発行、ダイレクトメッセージなどになります。MessageRecipient.Member()
メソッドを使用して、ダイレクトメッセージを使用してユーザーにアドレス指定し、その後、help
コマンドを呼び出したユーザーの ID を使用してProfileIdentifier
を構築します。チャットメッセージのテキストは、
ChatMessage.Text()
メソッドを使用して作成されます。メッセージは単なるテキスト以上のものにすることができます。複雑なフォーマットや、ボタンなどの UI 要素も含めることができます。とりあえずはテキストだけで十分です。
良い ! これで、ユーザーが実際に動作を試せるコマンドができました。
ステップ 7. ボットを実行する
Ctrl+F5 を押すか、 メニューを使用してアプリケーションを起動します。
Space インスタンスを開いてボットを見つけます。Ctrl+K を押してその名前を入力します。
ユーザーが送信したコマンドを分析することはありません。どのような種類のリクエストに対しても、
HandleHelpAsync
で生成されたメッセージで応答します。ボットをテストするには、チャットに何かを入力します。次のヘルプメッセージが表示されるはずです。効いてるよ ! 次に、残りのボット機能を追加しましょう。
ステップ 8. スラッシュコマンドのサポートを追加
ボットを完全に機能できるようにしましょう。
チャットボットとみなされるためには、ユーザーがチャットで
/
(スラッシュ) を入力したときに、アプリケーションが使用可能なコマンドのリストで応答できなければなりません。この場合、ボットはListCommandsPayload
タイプのペイロードを受け取ります。これは、ボットクラスのHandleListCommandsAsync
メソッドをオーバーライドすることで処理できます。このボットは「リマインダー」ボットと呼ばれているため、タイマーを開始し、タイマーが完了したらユーザーに通知を送信する
remind
コマンドが必要です。
まずは利用可能なコマンドのリストを見てみましょう。
RemindMeBotHandler
クラスに次のコードを追加します。public override async Task<Commands> HandleListCommandsAsync(ListCommandsPayload payload) { return new Commands(new List<CommandDetail> { new CommandDetail("help", "Show this help"), new CommandDetail("remind", "Remind me in N seconds, e.g., to remind in 10 seconds, send 'remind 10'") }); }ボットが
ListCommandsPayload
を受信すると、CommandDetail
のリストを返すCommands
で応答できます。各CommandDetail
にはコマンドname
と、ヘルプメニューに表示されるdescription
があります。ユーザーがキーを押すたびに、Space は
ListCommandsPayload
を送信します。/
(スラッシュ) の場合、Space を押すとコマンドの完全なリストが表示されます。他のキーの場合、Space はそのキーを含むコマンドのみを検索して表示します。コマンドをリストできるようになったため、
HandleHelpAsync
メソッドを更新して適切なヘルプ情報を返しましょう。HandleHelpAsync
メソッドのコードを次のように置き換えます。private async Task HandleHelpAsync(MessagePayload payload) { var commands = await HandleListCommandsAsync( new ListCommandsPayload { UserId = payload.UserId }); await _chatClient.Messages.SendMessageAsync( recipient: MessageRecipient.Member(ProfileIdentifier.Id(payload.UserId)), content: ChatMessage.Block( outline: new MessageOutline("Remind me bot help", new ApiIcon("smile")), sections: new List<MessageSectionElement> { MessageSectionElement.MessageSection( header: "List of available commands", elements: new List<MessageElement> { MessageElement.MessageFields( commands.CommandsItems .Select(it => MessageFieldElement.MessageField(it.Name, it.Description)) .ToList<MessageFieldElement>()) }) })); }ここに:
コマンドのリストを取得するために
HandleListCommandsAsync
を呼び出しています。念のため、そのメソッドで必要な場合に使用できるように、ユーザー ID も渡します。ChatMessage.Text()
はChatMessage.Block()
に置き換えられたため、フォーマットされたヘルプメッセージを返すことができます。
これで、受信した
MessagePayload
をチェックして、目的のコマンドを特定できるようになりました。テキストが"remind"
で始まる場合は、HandleRemindAsync
メソッドを呼び出します。HandleMessageAsync
メソッドを更新します。public override async Task HandleMessageAsync(MessagePayload payload) { var messageText = payload.Message.Body as ChatMessageText; if (string.IsNullOrEmpty(messageText?.Text)) return; if (messageText.Text.Trim().StartsWith("remind")) { await HandleRemindAsync(payload, messageText); return; } await HandleHelpAsync(payload); }次に、新しい
HandleRemindAsync
メソッドを追加します。private async Task HandleRemindAsync(MessagePayload payload, ChatMessageText messageText) { var arguments = messageText.Text.Split(' ', StringSplitOptions.TrimEntries); if (arguments.Length != 2 || !int.TryParse(arguments[1], out var delayInSeconds)) { // We're expecting 2 elements: "remind", "X" // If that's not the case, return help. await HandleHelpAsync(payload); return; } await _chatClient.Messages.SendMessageAsync( recipient: MessageRecipient.Member(ProfileIdentifier.Id(payload.UserId)), content: ChatMessage.Block( outline: new MessageOutline($"I will remind you in {delayInSeconds} seconds", new ApiIcon("smile")), sections: new List<MessageSectionElement>())); Task.Run(async () => { try { await Task.Delay(TimeSpan.FromSeconds(delayInSeconds)); await _chatClient.Messages.SendMessageAsync( recipient: MessageRecipient.Member(ProfileIdentifier.Id(payload.UserId)), content: ChatMessage.Block( outline: new MessageOutline($"Hey! {delayInSeconds} seconds are over!", new ApiIcon("smile")), sections: new List<MessageSectionElement>())); } catch (Exception) { // Since we're using Task.Run to run code outside of the // request context, we want to catch any Exception here // to prevent the server from crashing. } }); }ここに:
HandleRemindAsync
はコマンドを検証し、有効なコマンド引数が指定されていない場合はHandleHelpAsync
を呼び出します。このコードは、文字列に 2 つの要素があるかどうか、および 2 番目の要素が有効な整数であるかどうかをチェックします。ユーザーがremind 10
と入力する場合、2 番目の引数は整数10
である必要があります。確認メッセージがユーザーに送信されます。
Task.Run(...)
は、要求された時間分の遅延をスケジュールし、遅延が終了するとユーザーにメッセージを送信します。
もう一度ボットを実行して、ボットのすべての機能を試してみましょう。
スラッシュを入力します:
help
コマンド:remind
コマンド:
よくやった ! シンプルなボットの作成が完了しました。
関連ページ:
Space SDK
Space SDK は、JetBrains Space HTTP API を操作できるようにし、Space アプリケーションの開発を簡素化するライブラリです。クイックスタート:1. プロジェクト内の Space SDK を参照する次の依存関係をプロジェクトの / ファイルに追加します。// the example is given for build.gradle.kts repositories { // here go other project repos ... maven(...
アプリケーションの開発
アプリケーションは、Space の機能を拡張する主な方法です。アプリケーションは、以下を通じて Space と対話できる外部サーバー側サービスまたはクライアント側プログラム (JavaScript、デスクトップ、モバイル) です。Space SDK、Space HTTP API、Space とアプリケーション間のインタラクション:空間とアプリケーションは双方向で通信できます。アプリケーションはデータを Space に送信できます。例: チャットチャネルにメッセージを送信し、プロジェクトやチーム...
Space での認証
Space のセキュリティは、アクセストークン、つまり API リクエストの認証に使用されるシークレットに基づいています。Space と通信するには、アプリケーションはまずアクセストークンを取得する必要があります。その後、このトークンを使用してリクエストを Space に送信できます。例:GET https://mycompany.jetbrains.space/api/http/absences Authorization: Bearer <here-goes-access-token&...
クライアント資格情報フロー
基本:アプリケーション自体に代わって承認を行います。チャットボットなど、自分自身に代わってアクションを実行するサーバー側アプリケーションに適しています。クライアント資格情報フローでは、アプリケーションはおよびを送信することで Space からアクセストークンを受け取ります。アプリケーションで Space SDK を使用する場合は、メソッドを利用してフローを実装できます。クライアント資格情報フローを使用してすべての操作にアクセスできるわけではありません。多くのアクション (記事の下書きの投稿など...
権限のリクエスト
特定の Space エンドポイントにアクセスするには、アプリケーションはまず対応するアクセス許可を取得する必要があります。例: アプリケーションがプロジェクトの課題を作成する場合、アプリケーションには課題の作成権限が必要です。課題の詳細を表示するには、課題を表示する権限が必要です。アプリケーションに必要な権限のセット全体は、権限スコープと呼ばれます。アプリケーションがアクセス許可を要求する方法は、アプリケーション自体の代わりに動作するアプリケーションと、Space ユーザーの代わりに動作するアプ...
Space HTTP API
Space HTTP API を使用すると、チャット、チームディレクトリ、プロジェクト、ドキュメント、パッケージなどの任意の Space モジュールにプログラムでアクセスできます。特定の API リクエストの実行の詳細については、API 参照を参照するか、API Playground(下記を参照) を使用してください。HTTP API をすぐに使い始めるには、Space SDK を使用します。API Playground:API Playground を使用すると、次のことが可能になります。Spac...