2019-10追記: 2018年9月末に GA したバージョン V4.0.7 で、破壊的変更が多かったためこのバージョンと互換の無い部分があります。バージョンにご注意くださいね。
State は、外見だけなら V3 からあまり変更はないですが...さらっと整理しておきます♪
手順だけ整理しようと思ったけどそれじゃー自分メモの意味がないので、ダラダラと余計な解説があります。
Bot Builder V4 で State を使う際に気にすることは、以下2点を今回のアジェンダとしてます。
Overview
- 1. 準備編
- 2. Azure へ デプロイ
- 2-1. Azure ポータルから Web Bot 作成
- 2-2. VS2017 からデプロイ
- 2-3. Channel に接続
- 3-1. State を使うための設定(今回)
- State を保持する場所を指定
- State の初期化設定
- 3-2. State の Read/Write(今回)
State ? 日本語だと「状態」っていう?個人的には「ステート」って言ってますが...(←日本語でも単語を英語の読むことが多いので、別業界の人からみたら「ルー大柴かよ」って感じなんだろうなぁ...)
3-1. State を使うための設定
前置き
Bot Builder V4 は ASP.NET Core なので、こーゆーのは Middleware で設定してしまうやつです。プロジェクトテンプレートで生成された EchoBot のコード(このブログ内では「デフォルトのコード」と呼ぶことにします)をみると、Startup.cs
の ConfigureServices
で設定されています。
デフォルトではインメモリーで保持する設定になっているので、サクッとデバッグができるようになっています。
あくまでローカルデバッグ専用のサクッと動かせるためのものです。デバッグを再起動したら消えちゃうやつです。
ここでは、簡易サンプルとして Azure Storage の Table に 保存する設定してみます。
State を保持する場所を指定(Azure Storage の Table の例)
まず、Azure ポータルでポチポチしてStorage を作成し接続文字列を取得しておきましょう。
(Storage の作成やキーの取得方法が不明な場合、別の内容について記載した以前のブログの「Table Storage の作成」部分と「接続文字列は、Azure Portal のStorage アカウントの」という文のあたりが参考に...)
Storage の接続文字列と Bot の State を保存するテーブル名は、appsettings.json
の中に設定してみます。
VS 2017 でソリューションエクスプローラーから appsettings.json
を開き、例えば以下のようにします(4~7行目が変更したとこ)。
接続文字列の値とテーブル名を自身の値にします。
(私の場合、テーブル名を botState としました)
次に、準備として Nuget で Microsoft.Bot.Builder.Azure をインストールします。
VS 2017 の上部のメニューで ツール
> Nuget パッケージ マネージャー
> ソリューションの Nuget パッケージの管理
を開きましょう(って操作はめんどいのでいつも クイック起動 から起動しますが...)
Nuget の管理画面の 参照
をクリックし以下をしましょう。
VS2017 のソリューションエクスプローラーから Startup.cs
を開き ConfigureServices
をみましょう。みるべき場所は2行だけです。
(以下の ConfigureServices
メソッドだけを切り抜いて貼ったコードだと 24行目 と 32行目 の部分)
dataStore をインメモリーと指定している部分をコメントアウトしましょう(以下コードだと24行目)。
次は、Tableに保存する部分をアンコメントします(以下コードだと32行目)。ついでに、先ほど appsetting.json に設定した情報を取得するよう変更しています。
※ ローカル開発用に、例えば appsetting.debug.json
とか環境ごとにつくったりユーザーシークレットを設定したりってのが普通ですが、今回は Bot の話中心なのでやってません。
これで Bot の State の保存先が設定できました。次はなんのステートを保存するかの設定(上記コードの 35行目のあたり)の話をします。
と、その前にざっくりと デフォルトで用意されている ConversationState と UserState の概要を書いておきます。
ConversationState と UserState の概要
BotBuilder V4 での State は、まず、2つ用意されています。
(BotState
を継承したクラスが2だけっぽいのでそう思っています。つまりは自作したい場合、 BotState
とか BotState<T>
を継承したクラス作って、必要な設定....PropertyName とGetStorageKey の設定あたりですね....をしてあげれば、作れそうですね。)
二つの特徴をざっくりまとめると以下の感じです。
Stateの種類 | 特徴 |
---|---|
ConversationState | 各チャンネルの会話の接続(ConversationId毎)ごとに保持。 保存のキーは $"conversation/{context.Activity.ChannelId}/{context.Activity.Conversation.Id}" |
UserState | チャンネルのユーザーごとに保持。 保存のキーは $"user/{context.Activity.ChannelId}/{context.Activity.From.Id}" |
2つと分ける意味は特にないのですが、もうひとつ、ダイアログを管理するための Dictionary<string, object>
型のストアもあります。これはダイアログについて書くタイミングがあれば触れます。
State の初期化設定
"初期化"というよりシリアライズ - デシリアライズの設定といった方が適切かもです。
ConversationState は、デフォルトで EchoState
クラスのスキーマになるよう上記のコード35行目で実装がされています。
デフォルトのコードだと、UserState の保存はありませんので設定してみましょう。
どのようなスキーマで保存するかは、自身で自由に決めれます。ジェネリクスで指定してあげればシリアライズ - デシリアライズしてくれます。
ConversationState だとサンプルコードでは EchoState
クラスですね。UserState はサンプルの実装がないので、以下のようにてきとーなクラスを作ってみました。
UserState を利用するなら、先ほど書いた Startup.cs
の ConfigureServices
メソッドに以下のコード(6行目)を追加してあげれば利用できます。
これで、会話をユーザーに送った際に、良しなに State に保存してくれる設定ができました。
3-2. State の Read/Write
デフォルトのコードで EchoBot
クラスを見ると、ConversationState
の読み込む方法や更新のコードはありますので、察して独自の実装もできそうですね。
// ConversationState を読み込む
var state = context.GetConversationState<EchoState>();
UserSate
は以下のように取得できます。
// UserSate を読み込む
var user = context.GetUserState<User>();
別の呼び出し方もありますが、結局内部でこのコードが呼ばれるのでここでは書かないです....
書き込む際は、普通に(上記のコードだと、state
や user
に)代入してあげればよいです。会話をユーザーに返すときに、SDK が保存してくれます。
Bot をデバッグして、Emulator でアクセスしてみましょう。Azure Storage Explorer などを使って、設定した Storage の Table を見てみると保存できていることを確認できます。Emulator で会話を再接続(Start Over
をクリック)すると、ConversationState は新しいレコードが作られるけど、UserState は単一であることがなども確認できますね。
終わりに
設定を保存するだけなら、この文章の1/3で終わったところですが、実装を見て "最小限" のメモをしたらダラダラなブログになってもーた.....。
次回は、QnA や LUIS との連携あたりでしょうか....Prompt も簡単だけど V3 から結構変わったの整理しとこうか....RichCard や Bot Builder tools も整理したいところです。