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()
を呼び出すことはできません。
すべてのダイアログの各ステップでチェックを追加する以外に、ユーザーが特定のメッセージを入力したときにダイアログスタック全体を終了する他の方法はありますか?
投稿された賞金:
ここに投稿したとんでもないハックを使用せずに、すべてのIDialog
sを終了する方法が必要です(ユーザー設定や設定など、必要なすべてのユーザーデータを削除します)。
基本的に、ユーザーが「quit」または「exit」と入力すると、現在進行中のIDialog
を終了し、ユーザーが会話を開始したかのように新しい状態に戻す必要があります。
IDialogContext
にまだアクセスできない_MessageController.cs,
_からこれを実行できるようにする必要があります。私が持っていると思われる唯一の有用なデータは、Activity
オブジェクトです。誰かがそれを行うための他の方法を指摘してくれたら嬉しいです。
これにアプローチする別の方法は、Postメソッドではなく、ボットの他の場所で「exit」および「quit」キーワードをチェックする別の方法を見つけることです。
しかし、それはIDialog
のすべてのステップで行われるチェックであってはなりません。なぜなら、それはコードが多すぎて、常に可能でさえないからです(PromptDialog
を使用するとき、ユーザーが入力したテキスト)。
私が探求しなかった2つの可能な方法:
IDialog
sを終了する代わりに、ユーザーとの新しい会話を開始します(新しいConversationId
)IDialogStack
オブジェクトを取得し、それを使用してダイアログスタックを管理します。Microsoftのドキュメントはこのオブジェクトについて沈黙しているため、どのように取得するのかわかりません。ボットのどこでも.Switch()
を許可するChain
オブジェクトを使用していませんが、それを使用するように書き換えることができると思われる場合は、これを解決する方法の1つになります。しかし、さまざまな種類のダイアログ(FormFlow
と通常のIDialog
)の間で分岐を行う方法を見つけていません。
あなたの質問の私の理解から、あなたが達成したいことはボットの状態を完全に破壊することなくダイアログスタックをリセットするです。
BotDataStore> BotData> DialogStack
[〜#〜] facts [〜#〜]を上から知ると、私の解決策は
// 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);
private static ILifetimeScope Container
{
get
{
var config = GlobalConfiguration.Configuration;
var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
return resolver.Container;
}
}
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));
}
それが役に立てば幸い。
指摘してくれた@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));
}
これが動作する恐ろしくいハックです。基本的にすべてのユーザーデータ(実際に必要になる可能性がある)を削除し、これにより会話が再開されます。
ユーザーデータを削除せずに、誰かがより良い方法を知っている場合は、共有してください。
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);
}
}
私はこれが少し古いことを知っていますが、私は同じ問題を抱えていて、投稿された解決策はもはや最良のアプローチではありません。
これがどのバージョンで利用可能かはわかりませんが、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();
}
他の誰かのために働いた追加のコード:
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