Bot Framework と Microsoft Graph で DevOps その 20 : ステートサービスで状態の管理

今回は状態管理について。既にアプリのコードで多用してますけど、あらためて説明を。 概要 ボットに欠かせない重要な機能が状態管理。例えば、前回ユーザーが何を言ったかという単純な事から、ユーザーや会話のコンテキストを理解するため等に使います。Bot Framework はステートサービスと呼ばれる状態管理の仕組みを提供しており、ダイアログやフォームフローは、裏でこの仕組みを使ってユーザーとの会話を管理しています。 スコープ Bot Framework は以下 3 つのスコープで状態管理が行えます。 ユーザー単位 (UserData) : 会話に関わらずユーザー個人としてのステート。 会話単位 (ConversationData) : 現在の会話に関するステート。会話は対個人も対グループもある。 会話の中の個人単位 (PrivateConversationData) : 現在の会話かつ、特定個人に関するステート。 どのスコープにデータを保存するかは、データの性質によって変えます。 ステートサービスのデータ保存場所 既定でマイクロソフトが管理するサーバーに保存しますが、独自に管理したい場合、任意の Azure Table Storage か DocumentDB に変更が可能です。サンプルが GitHub に公開されているので参考にしてください。データの保存地域やスペックも独自に決められるため、パフォーマンス向上にもなります。 尚、以下主な注意点。 ステートはチャネル単位。実質同一ユーザーでもチャネルが異なるとステートは別と扱われる。 保存するデータはシリアライズ可能なもの。 保存できるデータサイズは 64 KB。情報元はこちら。マスターデータ的なものは別途他の DB から取得し、ボットアプリに関連する情報のみステートサービスに保存。 ステートサービスはボットアプリを公開するサーバーとは異なる場所にデータを保存するため、サービスを再公開してもデータは消えない。一方エミュレータを使っている場合、ステート情報はエミュレータ内に保持。よってエミュレータを再起動するとデータが消える。 ステートクライアント ステートサービスに接続するためのクライアントは、以下の方法で作成、取得できます。 新規に作成 StateClient stateClient = new StateClient(new MicrosoftAppCredentials(microsoftAppId, microsoftAppPassword)); Activity から作成… Read more

Bot Framework と Microsoft Graph で DevOps その 19 : LUIS と多言語対応ボットの実装編

※2017/6/19 ユニットテストで必要なファイルが抜けていたため、追加 前回は LUIS 応用編ということでエンティティやフォームフローとの連携を紹介しました。今回は開発中のボットアプリに組み込むところとユニットテストについて見ていきます。 多言語対応 将来的に日本語で datetimeV2 が出れば別ですが、今回は英語版の LUIS を使います。よってユーザーからのメッセージは一旦翻訳しましょう。 翻訳サービス Cognitive の翻訳サービスを使います。詳細はこちら。ただ、探し方が悪いのか C# SDK がなかった。。 1. Azure ポータルから Translator Text API のキーを取得します。 2. ボットアプリプロジェクトの Services フォルダに ITranslationService.cs を追加し、コードを差し替え。 using System.Threading.Tasks; namespace O365Bot.Services {     public interface ITranslationService     {         Task<string> Translate(string content, string from, string to);     } } 3. TranslationService.cs を追加し、コードを差し替え。… Read more

Bot Framework と Microsoft Graph で DevOps その 18 : エンティティとフォームフローの連携!LUIS 応用編

