对话框将其变量值保留在MS BotFramework v4中的新对话中

如何解决对话框将其变量值保留在MS BotFramework v4中的新对话中

我正在使用MS BotFramework v4。有一个RootDialogDialog_ADialog_B开头,具体取决于用户输入的内容。

TL; DR

如果在对话之后开始新的对话并且机器人没有重新启动,则已经为其分配了值(不是初始值)的对话框的私有变量不会重置为初始值,从而导致意外行为。如何避免这种情况?

详细

让我们假设以下情况: 这些对话框中的每一个都有一些私有变量来控制是输出长介绍消息还是简短介绍消息。长对话框仅应在第一次启动此对话框时输出。如果对话再次到达对话框,则只应打印短消息。

实现看起来像这样:

RootDialog.cs

public class RootDialog : ComponentDialog
{
    private bool isLongWelcomeText = true;
    // Some more private variables follow here

    public RootDialog() : base("rootId") {
        AddDialog(new WaterfallDialog(nameof(WaterfallDialog),new WaterfallStep[] {
            WelcomeStep,DoSomethingStep,FinalStep
        });
    }

    private async Task<DialogTurnContext> WelcomeStep(WaterfallStepContext ctx,CancellationToken token) {
        if(isLongWelcomeText) {
            await ctx.SendActivityAsync(MessageFactory.Text("A welcome message and some detailed bla bla about the bot"));
            isLongWelcomeText = false;
        } else {
            await ctx.SendActivityAsync(MessageFactory.Text("A short message that hte bot is waiting for input"));
        }
    }

    private async Task<DialogTurnContext> DoSomethingStep(WaterfallStepContext ctx,CancellationToken token) {
        // call Dialog_A or Dialog_B depending on the users input
        // Dialog X starts
        await ctx.BeginDialogAsync("Dialog_X",null,token);
    }

    private async Task<DialogTurnContext> FinalStep(WaterfallStepContext ctx,CancellationToken token) {
        // After dialog X has ended,RootDialog continues here and simply ends
        await ctx.EndDialogAsync(null,token);
    }
}

Dialog_ADialog_B的结构相同。

问题

如果漫游器处理了第一次对话,则一切都会按预期进行(将长欢迎文本显示给用户,并且isLongWelcomeText中的false设置为WelcomeStep。新的对话(新的对话ID和用户ID)isLongWelcomeText仍设置为false,这会导致漫游器将新对话中的简短欢迎文本输出给新用户。

在BotFramework v3中,对话框与所有变量值一起被序列化和反序列化。

如果我对BF v4的要求正确,对话框将不再序列化。

问题

如何解决?有更好的方法吗?

备注

我正在使用UserStateConversationState,它们已序列化并在新对话中重置。但是我不想在状态下存储每个对话框的每个私有变量值。这不是要走的路。

感谢advace

解决方法

通常,您应该将其视为将实例成员变量放入对话框类的错误。在某些情况下它可能会起作用,但是这些情况不会涉及尝试在转弯之间保持某种状态。使用您的bot类的任何类型的内存变量来保持转弯之间的状态存在三个主要问题:

  1. 范围不正确。这是您已经注意到的问题。您已经明确地将isLongWelcomeText定义为特定于用户和/或对话的内容,但是由于它是在您自己的机器人内存中用于处理每个用户的每次对话,因此它无法区分不同的对话和用户。
  2. 它无法正确扩展。这意味着,即使您的机器人只是在一次对话中与一个用户交谈,如果该机器人部署在某些托管服务(如Azure)中,也可以横向扩展,然后将多个您的机器人实例可能正在运行。机器人的不同实例将具有不同的内存,因此,如果您要正确地设计机器人,则需要采取行动,好像每个回合都将由完全不同的机器人实例(也许是在完全不同的服务器上)进行处理。一个实例无法访问另一实例的内存。
  3. 应用重新启动时,它将会丢失。即使您只有一个用户,一个对话,一个机器人实例,您仍然希望能够停止您的漫游器,然后在不破坏对话的情况下再次启动它。如果您正在使用漫游器的内存,则无法这样做。

后两个问题甚至在您使用MemoryStorage时也适用,而不仅仅是在使用内存中变量时。您可能已经猜到解决方案是使用漫游器状态(并且在部署漫游器时将漫游器状态连接到MemoryStorage以外的其他存储类)。

您是正确的,在v3中,对话框类的整个实例对象将被序列化为持久状态。这带来了自己的问题,并且并不总是合乎逻辑,因此在v4中,要序列化的对象是DialogInstance对象。 (了解有关对话框实例here的信息)。您想让对话框保持跟踪的所有内容,都应放入关联的对话框实例的状态对象,而查看如何执行此操作的示例的最佳位置是SDK源代码本身。例如,您可以看到waterfall dialog如何跟踪诸如其自定义值之类的内容以及其执行的步骤:

// Update persisted step index
var state = dc.ActiveDialog.State;
state[StepIndex] = index;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-