Microsoft Bot Framework V4, mam okno dialogowe Wodospad zdefiniowany w oknie dialogowym jak poniżej

var waterfallSteps = new WaterfallStep[]

        {
            CallConfirmAsync,
            SimilarProductAsync,
            CheckNewVersionAsync,
        };

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

Po wykonaniu pierwszych dwóch kroków wodospadu moja rozmowa jest zatrzymana ze względu na nierealizację od końca użytkownika. Więc chcę wznowić z trzeciej metody, gdy I.e. CheckNewversionSync, gdy użytkownik wróci do bota.

Czy ktoś może mi pomóc.

1
Vyshnavi 21 luty 2019, 09:57

2 odpowiedzi

Najlepsza odpowiedź

Edytuj: Odpowiedź Drew jest poprawna, ale mój zapewnia kolejne potencjalne rozwiązanie. Więcej informacji tutaj znajdziesz: Stan zarządzający. W szczególności:

Stan użytkownika jest dostępny w dowolnej kolejce, że bot rozmawia z tym użytkownikiem na tym kanale, niezależnie od konwersacji stanu konwersacji jest dostępny w dowolnym skręcie w określonej rozmowie, niezależnie od użytkowników (tj. Grupowych rozmów) Prywatny stan konwersacji jest zasłonięty do obu konkretna rozmowa i tego konkretnego użytkownika

Wskazówka

Zarówno stan użytkownika, jak i konwersacji są łączone przez kanał. Ta sama osoba używająca różnych kanałów dostępu do bota pojawia się jako różnych użytkowników, jeden dla każdego kanału, a każdy z wyraźnym stanem użytkownika.

Dodatkowe rozwiązanie

To rozwiązanie jest najlepsze, jeśli jesteś w stanie określić from Id, ale nie może zapewnić, że conversation Id pozostaje taka sama (patrz poniżej, pod Gotchas).

Możesz zapisać, jaki krok użytkownik jest włączony w ich UserState.

BasicBot.

Basicbot robi to z jego { {X0}} klasa.

Z jego GreetingDialog:

W pierwszym etapie inicjuje GreetingState, który śledzi, jak daleko w oknie dialogowym użytkownik jest widząc, jakie zmienne użytkownika zostały już ustawione:

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

A następnie w każdym kroku ładuje GreetingState:

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

I sprawdza, czy krok został już zakończony czymś w rodzaju:

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

Jeśli nie ma greetingState lub .Name lub .City, monituje dla nich, a jeśli są już wypełnione, porusza się z:

return await stepContext.NextAsync();

Na każdym kroku zapisuje GreetingState z czymś w rodzaju:

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

Uproszczenie dla każdego przypadku

Dla Ciebie, jeśli nie musisz zapisywać informacji o użytkowniku, możesz utworzyć prostą klasę Step:

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

Wprowadź pierwszy krok dialogu twojego wodospadu:

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

Na każdym kroku załaduj prąd Step:

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

Sprawdź, czy są już obok bieżącego kroku:

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.

Para duże rzeczy do oglądania na:

  • Użytkownicy utrzymuje się tylko za to samo from ID i channel ID. Upewnij się, że użytkownik, który pozostawia w środku wodospadu ma taki sam from ID, kiedy ponownie go wprowadzą i że ponownie wprowadzają go z tego samego Kanał. To nie jest domyślne dla emulatora - w emulatorze, gdy zostanie ponownie uruchomiony sesja, tworzona jest nowa from ID. (Uwaga: Rozważmy from ID, aby być synonimem User ID. Po prostu pochodzi z Activity.From.Id)

  • KonwersacjaState utrzymuje się tylko za to samo conversation ID i channel ID. Wytrwałość conversation ID w kanale zmienia się w zależności od kanału.

Więcej informacji na temat różnych identyfikatorów: Pola ID w ramach bot.

0
mdrichardson 21 luty 2019, 19:39

Tak więc na poziomie botów, to powinno się zdarzyć się automatycznie, jeśli skonfigurowałeś IStatePropertyAccessor<DialogState> za pomocą ConversationState. Bez względu na to, jak długo użytkownik zajmie się odpowiedzią, twój {x2}} pozostanie na szczycie stosu i będziemy pamiętać dokładnie, jaki krok był włączony. Zakładając, że Twój użytkownik wraca do tej samej rozmowy, wtedy wybierze proste, gdzie zostało wyłączone.

Biorąc pod uwagę, że pytanie, że zadasz to pytanie, prowadzi mnie do uwierzenia, że być może używasz WebChat, który nie utrzymuje tego samego conversationId przez obciążenia strony, chyba że tak skonfigurujesz. W takim przypadku, sugerowałbym, że poprosiłeś kolejne pytanie o tym, jak to zrobić, jeśli nie możesz dowiedzieć się, jak to, że jest to osobna kwestia z państwa dialogowego, który jest prawidłowo utrzymywany.

1
Drew Marsh 21 luty 2019, 19:01