Microsoft Bot Framework начинает диалог с определенного шага водопада в диалоге - PullRequest
0 голосов
/ 21 февраля 2019

Microsoft Bot Framework V4, у меня есть диалоговое окно водопада, определенное в диалоговом окне, как показано ниже

var waterfallSteps = new WaterfallStep[]

        {
            CallConfirmAsync,
            SimilarProductAsync,
            CheckNewVersionAsync,
        };

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

После выполнения первых двух шагов водопада мой разговор останавливается из-за неотзывчивости со стороны пользователя.Поэтому я хочу вернуться к третьему способу, когда, например, CheckNewVersionAsync, когда пользователь снова возвращается к боту.

Может кто-нибудь, пожалуйста, помогите мне здесь.

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Итак, на уровне ботов это должно произойти автоматически, если вы настроили IStatePropertyAccessor<DialogState> с ConversationState.Независимо от того, сколько времени потребуется пользователю, чтобы ответить, ваш WaterfallDialog останется на вершине стека и будет точно помнить, на каком шаге он находился.Предполагая, что ваш пользователь возвращается к тому же разговору, он сразу же продолжит с того места, где остановился.

Учитывая, что тот факт, что вы задаете этот вопрос, приводит меня к мысли, что, возможно, вы используете WebChat, который нене сохраняйте одинаковые значения conversationId при загрузке страниц, если только вы не настроите это самостоятельно.Если это так, то я бы посоветовал вам задать еще один вопрос о том, как это сделать, если вы не можете понять, как, поскольку это отдельная проблема из состояния диалога, сохраняющегося правильно.

0 голосов
/ 21 февраля 2019

Редактировать: Дрю отвечает правильно, но мой дает другое потенциальное решение.Вы можете найти больше информации здесь: Управление государством .В частности:

Состояние пользователя доступно в любой ход, когда бот общается с этим пользователем на этом канале, независимо от диалога. Состояние разговора доступно в любой ход в конкретном разговоре, независимо от пользователя.(т. е. групповые разговоры). Состояние приватного разговора ограничивается как конкретным разговором, так и конкретным пользователем.

Подсказка

Состояние пользователя и разговора ограничено каналом.Один и тот же человек, использующий разные каналы для доступа к вашему боту, выглядит как разные пользователи, по одному для каждого канала, и у каждого из них свое состояние пользователя.

Дополнительное решение

Это решение лучше всего подходит дляесли вы можете указать from Id, но не можете гарантировать, что conversation Id останется прежним (см. ниже, под Gotchas).

Вы можете сохранить, на каком шаге находится пользователь в его UserState.

BasicBot

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; }
    }
}

сделать первый шаг вашего WaterfallDialog:

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();
}

На каждом шаге загружатьcurrent 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();
}

Gotchas

Пара важных вещей, на которые стоит обратить вниманиедля:

  • UserState сохраняется только для тех же from ID и channel ID.Убедитесь, что у пользователя, который выходит посреди водопада, есть тот же from ID при повторном входе в него и что он повторно вводит его с того же канала .Это не значение по умолчанию для эмулятора - в эмуляторе при перезапуске сеанса создается новый from ID.(Примечание. Считайте, что from ID является синонимом User ID. Оно происходит только от Activity.From.Id)

  • ConversationState сохраняется только для тех же conversation ID и channel ID.Постоянство conversation ID в пределах канала зависит от канала.

Дополнительная информация о различных идентификаторах: Поля идентификатора в Bot Framework .

...