聊天机器人项目中将状态管理数据存储到数据库中
分类: Azure机器人 ◆ 标签: #Azure Bot Framework SDK #Azure Bot Service #机器人 ◆ 发布于: 2023-08-07 23:12:13

我们之前学习过了Bot Framework SDK
提供的状态管理组件,以及状态管理在Dialog
中的应用,如果您想了解什么是状态管理,您可以参考文章:https://www.azuredeveloper.cn/article-how-to-manage-chat-bot-status-base-azure-bot-framework, 从文章中可以看到,SDK
默认情况下仅仅提供了两种外部存储支持:
- 存放在内存中:
MemoryStorage
是我们的类。 - 存放在
Azure Storage
中,这又要求我们必须有Azure Storage
的账户。
有没有办法将这些状态数据存储到本地的存储机制上呢?例如关系型数据库?
要解决这个问题,要么自己实现IStore
要么可以使用现成的由开源社区开发的库:https://github.com/BotBuilderCommunity/botbuilder-community-dotnet/tree/develop/libraries/Bot.Builder.Community.Storage.EntityFramework, 这个库利用EF Core
来将状态保存在SQL Server
里,但是很不幸,这个库已经没有人维护了,已经无法在高于.Net 6
的项目上使用了,为了解决这个问题,我将这个库fork
了一次,并且修复了它的问题,您可以从这里找到这个库:
你可以将这个库clone
到您的本地,然后在项目中引用这个project
, 然后开始使用就好了。
使用方法
最重要的是先从我的fork
中clone
代码到你本地,然后在自己的项目中添加引用。
然后启动你的数据库,使用文档:https://github.com/hylinux/botbuilder-community-dotnet/tree/develop/libraries/Bot.Builder.Community.Storage.EntityFramework 创建库和表。
之后可以根据文档:https://www.azuredeveloper.cn/article/create-full-function-chat-bot-template, 创建一个项目模板,最后打开Program.cs
, 使用如下的方式引用:
var ConnectString = builder.Configuration["StoreConnectionString"]; var storage = new EntityFrameworkStorage(ConnectString); var TranscriptStorageLogger = new EntityFrameworkTranscriptStore(ConnectString); builder.Services.AddSingleton<IStorage>(storage); builder.Services.AddSingleton<UserState>(new UserState(storage)); builder.Services.AddSingleton<ConversationState>(new ConversationState(storage)); builder.Services.AddSingleton<ITranscriptStore>(TranscriptStorageLogger);
变量定义:
"StoreConnectionString": "Server=ServerName\\DBInstanceName;Database=botdb;User Id=sa;Password=password1;Trusted_Connection=True;",
如果要使用Transcript
自动存储,还需要更改Adapter
类:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace Microsoft.Bot.Builder.Adapters.WeChat { public class WeChatAdapterWithErrorAndTranscriptLoggerHandler : WeChatHttpAdapter { public WeChatAdapterWithErrorAndTranscriptLoggerHandler( ITranscriptStore transcriptLogger, WeChatSettings settings, IStorage storage, IBackgroundTaskQueue taskQueue, ILogger<WeChatAdapterWithErrorAndTranscriptLoggerHandler> logger, ConversationState conversationState, UserState userState, WeChatClient chatClient) : base(settings, storage, taskQueue, logger, chatClient) { Use(new TranscriptLoggerMiddleware(transcriptLogger)); OnTurnError = async (turnContext, exception) => { // Log any leaked exception from the application. logger.LogError($"Exception caught : {exception.Message}"); // Send a catch-all apology to the user. await turnContext.SendActivityAsync("Sorry, it looks like something went wrong."); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError($"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } }; Use(new AutoSaveStateMiddleware(conversationState, userState)); } } }
以上是一个Adapter
类,其中最重要的是两句:
Use(new TranscriptLoggerMiddleware(transcriptLogger));
使用Transcript
自动保存的中间件.Use(new AutoSaveStateMiddleware(conversationState, userState));
, 使用自动保存状态的中间件。
到这里你就可以将状态存储到外部的各种关系型数据库了。