前回 LUIS 入門編としてインテントと LUIS ダイアログの簡単な使いかたを紹介しました。今回は応用編として LUIS のエンティティとフォームフローとの密な連携を紹介します。尚、ボットアプリへの本格的な実装は次回で。 エンティティの活用 エンティティとは、文章におけるキーワードをカテゴライズしたものです。 Prebuilt domains 日本語ではまだ対応してませんが、LUIS はよくあるシナリオに関して、事前に定義したインテントとエンティティを追加できます。 1. https://luis.ai より前回作成した O365Bot_EN を開きます。 2. 左のメニューより Prebuilt domains をクリック。Calender を選択します。Learn more クリックすると追加されるインテントとエンティティの情報が表示されます。 3. 追加されたら左のメニューより Intents をクリック。インテント増えていることを確認します。それぞれに例文もあります。 4. Calnder.Add を開いて、どのような例文が登録されているか確認。[] で囲まれているのはエンティティとして認識される場所です。 5. Entities メニューから追加されたエンティティも確認。 6. 内容が重複するため、CreateEvent と GetEvents インテントを削除します。 カスタムエンティティの追加 Prebuild domain 同様、よく使うエンティティも事前定義されています。上記手順では時間についてのエンティティがないため、追加します。 1. 左のメニューより Entities をクリックします。 2. Add prebuild entity をクリック。… Read more

Bot Framework と Microsoft Graph で DevOps その 17 : 自然言語処理を試す LUIS 入門編

今回は LUIS (Language Understanding Intelligent Service) の入門編を。LUIS を使うことで、文章の意図(インテント)とキーワード(エンティティ)を取得することが出来ます。まずはイベント取得とイベント作成のインテントと取れるようにしてみます。 LUIS の登録と作成 1. https://luis.ai にアクセス。アカウントがない場合はアカウントの作成。ある場合はサインイン。 2. New App をクリックして新しいアプリを登録。 3. 日本語用の LUIS アプリをまず作成。 4. Create Intent をクリックして、Add Intent をクリック。 5. インテント名を GetEvents として保存。 6. テキストボックスに例文を入力。最低 5 個は入力して、保存。 7. 同じ手順で CreateEvent インテントも作成。 8. 左のメニューより Train & Test をクリックして、Train Application をクリック。 9. 例文を入力して、結果を確認。登録時とは異なる言い方をしましたが、無事インテント取得出来ました。 10. 左メニューより Publish App を選択して、Add a… Read more

Bot Framework と Microsoft Graph で DevOps その 16 : 会話のインターセプト処理

今回はボットアプリとユーザー間のやり取りを、インターセプトする方法を紹介します。 概要 ミドルウェアを会話の前後に差し込めると、会話のログ取得や、会話のフォワードなど、様々なことを既存のコードに影響を与えることなくできます。 インターセプトの実装 1. ボットアプリの Services フォルダに ActivityLogger.cs を追加し、コードを以下と差し替えます。 using Microsoft.Bot.Builder.History; using Microsoft.Bot.Connector; using System.Diagnostics; using System.Threading.Tasks; namespace O365Bot.Services {     public class ActivityLogger : IActivityLogger     {         public async Task LogAsync(IActivity activity)         {             Debug.WriteLine($”From:{activity.From.Id} – To:{activity.Recipient.Id} – Message:{activity.AsMessageActivity()?.Text}”);         }     } } 2. Global.asax.cs に処理差し込み用のコードを追加します。以下のコードと差し替えます。自分用の IoC Container と登録先を間違えないようにしてください。 using… Read more

Bot Framework と Microsoft Graph で DevOps その 15 : プロアクティブ通知 テスト編

※2017/06/11 これまでの記事でコードを一部直しました。動きがおかしい場合、過去記事を念のため再度確認してください。変更した記事はその5、その7、その9、その12、その13、その14 です。ファンクションテスト動いていませんでした。。 前回はプロアクティブ通知の実装をしましたが、今回はエミュレーターでの検証とテストを。 エミュレーターでのテスト これまでずっとローカルで試験を行っていましたが、Microsoft Graph から通知を行う関係で、サーバーは Azure に立てている状態で検証が必要となります。 エミュレータからの接続 1. エミュレーターより App Settings を開きます。 2. 画面の手順に従い、ngrok をインストール。パスを指定します。ngrok はローカルのアプリを ngrok サーバーをプロキシとして外部公開する仕組みです。 3. Url、App ID、App Password を入力して接続します。Locale は任意のものを使えます。 4. add appointment とメッセージを送ってみます。 5. 認証を求められたら接続はできています。 テスト手順 1. まず認証を済ませます。 2. イベントの作成を始めます。 3. https://portal.office.com より予定表に接続します。 4. 任意の予定を変更します。 5. 変更された旨通知がきます。詳細取得を選択します。 6. 詳細が表示され、元のダイアログに戻ることを確認します。 リモートデバッグ 今回のようにリモートに配置しないとテストできない場合、いくつかテスト方法はあります。 Visual Studio から Azure App… Read more

