.NET 6 で Bot Framework SDK を使ってみよう
Bot Framework SDK を使って C# でボットを作るときは基本的に Bot Framework のテンプレートが追加される Visual Studio の拡張機能から作り始めるのが一番簡単なのですが、現時点ではまだ .NET Core 3.1 までしかテンプレートが用意されていません。
.NET 6 版もそのうち追加されると思いますが、とりあえず手動で .NET 6 対応でさくっと EchoBot を作ってみようと思います。Bot Framework SDK 的には .NET Core 3.1 までしか対応してない雰囲気を感じるので本番のボットは大人しくプロジェクトテンプレートから .NET Core 3.1 で作るのがいいような気がします。
Minimal APIs プロジェクトを作って Bot を足す
ASP.NET Core (空) のプロジェクトテンプレートで作成すると、Minimal APIs のプロジェクトが出来ます。これは以下のようなコードで小さな API とか作るのであれば最適なテンプレートになっています。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Bot アプリは /messages
という単一のエンドポイントを公開するだけでよくて、その中で Bot Framework SDK のほうに処理をぶん投げる形になるので Web API としてはシンプルになるので、おそらく Minimal APIs と相性がいいと思ったので、ここをベースにボットを作っていきましょう。
まずは NuGet から Microsoft.Bot.Builder.Integration.AspNet.Core
をプロジェクトに追加します。Bots フォルダーを作って、その中に EchoBot
クラスを作成して以下のようにオウム返しのボットを実装します。
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
namespace Dotnet6EchoBot.Bots;
public class EchoBot : ActivityHandler
{
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
await turnContext.SendActivityAsync(
MessageFactory.Text($"Echo: {turnContext.Activity.Text}"),
cancellationToken);
}
}
では、ボット系の初期化処理を Program.cs
に追加していきましょう。といっても本当に受け取ったものを丸投げするだけなのでコード量はそんなにありません。
ボットのダイアログの状態の保存とかをやりはじめると、もうちょっと長くなりますが、エコーボットだとこれくらいで済んで楽ですね。
using Dotnet6EchoBot.Bots;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
var builder = WebApplication.CreateBuilder(args);
// Bot 系のサービスの追加
builder.Services.AddSingleton<IBotFrameworkHttpAdapter, CloudAdapter>();
builder.Services.AddTransient<IBot, EchoBot>();
var app = builder.Build();
// Bot のリクエストを /api/messages で受け取って BotFramework SDK に dispatch
Task handleRequest(HttpRequest req, HttpResponse res, IBotFrameworkHttpAdapter adapter, IBot bot) =>
adapter.ProcessAsync(req, res, bot);
app.MapGet("/api/messages", handleRequest);
app.MapPost("/api/messages", handleRequest);
app.Run();
ローカルで実行して Bot Framework Emulator でつないで動かしてみるとばっちり動きました。やったね。
Azure 上にデプロイ
では Azure 上にデプロイしてみましょう。
今回はちょっと実験もかねて Azure AD へのアプリ登録を手動でやるようにしました。
追記
Azure AD へのアプリ登録よりも、次の記事のユーザー割り当て済みマネージド ID を使ったほうがいいです。
Azure AD へのアプリ登録
さて、Azure Bot サービスを使ってボットを作るときには Azure AD へのアプリ登録が必要です。このアプリの AppID と AppSecret で、ちゃんと Microsoft の Azure Bot Service からの通信なのか認証をしています。ここら辺のアプリ登録は Azure Bot のリソースをポータルから作成すると自動で作られるのですが手動で作る方法も確認したうえで自動に身を任せるのが好きなので今回は手動でやります。
- Azure AD のページを開いて「アプリの登録」から「+新規登録」を選択します
- 名前を入力してサポートされているアカウントの種類で個人の Microsoft アカウントをサポートするものを選んで作成します
- 作成後のページで表示されるアプリケーション (クライアント) ID を控えておきます
- API のアクセス許可から、デフォルトで追加されている User.Read の権限を削除します。このアプリは、あくまで Azure の Bot Service からの通信を認証するためだけに使うので権限は不要です。
- 証明書とシークレットからクライアントシークレットを作成してシークレットを保存します
Web Apps を作成してデプロイ
ここはあまり書くこともありませんが、EchoBot を単純に Azure Web App にデプロイします。.NET 6 をランタイムスタックに指定することさえ忘れなければ問題ありません。作成が完了したらデプロイします。
デプロイをしたら先ほど Azure AD に作成したアプリ ID とクライアントシークレットを Web App のアプリケーション設定に追加します。
MicrosoftAppId
というキーでアプリケーション ID を追加して MicrosoftAppPassword
というキーでクライアントシークレットを追加します。
(オプション) Bot Framework Emuletor で疎通確認
デプロイして設定が終わったら疎通確認をします。Bot Framework Emulator で Bot に接続する画面で以下の情報を入力します。
- Bot URL: AzureのWebAppのURLに /api/messages を追加したもの
- Microsoft App ID: Azure AD に追加したアプリのアプリケーション ID
- Microsoft App password: Azure AD に追加したアプリのクライアントシークレット
繋いでみて疎通確認が出来たらあと一歩です。
Azure Bot のリソース作成
次に Azure Bot を作ります。基本的にはデフォルトですが、作成の種類の箇所で「既存のアプリ登録を使用する」を選択して、先ほど Azure AD に作ったアプリのアプリケーション ID とクライアントシークレット(アプリケーションシークレット) を入力します。
Azure Bot の作成が完了したら Azure Bot の構成に移動してメッセージング エンドポイントに EchoBot をデプロイした Web App の URL に /api/messages
を追加した値を入力します。
設定が完了したら、あとは適宜チャネルの構成をしてつなぐだけです。
とりあえず初期状態で構成されている WebChat でためしてみました。動いてますね。
懸念点
いくつか懸念点があります。
- アプリを別で作成した状態だと、Azure Bot 組み込みの Web チャットでテストが接続できませんというエラーで使用できませんでした。
- アプリを別で作成した状態だと、Azure Bot の構成のアプリ IDのリンクをクリックするとアクセス権がないという理由で画面が表示されませんでした。
- Bot Framework SDK は JSON.NET を前提としているようなのですが、今回は JSON.NET を利用していないので、動作に影響がないのかが自身がありません。大人しく .NET 6 対応がされるのを待ったほうが無難な可能性もあります。
Discussion