【问题标题】:Accessing user/conversation state before sending first message在发送第一条消息之前访问用户/对话状态
【发布时间】:2019-07-12 22:45:03
【问题描述】:

在 Bot Framework V4 中,it is explained 可以通过在OnTurnAsync 中创建对话上下文来访问用户状态或对话状态

var dc = await Dialogs.CreateContextAsync(turnContext);

或在对话上下文类中使用访问器

var state = await HogehogeSettingAccessor.GetAsync(stepContext.Context);

但是,如何在向对话框发送消息之前访问它们?

我目前正在开发 Directline API,并希望在发送第一条消息之前参考语言设置(例如,如果书面语言与设置不匹配,则忽略用户输入)。

private async Task OnMessageReceive(SocketMessage socketMessage)
{
    if (IsLanguageMatch(socketMessage)){
        await channel.SendMessageAsync(response);
    }
}

我如何做到这一点?

【问题讨论】:

    标签: c# botframework direct-line-botframework


    【解决方案1】:

    您可以让 OnTurnAsync 仅在满足您的条件时启动第一个/主对话框。 当用户第一次向机器人发送消息时,不会有任何活动的 Dialog。您可以利用该条件并在那里添加您的条件,只有在满足两者时才启动对话框:

     // Getting the bot accessor state you want to use   
    
    LanguageAccessor languageAccessor = await _accessors.LanguageAccessor.GetAsync(turnContext, () => new LanguageAccessor(), cancellationToken);
    
        // Every step sends a response. If no dialog is active, no response is sent and turnContext.Responded is null
        //where turnContext.Activity.Text is the message sent by the user
    
     if (!turnContext.Responded && ((languageAccessor.property)turnContext.Activity.Text))
    

    OnTurnAsync 应该如下所示:

            public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
                    {
    
                        if (turnContext.Activity.Type == ActivityTypes.Message)
                        {
            // Establish dialog state from the conversation state.
                            DialogContext dc = await _dialogs.CreateContextAsync(turnContext, cancellationToken);
    
                            // Get the user's info.
                           LanguageAccessor languageAccessor = await _accessors.LanguageAccessor.GetAsync(turnContext, () => new LanguageAccessor(), cancellationToken);
    
                            await _accessors.UserInfoAccessor.SetAsync(turnContext, userInfo, cancellationToken);
    
                            // Continue any current dialog.
                            DialogTurnResult dialogTurnResult = await dc.ContinueDialogAsync();    
    
                            // Every dialog step sends a response, so if no response was sent,
                            // then no dialog is currently active and the Else if is entered.
    
                            if (!turnContext.Responded && ((languageAccessor.property)turnContext.Activity.Text))
                            {
    
                                //This starts the MainDialog if there's no active dialog when the user sends a message
                                await dc.BeginDialogAsync(MainDialogId, null, cancellationToken);
    
    
                            }
    
                           //Else if the validation is not passed
                           else if (!turnContext.Responded && ! 
                           ((languageAccessor.property)turnContext.Activity.Text))
                              { await turnContext.SendActivityAsync("Thank you, see you next time"); }
                              }
                }
    

    另一种选择是将访问器对象发送到您要使用它的对话框,并使用第一个对话框的瀑布步骤在满足验证时继续对话框,否则结束它。

    瀑布步骤应如下所示:

         private async Task<DialogTurnResult> ValidationFirstStepAsync(
                    WaterfallStepContext stepContext,
                    CancellationToken cancellationToken = default(CancellationToken))
                {
                    // Access the bot UserInfo accessor so it can be used to get state info.
                    LanguageAccessor languageAccessor = await 
                    _accessors.LanguageAccessor.GetAsync(stepContext.Context, null, 
                    cancellationToken);
    
                   if ((languageAccessor)stepContext.Context.Activity.Text)
                   {             
                      await stepContext.Context.SendActivityAsync(
                                "Hi!");
                      return await stepContext.NextAsync();
                   }
                   else
                   { 
                      await stepContext.Context.SendActivityAsync("Sorry, your language is not supported");
                      return await stepContext.EndDialogAsync(); }
                   }
    }
    

    【讨论】:

    • 感谢您提供解决方案。我是否需要在 OnTurnAsync 或对话框上下文中插入该验证步骤?即使它仍然可以工作,我最初只是想在机器人开始处理消息之前“窥视”外部类中的状态。
    • 我从未尝试在机器人“外部”做类似的事情。我认为它会过于复杂。您不想在机器人内部使用 OnTurnAsync 处理验证的任何特殊原因?机器人框架随时准备进行验证,特别是在 V4 中,每次操作发生时都会循环 OnTurnAsync。
    • 我想知道减少机器人的传入消息可以更轻松地处理所有事情。但是,正如您指出的那样,应用程序似乎很混乱。我会选择你建议的选项。谢谢。
    • 我正在尝试修改我的对话框,但不太了解(languageAccessor)stepContext.Context.Activity.Text 这种情况。这是怎么回事?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    相关资源
    最近更新 更多