Bot Framework と Microsoft Graph で DevOps その 14 : プロアクティブ通知 実装編

※2017/6/11 一部コードを変更。 今回はボットアプリからプロアクティブにユーザーに話しかける方法について。内容多いので実装編とテスト編に分けて紹介します。 概要 本家のドキュメントが面白いので引用。https://docs.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-proactive-messages プロアクティブメッセージが生きるシナリオがいくつかあります。タイマーやリマインダーを設定した場合や、外部システムから通知を受け取った場合です。もしユーザーが、ある商品の値段をチェックするようボットアプリに依頼した場合、価格に変動があれば通知します。別の例としては、回答に時間を要する場合、後から連絡するということもあります。 プロアクティブ通知を実装する場合、以下の点に注意。 短時間に複数の通知を送らないこと。チャネルによっては制限がかかりボットアプリが停止されます。 会話したことのないユーザーにいきなり通知を送らない。 会話中に通知を送る場合 例えば次のような会話を考えます。 ロンドン旅行の予約をしようとしている際、前にモニターするよう指示しておいた、ラスベガスのホテルの価格が安くなったよ!と通知を受け、「え?なに?」と思わず聞いたら、それは日付ではありませんと言われる。明らかにボットアプリはロンドン旅行の予約のダイアログに戻っていますが、ユーザーからすると混乱するだけです。このような場合、以下の対処が考えられます。 現在のダイアログが終わるまで待ってから、通知を行う。会話に対する影響は減りますが、通知が遅くなります。ラスベガスにも行けなくなるかも。 現在のダイアログを一旦キャンセルして、通知をします。通知はリアルタイムですが、ロンドンに行きたい場合、また初めからやり直し。 現在のダイアログを保留して、トピックを明示的に変えます。ラスベガスのホテルについての話が終わったら、またロンドン旅行のダイアログに戻します。これが最良にも思えますが、ユーザーにとっても、開発者にとっても、複雑な処理になりえます。 通知の種類 プロアクティブな通知は、2 つに分類できます。 アドホック通知: ユーザーが現在会話しているかどうかに関わらず、通知を送る方法。現在の会話を変えることはありません。 ダイアログに基づいた通知: 現在の会話を把握して、通知のダイアログを差し込みます。通知のダイアログが終われば、元の会話に戻します。 予定の通知機能を実装 今回 O365 ボットには、イベントが変更されたことを通知する機能を付けます。各種コードは BotBuilder のサンプルから拝借します。 ダイアログの差し込み 1. ボットアプリの Services フォルダに ConversationStarter.cs ファイルを追加し、以下のコードと差し替えます。 using Autofac; using Microsoft.Bot.Builder.Dialogs; using Microsoft.Bot.Builder.Dialogs.Internals; using Microsoft.Bot.Connector; using System; using System.Threading; using System.Threading.Tasks; namespace O365Bot.Services {     public class… Read more

Bot Framework と Microsoft Graph で DevOps その 13 : グローバルメッセージでダイアログを制御

