浅读Rasa3.2.5源码(rasa train、rasa shell)

article/2025/9/19 18:58:34

目录

  • 浅读Rasa3.2.5源码(rasa train、rasa shell)
    • 一、 分析 __main__.py
      • (1). 解析main.py的部分代码
      • (2). rasa常用命令
    • 二、 训练阶段
      • (1). 准备训练数据
      • (2). 跟踪模型训练
        • 1. 从配置文件和参数中构造有向无环图
        • 2. 运行有向无环图,这是模型实际进行训练和持久化的过程
      • (3). 返回模型文件路径
    • 三、 推理阶段
      • (1). 建立connector,对外提供访问接口
      • (2). 从磁盘载入模型:rasa/core/agent.py
      • (3). 处理用户消息
    • 四、思维导图
    • 五、 结语

浅读Rasa3.2.5源码(rasa train、rasa shell)

你好,这里写这篇文章的原因是因为想要探究两个问题:
1、 终端执行rasa shell命令并出现交互界面后,rasa在此之前做了哪些工作?
2、 当用户发出消息后,rasa如何根据该消息执行动作?
本文主要记录了一些关于rasa train和rasa shell 的浅显见解:
(同时参考了孔晓泉大佬出版的《rasa实战》并使用了部分图表,如有不妥,立即删除)

一、 分析 main.py

(1). 解析main.py的部分代码

首先rasa会创建一个rasa命令的解析器,这包含了所有子指令(如shell、run等)的子解析器,确保你在终端输入的具体指令可以被及时执行。

#   创建一个命令解析器
def create_argument_parser() -> argparse.ArgumentParser:"""Parse all the command line arguments for the training script."""parser = argparse.ArgumentParser(prog="rasa",formatter_class=argparse.ArgumentDefaultsHelpFormatter,description="Rasa command line interface. Rasa allows you to build ""your own conversational assistants 🤖. The 'rasa' command ""allows you to easily run most common commands like ""creating a new bot, training or evaluating models.",)#   创建一条子命令 rasa --versionparser.add_argument("--version",action="store_true",default=argparse.SUPPRESS,help="Print installed Rasa version",)parent_parser = argparse.ArgumentParser(add_help=False)add_logging_options(parent_parser)parent_parsers = [parent_parser]subparsers = parser.add_subparsers(help="Rasa commands")#   为子命令创建子解析器,为了可以指定具体参数执行#   如rasa train 、 rasa shellscaffold.add_subparser(subparsers, parents=parent_parsers)run.add_subparser(subparsers, parents=parent_parsers)shell.add_subparser(subparsers, parents=parent_parsers)train.add_subparser(subparsers, parents=parent_parsers)interactive.add_subparser(subparsers, parents=parent_parsers)telemetry.add_subparser(subparsers, parents=parent_parsers)test.add_subparser(subparsers, parents=parent_parsers)visualize.add_subparser(subparsers, parents=parent_parsers)data.add_subparser(subparsers, parents=parent_parsers)export.add_subparser(subparsers, parents=parent_parsers)x.add_subparser(subparsers, parents=parent_parsers)evaluate.add_subparser(subparsers, parents=parent_parsers)return parser

(2). rasa常用命令

