【问题标题】:Microsoft Bot Framework start the conversation from specific waterfall step in dialogMicrosoft Bot Framework 从对话框中的特定瀑布步骤开始对话
【发布时间】:2019-02-21 06:57:41
【问题描述】:

Microsoft Bot Framework V4,我在对话框中定义了一个瀑布对话框,如下所示

var waterfallSteps = new WaterfallStep[]

        {
            CallConfirmAsync,
            SimilarProductAsync,
            CheckNewVersionAsync,
        };

        AddDialog(new WaterfallDialog("productenquiry", waterfallSteps));

在执行前两个瀑布步骤后,由于用户端没有响应,我的对话停止了。因此,当用户再次回到机器人时,我想从第三种方法恢复,即 CheckNewVersionAsync。

谁能帮帮我。

【问题讨论】:

  • 嗨@Drew,我无法将答案标记为已接受。我可以用第二个答案解决这个问题。谢谢
  • 没关系,很高兴您的问题得到了解决!也许一旦你有足够的 StackOverflow 积分,你就可以回来并将其标记为已回答。 ??????

标签: dialog botframework bots state-management


【解决方案1】:

因此,在机器人级别,如果您已将 IStatePropertyAccessor<DialogState> 配置为 ConversationState,这应该会自动发生。无论用户响应多长时间,您的WaterfallDialog 都将保持在堆栈的顶部,并且它会准确地记住它所在的步骤。假设您的用户回到同一个对话,那么它将从中断的地方继续。

鉴于此,您提出这个问题的事实让我相信,也许您使用的 WebChat 在页面加载时不会保持相同的conversationId,除非您自己进行设置。如果是这种情况,那么我建议您再问一个关于如何做到这一点的问题,如果您无法弄清楚如何做到这一点,因为这是与正确保持对话状态不同的问题。

【讨论】:

    【解决方案2】:

    编辑:Drew 的回答是正确的,但我的回答提供了另一种潜在的解决方案。您可以在此处找到更多信息:Managing State。特别是:

    用户状态在机器人与之交谈的任何时候都可用 该频道上的该用户,无论对话如何 状态在特定对话中的任何时候都可用,无论 用户(即群组对话)私人对话状态为 范围既适用于特定对话,也适用于该特定用户

    提示

    用户状态和会话状态都由频道限定。相同 使用不同渠道访问您的机器人的人显示为 不同的用户,每个频道一个,每个都有不同的用户 状态。

    其他解决方案

    如果您能够指定 from Id,但不能确保 conversation Id 保持不变(见下文,陷阱下方),则此解决方案最适合。

    您可以在他们的UserState 中保存用户正在执行的步骤。

    基本机器人

    BasicBot 使用它的 GreetingState 类来做到这一点。

    来自其GreetingDialog

    在第一步中,它初始化GreetingState,它通过查看已经设置了哪些用户变量来跟踪用户在对话框中的进度:

    private async Task<DialogTurnResult> InitializeStateStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        var greetingState = await UserProfileAccessor.GetAsync(stepContext.Context, () => null);
        if (greetingState == null)
        {
            var greetingStateOpt = stepContext.Options as GreetingState;
            if (greetingStateOpt != null)
            {
                await UserProfileAccessor.SetAsync(stepContext.Context, greetingStateOpt);
            }
            else
            {
                await UserProfileAccessor.SetAsync(stepContext.Context, new GreetingState());
            }
        }
    
        return await stepContext.NextAsync();
    }
    

    然后在每一步中,它都会加载GreetingState:

    var greetingState = await UserProfileAccessor.GetAsync(stepContext.Context);
    

    并检查该步骤是否已经完成,例如:

    if (greetingState != null && !string.IsNullOrWhiteSpace(greetingState.Name) && !string.IsNullOrWhiteSpace(greetingState.City))
    

    如果没有greetingState.Name.City 存在,则提示输入,如果已填写,则继续:

    return await stepContext.NextAsync();
    

    在每一步,它都会保存到GreetingState,如下所示:

    greetingState.Name = char.ToUpper(lowerCaseName[0]) + lowerCaseName.Substring(1);
    await UserProfileAccessor.SetAsync(stepContext.Context, greetingState);
    

    为您的用例简化

    对你来说,如果你不需要保存用户信息,你可以创建一个简单的Step类:

    {
        /// <summary>
        /// User state properties for Waterfall Step.
        /// </summary>
        public class Step
        {
            public string StepNumber { get; set; }
        }
    }
    

    开始你的瀑布对话框:

    private async Task<DialogTurnResult> InitializeStateStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        var StepState = await UserProfileAccessor.GetAsync(stepContext.Context, () => null);
        if (StepState == null)
        {
            var StepStateOpt = stepContext.Options as StepState;
            if (StepStateOpt != null)
            {
                await UserProfileAccessor.SetAsync(stepContext.Context, StepStateOpt );
            }
            else
            {
                await UserProfileAccessor.SetAsync(stepContext.Context, new StepState());
            }
        }
    
        return await stepContext.NextAsync();
    }
    

    在每一步,加载当前的Step

    var stepState = await UserProfileAccessor.GetAsync(stepContext.Context);
    

    检查他们是否已经超过当前步骤:

    if (stepState.StepNumber <= 2)
    {
        // ...do stuff
        // Save that user has completed step
        stepState.StepNumber++;
        await UserProfileAccessor.SetAsync(stepContext.Context, stepState);
    }
    else
    {
        return await stepContext.NextAsync();
    }
    

    陷阱

    需要注意的几件大事:

    • UserState 仅针对相同的from IDchannel ID 持续存在。确保离开瀑布中间的用户在重新输入时具有相同的from ID,并且他们从相同的channel 重新输入。这不是模拟器的默认设置——在模拟器中,当会话重新启动时,会创建一个新的from ID。 (注意:认为from IDUser ID 的同义词。它只是来自Activity.From.Id

    • ConversationState 仅针对相同的 conversation IDchannel ID 持续存在。 conversation ID 在频道内的持久性因频道而异。

    有关不同 ID 的更多信息:ID fields in the Bot Framework

    【讨论】:

      猜你喜欢
      • 2017-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-20
      • 2017-04-27
      • 2016-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多