※2017/6/10 テストについてやっぱり追記 今回はグローバルメッセージについて紹介します。 概要 ユーザーは開発者の意図通りに話してくれるか分からないという話は既にしました。途中でキャンセルしたいかもしれないし、急遽別のことを確認したいかもしれません。そのような場合は、特定のキーワードで現在の処理を中断したりキャンセルできるようにします。Bot Framework ではこのような処理またはキーワードをグローバルメッセージと呼んでいます。 処理のキャンセル 1. まずキャンセルのキーワードを登録。ボットアプリプロジェクトの Dialogs フォルダに、CancelScorable.cs を作成し、以下のコードと差し替えます。キーワードは多言語対応ということでリソースを使っています。 using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Bot.Builder.Dialogs.Internals; using Microsoft.Bot.Builder.Internals.Fibers; using Microsoft.Bot.Connector; using Microsoft.Bot.Builder.Scorables.Internals; using O365Bot.Resources; namespace O365Bot.Dialogs { #pragma warning disable 1998     public class CancelScorable : ScorableBase<IActivity, string, double>     {         private readonly IDialogTask task;         public CancelScorable(IDialogTask task)… Read more

Bot Framework と Microsoft Graph で DevOps その 12 : ボットアプリとテストの多言語対応

※2017/6/10 ユニットテストとファンクションテストのコードを修正。 今回はこれまで紹介したダイアログやフォームフローにも関係する、多言語対応について紹介します。 Activity の Locale プロパティ Web API に送られてくる Activity には Locale プロパティがあります。ダイアログやフォームフローで作成されたダイアログはこの値をみて、動的に言語を切り替えます。ただすべてのチャネルで Locale セットしてくれるわけではありません。またダイアログ以外の独自のラベルは、別途多言語対応する必要があります。 エミュレーターでの言語指定 言語を接続時に指定できます。 多言語対応 リソースファイル ボットアプリはただの Web API のため、resx ファイルを使った多言語対応が可能です。 1. ボットアプリプロジェクトに Resources フォルダを追加。 2. 新しいアイテムとしてリソースファイルを追加。名前は O365BotLabel.resx としました。これが既定の言語リソースになります。 3. Create_Event を追加し、値として Creating an event. と設定。 4. 次に同じフォルダ内に、O365BotLabel.ja.resx リソースファイルを追加。以下のように同じリソースを追加。 5. CreateEventDialog.cs を開いて、コードを差し替え。ハードコードされたコメントをリソースに入れ替えました。また BuildOutlookEventForm を public static にしています。 using Autofac; using Microsoft.Bot.Builder.Dialogs;… Read more

Bot Framework と Microsoft Graph で DevOps その 11 : フォームフロー応用編

前回はフォームフローの概要を紹介しました。今回はフォームフローの高度な使い方を見ていきます。 FormBuilder 前回は以下のコードを使ってクラスからダイアログを自動生成しました。 return new FormBuilder<OutlookEvent>()     .Message(“イベントを作成します。”)     .AddRemainingFields() // すべてのフィールドを処理対象として追加     .OnCompletion(processOutlookEventCreate)     .Build(); FormBuilder は様々な機能がありますが、上記の例では AddRemainingFields メソッドで、クラスのすべてのフィールドをダイアログに追加、OnCompletion メソッドで完了時の処理呼び出しをしています。プロンプトの情報はクラスのプロパティに定義した Prompt や Template 属性から情報を得ています。 [Prompt(“件名は?”)] public string Subject { get; set; } 以下で他の機能を見ていきます。 個別にフィールド追加 Field メソッドを使うことで、個別にフィールドが追加できます。例えば以下の場合は件名と詳細だけを含めています。 return new FormBuilder<OutlookEvent>()     .Message(“イベントを作成します。”)     .Field(nameof(OutlookEvent.Subject))     .Field(nameof(OutlookEvent.Description))     .OnCompletion(processOutlookEventCreate)     .Build(); Field メソッドは個別にフィールドを追加するだけでなく、プロンプトの指定、表示するかどうかの検証、入力した値の検証などを含めることが出来ます。 return new FormBuilder<OutlookEvent>()… Read more