如何在嵌套对话框中处理状态并配置cosmos db存储? (bot framewrok v4) [英] How to handle state and configure cosmos db storage in a nested dialog? (bot framewrok v4)

查看:63
本文介绍了如何在嵌套对话框中处理状态并配置cosmos db存储? (bot framewrok v4)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用嵌套对话框构建聊天机器人,该对话框应该从用户那里收集信息并将其存储在Azure CosmosDB中.在我实现Cosmos DB存储之前,该对话框运行良好.现在,使用CosmosDB存储,对话框将在第一个对话框中的第一个任务上循环,而不是继续.我该如何解决这个问题?

I am trying to build a chatbot with nested dialogs which is supposed to gather information from the user and store it in Azure CosmosDB. The dialog worked fine until I implemented the Cosmos DB storage. Now, with the CosmosDB storage the dialog loops on the first task in the first dialog, instead of continuing. How can I solve this problem?

从对话框开始,以及在实现CosmosDB存储之前的状态.我基本上遵循此样本 43中的代码.复杂对话框.

Beginning with the dialogs, and how it was before implementing CosmosDB storage. I basically followed the code in this sample 43.complex-dialog.

然后,实现我使用的存储此答案作为指导.我在Startup.cs中设置了cosmosDB存储,如下所示:

Then, implementing the storage I used this answer as a guide. I set up the cosmosDB storage in Startup.cs like this:

public class Startup
    {

        private const string CosmosServiceEndpoint = "MyCosmosServiceEndpoint";
        private const string CosmosDBKey = "MyCosmosDBKey";
        private const string CosmosDBDatabaseName = "MyCosmosDBDatabaseName";
        private const string CosmosDBCollectionName = "MyCosmosDBCollectionName";
        private const string CosmosDBPartitionKey = "MyCosmosDBPartitionKey";
        
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;    
        }
        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            var storage = new CosmosDbStorage(new CosmosDbStorageOptions
            {
                AuthKey = CosmosDBKey,
                CollectionId = CosmosDBCollectionName,
                CosmosDBEndpoint = new Uri(CosmosServiceEndpoint),
                DatabaseId = CosmosDBDatabaseName,
                PartitionKey = CosmosDBPartitionKey
            });

            var conversationState = new ConversationState(storage);
            var userState = new UserState(storage);

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
            services.AddSingleton<MainDialog>();
            services.AddTransient<IBot, WelcomeBot<MainDialog>>();
            services.AddSingleton<IStorage, MemoryStorage>();
            services.AddSingleton(userState);
            services.AddSingleton(conversationState);
            services.AddSingleton(userState.CreateProperty<UserProfile>("MyUserState"));
            services.AddSingleton(conversationState.CreateProperty<DialogState>("MyBotDialogState"));

        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseDefaultFiles();
            app.UseStaticFiles();

            app.UseMvc();
        }
    }
}

我的主要bot看起来像这样(不要在意"Echobot"的名字):

My main bot looks like this (don't mind the name "Echobot"):

public class EchoBot<T> : ActivityHandler where T : Dialog
    {
        private readonly BotState _userState;
        private readonly BotState _conversationState;
        private readonly Dialog _dialog;
        private readonly ILogger _logger;

        private readonly IStatePropertyAccessor<UserProfile> _userStateAccessor;
        private readonly IStatePropertyAccessor<DialogState> _conversationDialogStateAccessor;

        // Create cancellation token (used by Async Write operation).
        public CancellationToken CancellationToken { get; private set; }

        public EchoBot(ConversationState conversationState, UserState userState, T dialog, ILogger<EchoBot<T>> logger, IStatePropertyAccessor<UserProfile> userStatePropertyAccessor, IStatePropertyAccessor<DialogState> dialogStatePropertyAccessor) 
        {
            _conversationState = conversationState;
            _userState = userState;
            _dialog = dialog;
            _logger = logger;
            _userStateAccessor = userStatePropertyAccessor;
            _conversationDialogStateAccessor = dialogStatePropertyAccessor;

        }

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

            var currentUserState = await _userStateAccessor.GetAsync(turnContext, () => new UserProfile(), cancellationToken);
            var currentConversationDialogState = await _conversationDialogStateAccessor.GetAsync(turnContext, () => new DialogState(), cancellationToken);

            await _userStateAccessor.SetAsync(turnContext, currentUserState, cancellationToken);
            await _conversationDialogStateAccessor.SetAsync(turnContext, currentConversationDialogState, 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 OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken=default)
        {
            _logger.LogInformation("Running dialog with Message Activity.");
            //See DialogExtension.cs in the sample "complex-dialog" to see the Run method.
            await _dialog.Run(turnContext, _conversationDialogStateAccessor, cancellationToken);

        }
    }
}

推荐答案

现在,如果您从CosmosDbStorageOptions中删除PartitionKey参数,它应该可以工作.由于您的容器当前已分区,因此您可能需要删除您的容器或使用其他名称.最简单的方法就是删除您的容器,然后让机器人为您创建一个容器.

For now, it should work if you remove the PartitionKey parameter from CosmosDbStorageOptions. You will likely need to delete your Container or use a different name, since yours is currently partitioned. Easiest to just delete your Container and let the bot make one for you.

提供了partitionKey时,所有Bot Builder SDK当前都存在一个读取分区数据库中的错误. 在此处跟踪问题

There's currently a bug in all the Bot Builder SDKs around reading from partitioned databases when the partitionKey is supplied. Tracking the issue here

这篇关于如何在嵌套对话框中处理状态并配置cosmos db存储? (bot framewrok v4)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