• 报时机器人的rasa shell执行流程分析


      本文以报时机器人为载体,介绍了报时机器人的对话能力范围、配置文件功能和训练和运行命令,重点介绍了rasa shell命令启动后的程序执行过程。

    一.报时机器人项目结构

    1.对话能力范围

    (1)能够识别欢迎语意图(greet)和拜拜意图(goodbye)
    (2)能够识别时间意图(query_time)
    (3)能够识别日期意图(query_date)
    (4)能够识别星期几意图(query_weekday)

    2.配置文件功能

    (1)nlu.yml:主要包含意图、例子、对实体的标注等。
    (2)stories.yml文件:用户和机器人之间对话的表示,用户输入意图,机器人响应action。
    (3)actions.py:自定义的action,比如action_query_time、action_query_date、action_query_weekday。
    (4)config.yml:主要包含nlu(分词、特征提取和分类等)和dialog policy(记忆、规则、机器学习等)。
    (5)domain.yml:主要包含意图、视图、槽位、响应、动作等。
    (6)credentials.yml:主要和其它对话平台集成,比如facebook、slack等。
    (7)endpoints.yml:action_endpoint(调用自定义action)、tracker_store对话存储(内存、redis、mongodb等)、event_broker消息队列(RabbitMQ、Kafka等)。

    3.训练和运行命令

    (1)训练模型
    使用NLU数据和stories训练模型,模型保存在./models中。

    rasa train
    
    • 1

    说明:关于如何把数据集按照比例拆分为训练集和测试集,在训练集上训练模型,在测试集上测试模型,可以参考《聊天机器人框架Rasa资源整理》。
    (2)启动action服务器
    使用Rasa SDK开启action服务器。

    rasa run actions
    
    • 1

    (3)启动rasa服务器和客户端
    通过命令行的方式加载训练模型,然后同聊天机器人进行对话。

    rasa shell
    
    • 1

    二.rasa shell执行流程分析

      整体思路是通过rasa shell加载和解析模型,通过消息处理的方式建立起用户(客户端)和聊天机器人(rasa服务)对话的桥梁。

    1.rasa/cli/shell.py文件

      在rasa/cli/shell.py文件中,def shell(args: argparse.Namespace) -> None函数如下:

    2.rasa/cli/run.py文件

      在rasa/cli/run.py文件中,def run(args: argparse.Namespace) -> None函数如下:

    3.rasa/api.py文件

      在rasa/api.py文件中,def run(...) -> None函数如下:

      在run()函数中调用serve_application()函数如下:

    4.rasa/core/run.py文件

      在rasa/core/run.py文件中,serve_application()函数如下:

      在serve_application()函数中启动了一个基于Sanic的Web服务器,通过configure_app()方法构建了app,然后通过run()方法启动,如下所示:

    app = configure_app(
            input_channels,
            cors,
            auth_token,
            enable_api,
            response_timeout,
            jwt_secret,
            jwt_method,
            port=port,
            endpoints=endpoints,
            log_file=log_file,
            conversation_id=conversation_id,
            use_syslog=use_syslog,
            syslog_address=syslog_address,
            syslog_port=syslog_port,
            syslog_protocol=syslog_protocol,
            request_timeout=request_timeout,
        )
    ......    
    app.run(
            host=interface,
            port=port,
            ssl=ssl_context,
            backlog=int(os.environ.get(ENV_SANIC_BACKLOG, "100")),
            workers=number_of_workers,
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

      通过register_listener(listener, event)注册给定事件的侦听器:

    app.register_listener(partial(load_agent_on_start, model_path, endpoints, remote_storage), "before_server_start",)
    app.register_listener(close_resources, "after_server_stop")
    
    • 1
    • 2

    5.rasa/core/agent.py文件

      通过load_agent_on_start()方法加载一个agent。在rasa/core/agent.py文件中,load_agent()函数如下所示:

      在load_agent()函数中,加载模型代码是agent.load_model(model_path)。在Agent类的def load_model()方法中,关于初始化MessageProcessor代码如下:

    self.processor = MessageProcessor(
        model_path=model_path,
        tracker_store=self.tracker_store,
        lock_store=self.lock_store,
        action_endpoint=self.action_endpoint,
        generator=self.nlg,
        http_interpreter=self.http_interpreter,
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    加载模型的代码如下:

    logger.info(f"Loading model {model_tar}...")
    with tempfile.TemporaryDirectory() as temporary_directory:
        try:
            metadata, runner = loader.load_predict_graph_runner(
                Path(temporary_directory),
                Path(model_tar),
                LocalModelStorage,
                DaskGraphRunner,
            )
            return os.path.basename(model_tar), metadata, runner
        except tarfile.ReadError:
            raise ModelNotFound(f"Model {model_path} can not be loaded.")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.rasa/engine/loader.py文件

      在rasa/engine/loader.py文件中,def load_predict_graph_runner()函数如下:

    三.遇到的问题和说明

    1.如何用PyCharm调试Rasa项目

    解析:一种是基于Script path的调试方法,一种是基于Module name的调试方法。这里介绍前者如下所示:

    (1)Script Path:安装rasa类库的__main__.py文件路径。
    (2)Parameters:rasa的各种cli,比如train、test、shell等。
    (3)Working directory:安装rasa类库的根目录。
    说明:因为rasa类库依赖类库太多导致系统环境混乱,所示建议使用虚拟环境进行rasa类库安装。

    2.NoConsoleScreenBufferError

    解析:exception=NoConsoleScreenBufferError(‘No Windows console found. Are you running cmd.exe?’)

    3.模型20220915-081548-honest-yield.tar.gz

    解析:由metadata.json文件和components文件夹组成,后者和config.yml内容密切相关,如下所示:

    4.Sanic框架

    解析:Sanic是一个高性能异步的Web框架。

    5.asyncio库

    解析:它的编程模型是一个消息循环,关键字涉及event_loop、coroutine、task、future、async/await等。

      本文只是简要的介绍了rasa shell命令启动后的程序执行过程,但是对于加载模型后如何解析模型构建图,以及用户输入后,消息如何通过模型(nlu和dialog policy)得到输出并没有介绍,后面写篇文章专门介绍。

    参考文献:
    [1]Rasa实战:构建开源对话机器人
    [2]Sanic官方文档:https://www.osgeo.cn/sanic/
    [3]asyncio库异步I/O:https://docs.python.org/3.7/library/asyncio.html
    [4]聊天机器人框架Rasa资源整理

  • 相关阅读:
    java特种兵读书笔记(3-5)——java程序员的OS之OOM
    C++系列赋值运算符重载
    C++函数重载
    使用目标之间的先验关系提升目标检测器性能
    Spring注入bean的常用的六种方式
    冒泡排序概览(java+R_优化以及双向冒泡代码)
    K8S集群进行分布式负载测试
    PTA之SQL训练题
    【驱动开发】控制stm32mp157a开发板三盏灯的亮灭
    Spring事件Event详解
  • 原文地址:https://blog.csdn.net/shengshengwang/article/details/134355282