【问题标题】:How to create a new IDialogContext instance in Microsoft Bot framework?如何在 Microsoft Bot 框架中创建新的 IDialogContext 实例?
【发布时间】:2017-09-06 15:01:52
【问题描述】:

我需要重置或终止(使用 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);
        }
    }

我的用例是,如果用户输入是,那么机器人应该返回是,如果用户输入否,那么机器人应该返回谢谢。如果用户键入“Hi”,机器人应该通过 Luis 找到 Hi 的答案,这将触发新的 Greeting Intent 并返回 Hi 用户。

如果我在这里使用 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");
    }

【问题讨论】:

  • 我想在我当前的函数中创建实例。因为我正在处理多个对话框,最后,我需要将它重定向到另一个需要 Idialogcontext 实例的函数
  • 请出示你的代码,否则真的很难理解你在做什么。
  • @EzequielJadib 您好我已经添加了代码..:)
  • 你为什么要杀死上下文?为什么你不使用 LuisDialog 而不是在你的方法中复制代码?
  • 这就是我想做的。我想重定向到另一个意图。假设有 2 个意图 A 和 B。虽然在一个条件下的意图 A 内,我想触发另一个意图。怎么做?。当我在内部重定向到另一个意图时,也使用当前方法,新对话框被推入堆栈。因此,当当前对话框退出时,它会触发上一个不期望的对话框。

标签: c# frameworks bots botframework azure-language-understanding


【解决方案1】:

根据我们在 cmets 中的讨论以了解更多您的要求,看来您不需要重置堆栈。

相反,您需要做的是利用您继承自 LuisDialogMessageReceived 方法。通过这样做,您可以直接调用该方法并强制它转到LUIS 来解析新的意图,而无需用户输入新的内容。

调用该方法与调用任何其他方法完全相同。唯一需要注意的是,由于MessageReceived 方法需要IAwaitable&lt;IMessageActivity&gt;,因此您必须创建它。好消息是这就像使用 Awaitable.FromItem 一样简单

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多