如何在 Microsoft Bot 框架中创建一个新的 IDialogContext 实例?
How to create a new IDialogContext instance in Microsoft Bot framework?
我需要重置或终止(使用 context.Done)当前 IDialogContext 实例并创建一个新实例并在不同的函数中使用它。如何创建这样的实例,IDialogContext 是一个接口。可能吗?
这是我试图从中调用函数的函数 "selfredirect"
private async Task ApprovalConfirm(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
xxxticket xxxticketobject = new xxxticket();
if (message.Text.Contains("yes"))
{
xxxticketobject = context.ConversationData.Get<xxxticket>("xxxcard");
if (xxxticketobject.action == "Approve")
await context.PostAsync("Accepted");
else
await context.PostAsync("Rejected");
context.ConversationData.RemoveValue("xxxfinalcard");
context.Reset();// *This is what I want to do...clear context and then call the following function*
await SelfRedirect(context, context.UserData.Get<string>("CurrentQuery"), "Approval");
}
else if (message.Text == "no")
{
await context.PostAsync("Thank you");
context.Done(context);
}
else
await SelfRedirect(context, context.UserData.Get<string>("CurrentQuery"), null);
}
自我重定向功能
public static async Task SelfRedirect(IDialogContext context, string msg, string intent=null)
{
try
{
DialogLuis LUISDialog = new DialogLuis();
IMessageActivity message = context.MakeMessage();
message.Text = msg;
var tasks = LUISDialog.services.Select(s => s.QueryAsync(message.Text, context.CancellationToken)).ToArray();
var results = await Task.WhenAll(tasks);
var winners = from result in results.Select((value, index) => new { value, index })
let resultWinner = LUISDialog.BestIntentFrom(result.value)
where resultWinner != null
select new LuisServiceResult(result.value, resultWinner, LUISDialog.services[result.index]);
if (intent != null)
{
winners = from result in results.Select((value, index) => new { value, index })
let resultWinner = new IntentRecommendation(intent)
where resultWinner != null
select new LuisServiceResult(result.value, resultWinner, LUISDialog.services[result.index]);
}
var winner = LUISDialog.BestResultFrom(winners);
if (winner == null)
{
throw new InvalidOperationException("No winning intent selected from Luis results.");
}
if (winner.Result.Dialog?.Status == DialogResponse.DialogStatus.Question)
{
var childDialog = await LUISDialog.MakeLuisActionDialog(winner.LuisService,
winner.Result.Dialog.ContextId,
winner.Result.Dialog.Prompt);
context.Call(childDialog, LUISDialog.LuisActionDialogFinished);
}
else
{
IAwaitable<IMessageActivity> item = null;
await LUISDialog.DispatchToIntentHandler(context, item, winner.BestIntent, winner.Result);
}
}
catch (Exception ex) { CommonMethods.LogTime("", ex, context); }
}
但是由于堆栈为空,我无法在重置后使用重定向功能。请帮助
让我详细说明为什么我必须通过这个小函数使用selfredirect函数而不是context.wait(MessageReceived)
private async Task ApprovalConfirm(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
if (message.Text == "no")
{
await context.PostAsync("Thank you");
context.Done(context);
}
else if (message.Text == "yes")
{
await context.PostAsync("yes");
context.Done(context);
}
else
{
context.Wait(MessageReceived);
}
}
我的用例是,如果用户输入是,那么机器人应该 return 是的,如果用户输入否,那么机器人应该 return 谢谢。如果用户键入 "Hi" 机器人应该通过 Luis 找到 Hi 的答案,这将命中一个新的 Greeting 意图和 return Hi user.
在这里,如果我使用 context.Wait(MessageReceived),那么机器人只会等待来自用户
的下一个查询
对话框的结构!
[LuisIntent("Approval")]
public async Task Approval(IDialogContext context, LuisResult result)
{
context.ConversationData.SetValue("currentIntent", "Approval");
.
.
.
PromptDialog.Choice<string>(context, ApprovalList, ...);
}
private async Task ApprovalList(IDialogContext context, IAwaitable<string> result)
{
try
{
var request_type = await result;
.
.
context.Wait(ApprovalResponse);
}
}
catch (Exception ex)
{
CommonMethods.LogTime("ApprovalList", ex, context);
}
}
private async Task ApprovalResponse(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
.
.
.
context.Wait(AfterApprovalComment);
}
catch (Exception ex)
{
CommonMethods.LogTime("ApprovalResponse", ex, context);
await context.PostAsync("out of approvals...");
context.Done(context);
}
}
private async Task ApprovalConfirm(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
.
.
.
await SelfRedirect(context, context.UserData.Get<string>("CurrentQuery"), "Approval");
}
根据我们在评论中的讨论,进一步了解您的要求,看来您不需要重置堆栈。
相反,您需要做的是利用您正在继承的 LuisDialog
中的 MessageReceived
方法。通过这样做,您可以直接调用该方法并强制它转到 LUIS
来解析新的意图,而不需要用户的新输入。
调用该方法与调用任何其他方法完全相同。唯一需要注意的是,由于 MessageReceived
方法需要一个 IAwaitable<IMessageActivity>
,因此您必须创建它。好消息是使用 Awaitable.FromItem
一样简单
我需要重置或终止(使用 context.Done)当前 IDialogContext 实例并创建一个新实例并在不同的函数中使用它。如何创建这样的实例,IDialogContext 是一个接口。可能吗?
这是我试图从中调用函数的函数 "selfredirect"
private async Task ApprovalConfirm(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
xxxticket xxxticketobject = new xxxticket();
if (message.Text.Contains("yes"))
{
xxxticketobject = context.ConversationData.Get<xxxticket>("xxxcard");
if (xxxticketobject.action == "Approve")
await context.PostAsync("Accepted");
else
await context.PostAsync("Rejected");
context.ConversationData.RemoveValue("xxxfinalcard");
context.Reset();// *This is what I want to do...clear context and then call the following function*
await SelfRedirect(context, context.UserData.Get<string>("CurrentQuery"), "Approval");
}
else if (message.Text == "no")
{
await context.PostAsync("Thank you");
context.Done(context);
}
else
await SelfRedirect(context, context.UserData.Get<string>("CurrentQuery"), null);
}
自我重定向功能
public static async Task SelfRedirect(IDialogContext context, string msg, string intent=null)
{
try
{
DialogLuis LUISDialog = new DialogLuis();
IMessageActivity message = context.MakeMessage();
message.Text = msg;
var tasks = LUISDialog.services.Select(s => s.QueryAsync(message.Text, context.CancellationToken)).ToArray();
var results = await Task.WhenAll(tasks);
var winners = from result in results.Select((value, index) => new { value, index })
let resultWinner = LUISDialog.BestIntentFrom(result.value)
where resultWinner != null
select new LuisServiceResult(result.value, resultWinner, LUISDialog.services[result.index]);
if (intent != null)
{
winners = from result in results.Select((value, index) => new { value, index })
let resultWinner = new IntentRecommendation(intent)
where resultWinner != null
select new LuisServiceResult(result.value, resultWinner, LUISDialog.services[result.index]);
}
var winner = LUISDialog.BestResultFrom(winners);
if (winner == null)
{
throw new InvalidOperationException("No winning intent selected from Luis results.");
}
if (winner.Result.Dialog?.Status == DialogResponse.DialogStatus.Question)
{
var childDialog = await LUISDialog.MakeLuisActionDialog(winner.LuisService,
winner.Result.Dialog.ContextId,
winner.Result.Dialog.Prompt);
context.Call(childDialog, LUISDialog.LuisActionDialogFinished);
}
else
{
IAwaitable<IMessageActivity> item = null;
await LUISDialog.DispatchToIntentHandler(context, item, winner.BestIntent, winner.Result);
}
}
catch (Exception ex) { CommonMethods.LogTime("", ex, context); }
}
但是由于堆栈为空,我无法在重置后使用重定向功能。请帮助
让我详细说明为什么我必须通过这个小函数使用selfredirect函数而不是context.wait(MessageReceived)
private async Task ApprovalConfirm(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
if (message.Text == "no")
{
await context.PostAsync("Thank you");
context.Done(context);
}
else if (message.Text == "yes")
{
await context.PostAsync("yes");
context.Done(context);
}
else
{
context.Wait(MessageReceived);
}
}
我的用例是,如果用户输入是,那么机器人应该 return 是的,如果用户输入否,那么机器人应该 return 谢谢。如果用户键入 "Hi" 机器人应该通过 Luis 找到 Hi 的答案,这将命中一个新的 Greeting 意图和 return Hi user.
在这里,如果我使用 context.Wait(MessageReceived),那么机器人只会等待来自用户
的下一个查询对话框的结构!
[LuisIntent("Approval")]
public async Task Approval(IDialogContext context, LuisResult result)
{
context.ConversationData.SetValue("currentIntent", "Approval");
.
.
.
PromptDialog.Choice<string>(context, ApprovalList, ...);
}
private async Task ApprovalList(IDialogContext context, IAwaitable<string> result)
{
try
{
var request_type = await result;
.
.
context.Wait(ApprovalResponse);
}
}
catch (Exception ex)
{
CommonMethods.LogTime("ApprovalList", ex, context);
}
}
private async Task ApprovalResponse(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
.
.
.
context.Wait(AfterApprovalComment);
}
catch (Exception ex)
{
CommonMethods.LogTime("ApprovalResponse", ex, context);
await context.PostAsync("out of approvals...");
context.Done(context);
}
}
private async Task ApprovalConfirm(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
.
.
.
await SelfRedirect(context, context.UserData.Get<string>("CurrentQuery"), "Approval");
}
根据我们在评论中的讨论,进一步了解您的要求,看来您不需要重置堆栈。
相反,您需要做的是利用您正在继承的 LuisDialog
中的 MessageReceived
方法。通过这样做,您可以直接调用该方法并强制它转到 LUIS
来解析新的意图,而不需要用户的新输入。
调用该方法与调用任何其他方法完全相同。唯一需要注意的是,由于 MessageReceived
方法需要一个 IAwaitable<IMessageActivity>
,因此您必须创建它。好消息是使用 Awaitable.FromItem