Остановка бесконечного диалогового цикла - PullRequest
2 голосов
/ 29 мая 2019

Короче говоря, я хочу знать, как остановить многострочный пример на цикле git-репозитория Microsoft навсегда.

Я просматривал документацию по V4 и не могу найти здесь ничего, намекающего на решение.

Microsoft опубликовала пример использования диалогового окна с несколькими подсказками, доступного здесь: https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/05.multi-turn-prompt

Если вы клонируете и запускаете, действие выполняется следующим образом:

Вы: отправить сообщение

бот: отвечает открытием диалога

Вы: ответьте на диалог

бот: переход к следующему шагу диалога

....

продолжается до последнего шага при запуске

return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);

Бот отправляет последнее сообщение в шагах водопада и ждет другого сообщения от пользователя. Еще раз, когда пользователь отправляет любое сообщение, бот снова активирует диалоговое окно «Водопад».

Очевидно, что из-за этого метода в DialogBot.cs каждый раз, когда пользователь отправляет сообщение, бот переходит в диалог.

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            Logger.LogInformation("Running dialog with Message Activity.");

            // Run the Dialog with the new message Activity.
            await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
        }

Я хочу остановить это и запустить диалоговое окно только один раз, диалоговое окно не должно активироваться снова, как только диалоговое окно завершается в первый раз.

1 Ответ

0 голосов
/ 31 мая 2019

Внимательно посмотрите на образец 45.state-management из репозитория Botbuilder-Samples.Он демонстрирует, как вы можете ссылаться на установленное значение в состоянии, чтобы определить поток диалога.Также было бы полезно прочитать документ «Сохранить данные пользователя и беседы», расположенный по адресу здесь .

Короче говоря, вам нужно будет выполнить следующее:

В файле Startup.cs добавьте следующее.Будьте готовы к настройке в соответствии с вашими потребностями.

public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            // Create the credential provider to be used with the Bot Framework Adapter.
            services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();

            // Create the Bot Framework Adapter with error handling enabled. 
            services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

            // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.) 
            services.AddSingleton<IStorage, MemoryStorage>();

            // Create the User state. 
            services.AddSingleton<UserState>();

            // Create the Conversation state. 
            services.AddSingleton<ConversationState>();

            // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
            services.AddTransient<IBot, StateManagementBot>();
        }
    }

В вашем файле "bot.cs" сделайте следующее.Опять же, это пример, так что с учетом ваших потребностей.Сначала установите объекты состояния (_conversationState, _userState).Как только это будет сделано, вы можете установить и вызвать значения состояния в соответствии с диалоговым потоком, используя эти значения, чтобы помочь выполнить следующее действие.В этом примере на состояние ссылаются, чтобы определить, нужно ли снова запрашивать имя пользователя или нет.

namespace Microsoft.BotBuilderSamples
{
    public class StateManagementBot : ActivityHandler
    {
        private BotState _conversationState;
        private BotState _userState;

        public StateManagementBot(ConversationState conversationState, UserState userState)
        {
            _conversationState = conversationState;
            _userState = userState;
        }

        public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            await base.OnTurnAsync(turnContext, cancellationToken);

            // Save any state changes that might have occured during the turn.
            await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
        }

        protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            await turnContext.SendActivityAsync("Welcome to State Bot Sample. Type anything to get started.");
        }

        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            // Get the state properties from the turn context.

            var conversationStateAccessors =  _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
            var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

            var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
            var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile());

            if (string.IsNullOrEmpty(userProfile.Name))
            {
                // First time around this is set to false, so we will prompt user for name.
                if (conversationData.PromptedUserForName)
                {
                    // Set the name to what the user provided.
                    userProfile.Name = turnContext.Activity.Text?.Trim();

                    // Acknowledge that we got their name.
                    await turnContext.SendActivityAsync($"Thanks {userProfile.Name}. To see conversation data, type anything.");

                    // Reset the flag to allow the bot to go though the cycle again.
                    conversationData.PromptedUserForName = false;
                }
                else
                {
                    // Prompt the user for their name.
                    await turnContext.SendActivityAsync($"What is your name?");

                    // Set the flag to true, so we don't prompt in the next turn.
                    conversationData.PromptedUserForName = true;
                }
            }
            else
            {
                // Add message details to the conversation data.
                // Convert saved Timestamp to local DateTimeOffset, then to string for display.
                var messageTimeOffset = (DateTimeOffset) turnContext.Activity.Timestamp;
                var localMessageTime = messageTimeOffset.ToLocalTime();
                conversationData.Timestamp = localMessageTime.ToString();
                conversationData.ChannelId = turnContext.Activity.ChannelId.ToString();

                // Display state data.
                await turnContext.SendActivityAsync($"{userProfile.Name} sent: {turnContext.Activity.Text}");
                await turnContext.SendActivityAsync($"Message received at: {conversationData.Timestamp}");
                await turnContext.SendActivityAsync($"Message received from: {conversationData.ChannelId}");
            }
        }
    }
}

Таким образом, вы можете отслеживать, посетил ли пользователь конкретный диалог.,Если значение равно true, то диалоговое окно пропускается, и пользователь перенаправляется.Надеюсь на помощь!

...