命令功能
rasa init创建一个新的项目,包含样本训练模型、配置和动作
rasa train使用NLU训练数据、故事数据和配置训练模型,默认情况下模型保存在/models目录中
rasa interactive交互式的训练:通过和机器人对话修正可能的错误,并将对话数据导出
rasa run运行Rasa 服务器
rasa shell等价于执行rasa run命令,开启基于命令行界面的对话界面和机器人交流
rasa run actions运行Rasa动作服务器
rasa x启动RasaX服务器(如果没有安装RasaX的话会提示安装吗,并且RasaX是与Rasa适配,版本不匹配,会无法使用 1
rasa -h打印 Rasa命令的帮助信息

二、 训练阶段

训练阶段是执行了rasa train命令。即运行了/rasa/cli/train.py文件。
/rasa/cli/train.py
从源码看出,rasa train 也可以只单独训练nlu 或者 core 部分,并有相应的训练函数。

# 为 rasa train 再创建一个子命令解析器train_subparsers = train_parser.add_subparsers()# '''add_parser:为 rasa train 添加指定命令 core'''train_core_parser = train_subparsers.add_parser("core",parents=parents,conflict_handler="resolve",formatter_class=argparse.ArgumentDefaultsHelpFormatter,help="Trains a Rasa Core model using your stories.",)train_core_parser.set_defaults(func=run_core_training)  ## 添加训练core的函数(rasa train core)# '''add_parser:为 rasa train 添加指定命令 nlu'''train_nlu_parser = train_subparsers.add_parser("nlu",parents=parents,formatter_class=argparse.ArgumentDefaultsHelpFormatter,help="Trains a Rasa NLU model using your NLU data.",)train_nlu_parser.set_defaults(func=run_nlu_training)  ## 添加训练nlu的函数(rasa train nlu)

(1). 准备训练数据

从源码可以看出参与训练的数据只有data文件夹、domain.yml和config.yml文件。

def run_training(args: argparse.Namespace, can_exit: bool = False) -> Optional[Text]:"""Trains a model.Args:args: Namespace arguments.can_exit: If `True`, the operation can send `sys.exit` in the casetraining was not successful.Returns:经过训练的模型的路径,如果训练不成功,则为“无”Path to a trained model or `None` if training was not successful."""##  train: rasa.api.train()from rasa import train as train_all# 可以指定路径,否则就默认路径# get_validated_path:检查路径是否存在并且合理domain = rasa.cli.utils.get_validated_path(args.domain, "domain", DEFAULT_DOMAIN_PATH, none_is_valid=True)config = _get_valid_config(args.config, CONFIG_MANDATORY_KEYS)training_files = [rasa.cli.utils.get_validated_path(f, "data", DEFAULT_DATA_PATH, none_is_valid=True)for f in args.data]## ---------读到此处就可以知道rasa train只需要data、config和domain文件------------------

(2). 跟踪模型训练

事实上,模型训练的主要函数是rasa/model_training.py的track_model_training()。

1. 从配置文件和参数中构造有向无环图

	# 将配置转换为与图形兼容的模型配置# 构造有向无环图model_configuration = recipe.graph_config_for_recipe(config,kwargs,training_type=training_type,is_finetuning=is_finetuning,)

2. 运行有向无环图,这是模型实际进行训练和持久化的过程

	trainer.train(model_configuration,file_importer,full_model_path,force_retraining=force_full_training,is_finetuning=is_finetuning,)

(3). 返回模型文件路径

训练的模型一般就保存到/models文件夹下。

return self._model_storage.create_model_package(output_filename, model_configuration, domain)

三、 推理阶段

代码位置:rasa/cli/shell.py
rasa shell 也可以只测试nlu部分,来帮助我们测试nlu样本部分,看能否正确识别用户的意图。
即rasa shell nlu。

shell_nlu_subparser = run_subparsers.add_parser("nlu",parents=parents,conflict_handler="resolve",formatter_class=argparse.ArgumentDefaultsHelpFormatter,help="Interprets messages on the command line using your NLU model.",)

可以看到,rasa shell 实际上是等价于rasa run的。在shell函数里,最终是启动了run函数。

# rasa shell nluif metadata.training_type == TrainingType.NLU:import rasa.nlu.runtelemetry.track_shell_started("nlu")rasa.nlu.run.run_cmdline(model)# rasa shell# 其实 rasa shell 等价于 rasa runelse:import rasa.cli.runtelemetry.track_shell_started("rasa")rasa.cli.run.run(args)

接下来的推理阶段主要在rasa/core/run.py: serve_application()函数中

(1). 建立connector,对外提供访问接口

在rasa shell中指定connector为 cmdline,这样用户就可以通过命令行与rasa进行交互。如果不在命令行而在其他客户端进行交互的话,我们就需要在credentials中配置新的connector。比如自己建造的网站、微信或者嵌入在一些软件上等等,而载入connector的函数代码在create_http_input_channels()中。

    if not channel and not credentials:channel = "cmdline"# 第一步:将channel指定为cmdline# 正在连接到由“--connector”参数指定的通道“cmdline”。任何其他通道都将被忽略。要连接到所有给定的通道,请省略 '--connector' 参数。input_channels = create_http_input_channels(channel, credentials)

(2). 从磁盘载入模型:rasa/core/agent.py

从源码中可以看出有三种不同的方式加载已训练的模型:

1、从云存储(如 S3)获取模型
2、从自己的 HTTP 服务器获取模型
3、从本地磁盘加载模型

默认情况下,Rasa 的 CLI 的所有命令都将从本地磁盘加载模型。具体信息可以参考Rasa官方文档。2

        try:if model_server is not None:return await load_from_server(agent, model_server)elif remote_storage is not None:agent.load_model_from_remote_storage(model_path)elif model_path is not None and os.path.exists(model_path):try:agent.load_model(model_path)except ModelNotFound:rasa.shared.utils.io.raise_warning(f"No valid model found at {model_path}!")else:rasa.shared.utils.io.raise_warning("No valid configuration given to load agent. ""Agent loaded with no model!")return agent

(3). 处理用户消息

首先要说一下在rasa/core/agent.py里有一个重要的Agent类,它是rasa里的重要接口,包含了加载模型、处理消息等的重要功能。我们在实例化Agent的时候会同时实例化它的处理器processor,processor是与机器人的通信的接口。在这个过程中,processor会从磁盘中加载模型并还原成推理所用的有向无环图。核心代码在rasa/core/processor.py的load_predict_graph_runner()函数中。

当用户通过客户端向指定的connector发送消息到rasa服务器(实际上,connector应该是rasa服务器的 接口),然后rasa服务器就会处理用户消息返回响应消息到客户端。从逻辑上讲,这个处理过程应该是先由Rasa NLU解析消息传递到Rasa Core来决定合适的动作执行。核心代码是processor中定义的hand_message()方法。

    async def handle_message(self, message: UserMessage) -> Optional[List[Dict[Text, Any]]]:"""Handle a single message with this processor."""# 处理UserMessage类返回的用户消息# 对用户消息作NLU的预处理# log_message:运行推理的有向无环图,得到NLU的结果# 这些NLU的结果会更新tracker的状态tracker = await self.log_message(message, should_save_tracker=False)# 如果是执行rasa shell nluif self.model_metadata.training_type == TrainingType.NLU:await self.save_tracker(tracker)rasa.shared.utils.io.raise_warning("No core model. Skipping action prediction and execution.",docs=DOCS_URL_POLICIES,)return None# 如果是执行rasa shell# run_action_extract_slots:根据slot 的配置映射更新tracker的状态tracker = await self.run_action_extract_slots(message.output_channel, tracker)# 把tracker的状态作为输入,通过有向无环图推理得到新的tracker,得到目的tracker状态# 并根据目的tracker状态执行动作,但是执行动作可能会带来新的tracker状态# 重复过程,直到满足条件await self._run_prediction_loop(message.output_channel, tracker)# 保存tracker状态# 这个tracker的状态决定了bot是选择继续倾听还是继续执行动作await self.save_tracker(tracker)if isinstance(message.output_channel, CollectingOutputChannel):return message.output_channel.messagesreturn None

从源码中读到,在用户消息经过UserMessage类的处理后传入handle_message()中,首先经过log_message()方法的处理。这个方法实际上就是Rasa NLU在工作,先根据“sender_id”来获得当前会话的tracker,再根据tracker得到用户消息来进行NLU解析,并按需求保存tracker。

    async def log_message(self, message: UserMessage, should_save_tracker: bool = True) -> DialogueStateTracker:"""Log `message` on tracker belonging to the message's conversation_id.在属于该消息的对话ID的tracker上记录消息Optionally save the tracker if `should_save_tracker` is `True`. Tracker savingcan be skipped if the tracker returned by this method is used for furtherprocessing and saved at a later stage.如果'should_save_tracker'为'True',则可以选择保存跟踪器。如果此方法返回的跟踪器用于其他用途,则可以跳过跟踪器保存处理并在稍后阶段保存"""# 得到当前会话的trackertracker = await self.fetch_tracker_and_update_session(message.sender_id, message.output_channel, message.metadata)await self._handle_message_with_tracker(message, tracker)# 是否保存trackerif should_save_tracker:await self.save_tracker(tracker)return tracker

然后执行run_action_extract_slots()和_run_prediction_loop()方法。

前者从tracker中获取解析过的用户消息来填充slots,填充slots的时候,slots会将消息中的实体映射成需要的实体,并更新tracker的值(关于slots的具体内容可以参考Rasa官方文档 3)。比如用户询问“今天长沙的天气如何?”,这里通过NLU解析可以提取出“今天”,“长沙”的实体值,然后该函数会通过slots的配置将提取到的实体值映射到如“datetime”,“address”的词槽,只有满足了这两个词槽,Rasa才能执行查询天气的动作。

后者将这个tracker作为有向无环图的输入,预测下一步执行的动作并执行这一动作,但是这个过程中可能会重复并带来新的tracker状态,直到满足停止条件。最后保存tracker,并倾听等待下一用户消息。

		# run_action_extract_slots:根据slot 的配置映射更新tracker的状态tracker = await self.run_action_extract_slots(message.output_channel, tracker)# 把tracker的状态作为输入,通过有向无环图推理得到新的tracker,得到目的tracker状态# 并根据目的tracker状态执行动作,但是执行动作可能会带来新的tracker状态# 重复过程,直到满足条件await self._run_prediction_loop(message.output_channel, tracker)# 保存tracker状态await self.save_tracker(tracker)

四、思维导图

事实上,在Rasa3中NLU和Core的界限不在清晰,但是为了理解,我仍然画成了两个部分。
思维导图

五、 结语

事实上,本文只是从宏观层面解析了模型训练和用户消息传入Rasa服务器的处理过程,具体细节仍未展开剖析,一些东西也是点到为止。接下来的时间我会从NLU和Core的处理过程展开研究,同时记录思路过程,也请阅者批评斧正。


  1. RasaX版本适配图表 ↩︎

  2. Rasa官方文档之模型存储 ↩︎

  3. Rasa官方文档之slots ↩︎


http://chatgpt.dhexx.cn/article/G1JtGHG1.shtml

相关文章

2.rasa架构

rasa架构 消息处理 此图显示了使用Rasa构建的助手如何响应消息的基本步骤: 这些步骤分别是: 1. 收到消息并将其传递给解释器(Interpreter),解释器将其转换为包含原始文本,意图和找到的任何实体的字典。这部分由NLU处理。 2. 跟踪…

Rasa -流程

Rasa入门笔记1 -流程 一、Rasa是什么二、Rasa工作流程 一、Rasa是什么 Rasa是一个nlp开源机器学习框架,用于构建问答与多轮对话机器人。 二、Rasa工作流程 Rasa分为两个模块NLU模块与Core模块,NLU 一>用于提取意图与实体,Core一>用于…

Rasa-X 部署

Rasa-X 部署(docker版) 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明,违反必究。 本文链接:https://blog.csdn.net/junxing2018_wu/article/details/106638599 说明: do…

Rasa系列教程(二) -- Rasa NLU基础

目录 前言 一、训练数据 1.1 意图字段(intent) 1.2 同义词字段(synonym) 1.3 查找表字段(lookup) 1.4 正则表达式字段(regex) 1.5 查找表和正则表达式的使用 二、组件 2.1 …

RASA框架介绍

关于RASA一个机器学习框架,用于构建基于文本和语音的聊天机器人。框架完整,可扩展性,易用性高,高效灵活。2.0新版本统一训练数据格式,配置文件和模型处理方式。 在最新版的rasa里已经集成了bert模型和xlnet&#xff0c…

rasa的使用

文章目录 rasa的使用一. 安装二. 创建一个简单的语音助手三、命令行四 rasa整体流程参考 rasa的使用 一. 安装 rasa有NLU和core两个模块,可以使用pip全部安装,默认是基于tensorflow2.1版本的 直接使用pip安装 # 创建一个python是3.6.8的环境 conda cr…

Rasa

Rasa NLU是一种开源自然语言处理工具,用于聊天机器人中的意图分类和实体提取;主要是理解用户意图,配合rasa_core使用可以实现AI对话。 参考文献 Rasa介绍 对话系统、产品与技术by清华 Rasa开发使用 Rasa_NLU及Rasa_Core模型训练与测试by冰蓝 …

Rasa使用指南02

转载请注明出处,原文地址 Rasa使用指南01 前言 最近工作很忙,重心也一直在模型方面,例如BERT、GPT-2等等,对于Rasa系列的博文实在是没有时间更新。最近有不停的收到一些小伙伴发来的信息,希望能看到Rasa使用指南02&…

rasa - http api测试

rasa - http api测试 rasa run --enable-api --cors "*" 仅解析意图 请求地址:localhost:5005/model/parse 命令行 curl -X POST localhost:5005/model/parse -d ‘{“text”: “hello”}’ 代码示例 import json import requestsurl "http://…

rasa 介绍文档

重磅推荐专栏: 《Transformers自然语言处理系列教程》 手把手带你深入实践Transformers,轻松构建属于自己的NLP智能应用! 1. Rasa介绍 1.1 架构 Rasa Open Source: NLU (理解语义) Core (决定对话中每一步执行的actions)Rasa SDK: Action …

Rasa 问答

开发一个智能对话系统用什么工具? Rasa是Conversational AI在智能业务对话领域工程落地全球最为成功对话机器人系统,是基于Transformer架构的全球使用最广泛的智能业务对话机器人框架,是NLP技术的集大成者。在当今全球范围各项对比指标综合成…

Rasa Core开发指南

文章目录 1. Rasa Core简介1.1 Rasa Core消息处理流程1.2 安装Rasa Core 2. Dialogue模型训练2.1 Story样本数据2.2 Domain2.2.0 intents2.2.1 actions2.2.2 templates2.2.3 entities2.2.4 slots 3 .训练和使用对话模型3.1 训练对话模型3.2 使用对话模型 4. 搭建CustomActions服…

Rasa使用指南01

转载请注明出处,原文地址: https://terrifyzhao.github.io/2018/09/17/Rasa%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%9701.html Rasa使用指南02 前言 本文内容基于Rasa官网文档,做了翻译与整理,并添加一些自己的理解,方便…

Rasa安装

下载 Rasa https://download.csdn.net/download/Da___Vinci/12404001 Rasa-x https://download.csdn.net/download/Da___Vinci/12403992 安装 找个位置存放,cd到那个目录执行安装,注意你的pip版本,我的是3.7,如果装了多个pyhon&#xf…

RASA介绍

引言 自然语言是人类表达情感、观念的主要工具和人类思维的重要载体,而最常见的自然语言应用场景则是对话。人们希望通过自然语言控制机器,甚至实现机器与人类的对话与交流。使用自然语言作为输入输出的媒介,会使用户获得更自然友好的人机交互…

关于Rasa你必须要知道的几件事

关于Rasa你必须要知道的几件事 1、为什么选择Rasa 2、Understanding the Rasa NLU Pipeline 3、Components in Rasa 4、DIET in Rasa 5、Dialogue Management in Rasa 2.0 6、TED Policy in Rasa 本文从一个high-level的角度对使用Rasa构建聊天助手的整个过程进行了总结&#x…

Rasa系列教程(一) -- 系统及各组件介绍

目录 前言 一、传统对话机器人架构 二、对话系统流程 2.1 ASR语音识别 2.2 NLU自然语言理解 2.3 DM对话管理 2.4 NLG自然语言生成 2.5 TTS语音合成 三、Rasa组件介绍 3.1 Rasa简介 3.2 Rasa安装 3.3 Rasa项目基本流程 3.4 Rasa常用命令 3.4 Rasa常用命令 ​​​​…

数据治理-数据标准

问题导读1.为什么要做数据标准管理?2.生产变更的标准管理主要解决了哪些问题?3.变更通知谁(影响范围)?4.业务元数据的标准管理主要解决了哪些问题? 一、为什么要做数据标准管理 数据治理的问题并不仅仅只…

数据治理效果差?掌握正确治理方法,解决企业数据问题

数字化时代,数据已经成为构建现代化社会的重要元素,也深深扎根于商业世界,成为无数企业经营管理中悉心培养的”明珠“。 然而,这些宝贵的数据是需要有人来照料、培养的,如果企业没有完善的数据治理方案,就…

数据治理要点

目录 数据治理-ods治理前言-确定表主键数据治理-行政区划数据治理-字段拆分数据治理-必去的脏数据数据治理-全角转半角 已经在公司待了有一段时间了,自己也亲身接触和实践了一些项目,最近发现自己一直没有进步,想了想或许是自己一直没有反思总…