web-dev-qa-db-ja.com

ユーザーが「exit」、「quit」などを入力すると、すべてのダイアログを終了し、MS Bot Frameworkで会話を終了します

MS Bot Frameworkで非常に簡単なことを行う方法がわかりません。ユーザーが会話を中断し、現在のダイアログを終了して、「quit」、「exit」、または「やり直し」。

メインの会話のセットアップ方法は次のとおりです。

_    public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        try
        {
            if (activity.Type == ActivityTypes.Message)
            {
                UserActivityLogger.LogUserBehaviour(activity);

                if (activity.Text.ToLower() == "start over")
                {
                    //Do something here, but I don't have the IDialogContext here!
                }
                BotUtils.SendTyping(activity); //send "typing" indicator upon each message received
                await Conversation.SendAsync(activity, () => new RootDialog());
            }
            else
            {
                HandleSystemMessage(activity);
            }
        }
_

context.Done<DialogType>(this);でダイアログを終了する方法は知っていますが、このメソッドではIDialogContextオブジェクトにアクセスできないため、.Done()を呼び出すことはできません。

すべてのダイアログの各ステップでチェックを追加する以外に、ユーザーが特定のメッセージを入力したときにダイアログスタック全体を終了する他の方法はありますか?

投稿された賞金:

ここに投稿したとんでもないハックを使用せずに、すべてのIDialogsを終了する方法が必要です(ユーザー設定や設定など、必要なすべてのユーザーデータを削除します)。

基本的に、ユーザーが「quit」または「exit」と入力すると、現在進行中のIDialogを終了し、ユーザーが会話を開始したかのように新しい状態に戻す必要があります。

IDialogContextにまだアクセスできない_MessageController.cs,_からこれを実行できるようにする必要があります。私が持っていると思われる唯一の有用なデータは、Activityオブジェクトです。誰かがそれを行うための他の方法を指摘してくれたら嬉しいです。

これにアプローチする別の方法は、Postメソッドではなく、ボットの他の場所で「exit」および「quit」キーワードをチェックする別の方法を見つけることです。

しかし、それはIDialogのすべてのステップで行われるチェックであってはなりません。なぜなら、それはコードが多すぎて、常に可能でさえないからです(PromptDialogを使用するとき、ユーザーが入力したテキスト)。

私が探求しなかった2つの可能な方法:

  • 現在のすべてのIDialogsを終了する代わりに、ユーザーとの新しい会話を開始します(新しいConversationId
  • IDialogStackオブジェクトを取得し、それを使用してダイアログスタックを管理します。

Microsoftのドキュメントはこのオブジェクトについて沈黙しているため、どのように取得するのかわかりません。ボットのどこでも.Switch()を許可するChainオブジェクトを使用していませんが、それを使用するように書き換えることができると思われる場合は、これを解決する方法の1つになります。しかし、さまざまな種類のダイアログ(FormFlowと通常のIDialog)の間で分岐を行う方法を見つけていません。

25
K48

問題の内訳

あなたの質問の私の理解から、あなたが達成したいことはボットの状態を完全に破壊することなくダイアログスタックをリセットするです。


ファクト(githubリポジトリから読み取ったものから)

  1. フレームワークがダイアログスタックを保存する方法は次のとおりです。

BotDataStore> BotData> DialogStack

  1. BotFrameworkはAutoFacをDIコンテナとして使用しています
  2. DialogModuleは、ダイアログコンポーネント用のAutofacモジュールです

実行する方法

[〜#〜] facts [〜#〜]を上から知ると、私の解決策は

  1. 依存関係の登録コントローラで使用できるように:

// in Global.asax.cs
var builder = new ContainerBuilder();
builder.RegisterModule(new DialogModule());
builder.RegisterModule(new ReflectionSurrogateModule());
builder.RegisterModule(new DialogModule_MakeRoot());

var config = GlobalConfiguration.Configuration;
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterWebApiFilterProvider(config);
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
  1. Autofac Containerを取得します(コード内の任意の場所に自由に配置できます)

private static ILifetimeScope Container
{
    get
    {
        var config = GlobalConfiguration.Configuration;
        var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
        return resolver.Container;
    }
}
  1. スコープBotDataをロードします
  2. DialogStackをロードします
  3. DialogStackをリセットします
  4. 新しいBotDataBotDataStoreに戻す

using (var scope = DialogModule.BeginLifetimeScope(Container, activity))
{
    var botData = scope.Resolve<IBotData>();
    await botData.LoadAsync(default(CancellationToken));
    var stack = scope.Resolve<IDialogStack>();
    stack.Reset();
    await botData.FlushAsync(default(CancellationToken));
}

それが役に立てば幸い。


更新1(27/08/2016)

指摘してくれた@ejadibのおかげで、Containerはすでに会話クラスで公開されています。

上記の答えのステップ2を削除できます。最終的にはコードは次のようになります

using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
    var botData = scope.Resolve<IBotData>();
    await botData.LoadAsync(default(CancellationToken));
    var stack = scope.Resolve<IDialogStack>();
    stack.Reset();
    await botData.FlushAsync(default(CancellationToken));
}
26
Kien Chu

これが動作する恐ろしくいハックです。基本的にすべてのユーザーデータ(実際に必要になる可能性がある)を削除し、これにより会話が再開されます。

ユーザーデータを削除せずに、誰かがより良い方法を知っている場合は、共有してください。

    public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        try
        {
            if (activity.Type == ActivityTypes.Message)
            {
                //if the user types certain messages, quit all dialogs and start over
                string msg = activity.Text.ToLower().Trim();
                if (msg == "start over" || msg == "exit" || msg == "quit" || msg == "done" || msg =="start again" || msg == "restart" || msg == "leave" || msg == "reset")
                {
                    //This is where the conversation gets reset!
                    activity.GetStateClient().BotState.DeleteStateForUser(activity.ChannelId, activity.From.Id);
                }

                //and even if we reset everything, show the welcome message again
                BotUtils.SendTyping(activity); //send "typing" indicator upon each message received
                await Conversation.SendAsync(activity, () => new RootDialog());
            }
            else
            {
                HandleSystemMessage(activity);
            }
        }
9
K48

私はこれが少し古いことを知っていますが、私は同じ問題を抱えていて、投稿された解決策はもはや最良のアプローチではありません。

これがどのバージョンで利用可能かはわかりませんが、3.8.1では、ダイアログのどこでもトリガーできるIScorableサービスを登録できます。

それがどのように機能するかを示すサンプルコードがあり、「キャンセル」グローバルコマンドハンドラーがあります。

https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-GlobalMessageHandlers

コードの一部は次のようになります。

protected override async Task PostAsync(IActivity item, string state, CancellationToken token)
{
    this.task.Reset();
}
2
Ivo Udelsmann

他の誰かのために働いた追加のコード:

private async Task _reset(Activity activity)
    {
        await activity.GetStateClient().BotState
            .DeleteStateForUserWithHttpMessagesAsync(activity.ChannelId, activity.From.Id);

        var client = new ConnectorClient(new Uri(activity.ServiceUrl));
        var clearMsg = activity.CreateReply();
        clearMsg.Text = $"Reseting everything for conversation: {activity.Conversation.Id}";
        await client.Conversations.SendToConversationAsync(clearMsg);
    }

このコードは、ユーザーmmulhearnによってここに投稿されます: https://github.com/Microsoft/BotBuilder/issues/101#issuecomment-316170517

0
K48