人工智能 Rasa Rasa-入门 cmyang 2023-03-09 2023-06-05 1. 聊天机器人简介 聊天机器人,一种通过语音、文字和计算机程序进行交互,模拟人类对话的过程。
相关产品:chatGPT,阿里小蜜,Siri等
分类:闲聊型,FAQ,任务型
1.1 人机交互过程
1.1.1 语音识别 Automatic Speech Recognition(简称:ASR),是一种语音转文字的技术,目前科大讯飞,百度等都有相关的商业解决方案,开源的项目Kaldi
1.1.2 自然语言理解 Natural Language Understanding(简称:NLU),主要用于提取用户说的一句话中,所要表达的意图,和提供的相关信息实体
比如:我要请一天假
通过NLU,转化为,意图:请假,实体:{请假时长:1天}
1.1.3 对话管理 Dialog Management(简称:DM),人机对话的控制中心,在多轮对话中,会根据对话历史推断出当前应该做什么,需要给用户响应什么数据。
比如:
NLU:意图:请假,实体:{请假时长:1天}
DM:要执行请假动作,还缺少实体,请假开始时间,请假类型
NLG:询问用户请假开始时间,请假类型
NLU:识别到用户输入的请假开始时间和类型
DM:调用业务后台API写入请假数据,提示用户请假申请完成
NLG:请假申请提交成功
1.1.4 自然语言生成 Natural Language Generation(简称:NLG),通过模板或者序列生成方式,将数据转换成人类可以识别的文本。可以转换为不同的语言风格和不同国家的语言
1.1.5 语音合成 Text To Speech(简称:TTS),将文字转语音的技术
1.2 机器学习
训练过程:通过给机器人提供对话模板,包含标识对话的意图,对话中包含的实体,对话情景故事等,让机器人通过算法学习,生成模型
机器人:通过加载模型,让机器人知道如何根据模型响应真实用户说的话
算法:解决如何在计算机中表示文本信息,如何为文本建模。比如将文本转化为词向量,word2vec,用一个浅层神经网络,在大规模语料上进行训练,通过每个词语上下文的联系,将文本的语义嵌入一个稠密向量。通过transformer解决上下文不同语义的问题,使用transformer开发模型,BERT,GPT等,GPT-3.5目前chatGPT使用的主要模型,已经能生成质量很高的文本。
2. Rasa简介 官方网站:https://rasa.com/
开源版本文档地址:https://rasa.com/docs/rasa/
github:https://github.com/rasahq/rasa
Rasa 是通过可扩展的对话式 AI 平台,可以构建工业级的聊天机器人,主要解决FAQ和任务型对话,Apache 2.0协议,可商用。截至2020年已经筹集4000多万美元的融资。包含开源的核心包rasa,商业版本:管理后台rasa-x,rasa平台rasa platform
3. Rasa 安装&Demo 3.1 python环境 目前支持 3.7,3.8,3.9,3.10
3.2 运行一个demo
创建rasa-learn项目
创建虚拟环境conda create -n rasa-learn python=3.7
,并切换到rasa-learn
pip安装rasa,最好设置下pip的镜像,加快下载速度
在执行init后
第一个提示,是否创建在当前目录(直接回车)
? Please enter a path where the project will be created [default: current directory]
第二个提示,目录不为空,是否继续(直接回车)
? Directory ‘D:\code\learn\rasa-learn’ is not empty. Continue? (Y/n)
第三个提示,项目初始化完成,是否训练(直接回车)
Created project directory at ‘D:\code\learn\rasa-learn’.
Finished creating project structure.
? Do you want to train an initial model? 💪🏽 (Y/n)
第四个提示,项目训练完后,是否开启对话(直接回车)
Your Rasa model is trained and saved at ‘models\20230318-134634-obsolete-armament.tar.gz’. ? Do you want to speak to the trained assistant on the command line? 🤖 (Y/n)
现在可以开始对话
1 2 3 4 5 6 7 8 9 10 11 2023-03-18 13:51:38 INFO root - Rasa server is up and running. Bot loaded. Type a message and press enter (use '/stop' to exit): Your input -> hi Hey! How are you? Your input -> so perfect Great, carry on! Your input -> are you a bot I am a bot, powered by Rasa. Your input -> /stop 2023-03-18 13:54:37 INFO root - Killing Sanic server now.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 . ├── actions │ ├── __init__.py │ └── actions.py ├── config.yml ├── credentials.yml ├── data │ ├── nlu.yml │ └── stories.yml ├── domain.yml ├── endpoints.yml ├── models │ └── <timestamp>.tar.gz └── tests └── test_stories.yml
4. Rasa命令
命令
影响
rasa init
使用示例训练数据、操作和配置文件创建一个新项目。
rasa train
使用您的 NLU 数据和故事训练模型,将训练后的模型保存在./models
.
rasa interactive
通过与您的助手聊天,开始交互式学习会话以创建新的训练数据。
rasa shell
加载经过训练的模型并让您在命令行上与您的助手交谈。
rasa run
使用经过训练的模型启动服务器。
rasa run actions
使用 Rasa SDK 启动一个动作服务器。
rasa visualize
生成故事的视觉表示。
rasa test
在任何以test_
.
rasa data split nlu
对您的 NLU 训练数据执行 80/20 拆分。
rasa data convert
在不同格式之间转换训练数据。
rasa data migrate
将 2.0 域迁移到 3.0 格式。
rasa data validate
检查域、NLU 和对话数据是否存在不一致。
rasa export
将对话从跟踪器存储导出到事件代理。
rasa evaluate markers
从现有跟踪器存储中提取标记。
rasa -h
显示所有可用命令。
5. 构建一个请假机器人 5.1 需求
通过构建一个请假机器人,来认识rasa的各个组件,机器人支持FAQ,和请假任务
创建一个机器人的过程
使用rasa init
初始化项目
编写NLU数据
编写回应数据
编写form
编写规则
编写故事
训练模型
测试模型
5.2 初始化项目
创建一个bot-leave的项目
安装依赖
pip install rasa
pip install jieba
rasa init初始化项目
5.3 编写NLU数据 Rasa NLU负责意图提取和实体提取。比如:我想请一天假,NLU会提取意图:请假,实体:时长一天,如下编写一个请假需要的NLU数据,写在nlu.yml中
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 version: "3.1" nlu: - intent: greet examples: | - hello - hi - 你好 - intent: goodbye examples: | - 再见 - 拜拜 - bye - intent: faq/how_to_leave examples: | - 怎么请假 - 如何请假 - 我想请个假该怎么做 - 请假需要做什么 - intent: faq/leave_type examples: | - 有哪些请假类型 - 我可以请哪些假 - 支持的请假类型有哪些 - intent: faq/leave_flow examples: | - 怎么查看请假审批进程 - 请假进度 - 请假审批进度 - 在哪看请假进度 - intent: leave examples: | - 帮我请个假 - 我想请[一天](duration)假 - 帮我请[一周](duration)假 - 我要请[三天](duration)假 - [今天](begin_time)我要请[一天](duration)假 - [10月9号](begin_time)我要请[一天](duration)假 - 我需要请[半天](duration)[事假](leave_type) - 帮我请[1天](duration)[病假](leave_type) - [后天](begin_time)我想请[一天](duration)[年假](leave_type) - 从[明天](begin_time)开始请[2天](duration)[年假](leave_type) - [6月1号](begin_time)帮我请[一天](duration)[调休假](leave_type) - intent: info_begin_time examples: | - [今天](begin_time) - [明天](begin_time) - [后天](begin_time) - [6月10号](begin_time) - [3月2号](begin_time) - [7月1号](begin_time) - [3月3日](begin_time) - [12月25日](begin_time) - intent: info_duration examples: | - [1天](duration) - [一天](duration) - [两天](duration) - [三天](duration) - [半天](duration) - [一周](duration) - intent: info_leave_type examples: | - [事假](leave_type) - [病假](leave_type) - [婚假](leave_type) - lookup: leave_type examples: | - 事假 - 病假 - 年假 - 婚假 - 调休假 - 育儿假 - 呱呱假 - synonym: "0.5" examples: | - 半天 - synonym: "1" examples: | - 1天 - 一天 - synonym: "2" examples: | - 两天 - 二天 - synonym: "3" examples: | - 三天 - 3天 - synonym: "7" examples: | - 七天 - 一周
intent表示意图
examples列举了一些提供给机器学习的样本
intent分为两种
faq/xxx,该意图表示问答类型,faq名字可以随意更换,xx/xxx,主要是提供了同一类型的意图,通用的学习处理方式,不用每个意图都去设置规则或者故事
不带/的意图,普通的意图,意图的示例样本中,可以标记实体,让机器学习,标记的方式[xxx](实体类型)
lookup:查找表,当你在训练数据中提供查找表时,该表的内容将组合成一个大的正则表达式。此正则表达式用于检查每个训练样本,以查看它是否包含查找表中词条的匹配项。
synonym:同义词,通过将提取的实体映射到一个值而非提取的文字来规范化训练数据
5.4 编写回应数据和表单 5.4.1 固定响应数据和表单 响应数据,主要编写机器人应该如何回复用户,
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 version: "3.1" intents: - greet - goodbye - leave - info_begin_time - info_duration - info_leave_type entities: - begin_time - duration - leave_type slots: begin_time: type: any mappings: - type: from_entity entity: begin_time duration: type: any mappings: - type: from_entity entity: duration leave_type: type: any mappings: - type: from_entity entity: leave_type responses: utter_default: - text: "对不起,我没有明白您在说什么,请换个说法重试" utter_greet: - text: "你好,我是一个请假机器人" utter_goodbye: - text: "再见,感谢您的使用" utter_faq/how_to_leave: - text: "我可以帮您请假呦,您可以这样讲,帮我请一天假" utter_faq/leave_type: - text: "您可以请:事假、病假、年假、婚假、育儿假、调休假、呱呱假" utter_faq/leave_flow: - text: "对不起,系统暂时不支持查询请假流程,请登录员工考勤系统查看审批进程哦,我们会尽快完善功能" utter_ask_begin_time: - text: "请输入请假开始时间" utter_ask_duration: - text: "您要请多长时间" utter_ask_leave_type: - text: "请选择您要请假的类型" buttons: - title: "事假" payload: '/info_leave_type{{"leave_type":"事假"}} ' - title: "病假" payload: '/info_leave_type{{"leave_type":"病假"}} ' - title: "年假" payload: '/info_leave_type{{"leave_type":"年假"}} ' - title: "婚假" payload: '/info_leave_type{{"leave_type":"婚假"}} ' - title: "育儿假" payload: '/info_leave_type{{"leave_type":"育儿假"}} ' - title: "调休假" payload: '/info_leave_type{{"leave_type":"调休假"}} ' - title: "呱呱假" payload: '/info_leave_type{{"leave_type":"呱呱假"}} ' actions: - action_leave forms: leave_form: required_slots: - begin_time - duration - leave_type session_config: session_expiration_time: 60 carry_over_slots_to_new_session: true
回复数据写在domain.yml中,主要包含以下内容:
intents:定义所有的意图
entities:定义所有用到的实体
slots:插槽,槽内的值可以让机器人知道之前的对话里,用户提供了哪些关键信息
responses:给用户回复的模板,定义了机器人回复用户的内容,可以包含,文本,图片,按钮,富文本等信息
actions:定义了所有的自定义动作,应为我们要处理任务,比如提交一个请假数据,单靠机器人是无法做到的,这时候就需要结合我们的提交接口去完成,actions中可以编写我们自己的业务代码,完成业务逻辑处理。
forms:表单,定义完成某项任务必须要收集到的用户数据,在没有收集完数据前,机器人会循环询问用户所需要的参数,比如请假,需要请假开始时间,请假时长,请假类型,三个参数,如果一开始用户说“我要请一天假“,之提供了时长,这时候,机器人就会问用户,什么时候开始请假,请什么假来收集数据
5.4.2 自定义响应 我们需要通过自定义动作来实现业务逻辑处理,通过实现Action类的方法,来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from typing import Any , Text, Dict , List from rasa_sdk import Action, Trackerfrom rasa_sdk.executor import CollectingDispatcherclass ActionLeaveWorld (Action ): def name (self ) -> Text: return "action_leave" def run (self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict [Text, Any ] ) -> List [Dict [Text, Any ]]: begin_time = tracker.get_slot("begin_time" ) duration = tracker.get_slot("duration" ) leave_type = tracker.get_slot("leave_type" ) print (f"请假参数信息,开始时间:{begin_time} , 时长:{duration} ,类型:{leave_type} " ) dispatcher.utter_message(text=f"您从{begin_time} 开始,为期{duration} 天的{leave_type} 申请已提交,请关注审批进度" ) return []
name表示响应的名称,要和domain中定义的名称一致
run中编写业务代码
5.5 编写规则 规则,就是机器人接受到用户发送的某个意图后,不管在什么情况,都会按照固定的方式响应用户。编写在rules.yml中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 version: "3.1" rules: - rule: FAQ steps: - intent: faq - action: utter_faq - rule: activate leave form steps: - intent: leave - action: leave_form - active_loop: leave_form - rule: submit form condition: - active_loop: leave_form steps: - action: leave_form - active_loop: null - action: action_leave
rule定义了每一条规则
steps定义了一个固定的用户对话情景步骤
intent收到用户的意图
action机器人该如何响应该意图
该配置文件定义了3条规则
faq规则
因为FAQ的模式是固定的,就是一问一答,不需要考虑上下文语境
表单开始规则
定义了,一旦收到用户发起请假申请的意图,就会自动开启请假表单,并且开始收集表单需要的参数
表单提交规则
定义了,在开启leave_form表单的条件下,一旦所有参数收集完成(active_loop: null),就提交表单(action_leave)
5.6 编写故事 一个故事就是一个剧本,故事可让机器人知道如何响应用户的请求,正常完成一个任务,需要哪些步骤来完成,怎么引导用户完成任务,故事是可以让机器进行学习的,机器学习完成后,可以一定程度上泛化这个故事,不用把每一种场景都写成一个故事。故事写在stories.yml中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 version: "3.1" stories: - story: happy path steps: - intent: greet - action: utter_greet - intent: leave - action: leave_form - active_loop: leave_form - intent: faq - action: utter_faq - action: leave_form
该故事,编写了一种场景,用户在和机器人打招呼后,发起请假流程,正常情况,机器人会收集3个参数,并完成表单提交,但是有一种场景,机器人在收集参数的过程中,用户并没有回答机器人收集的参数,而是提了一个faq的问题,比如,机器人提示,请问您需要请什么假,这时候用户提了一个问题,有哪些请假类型,机器人需要先回答用户的问题,再接着收集参数,这种场景,就需要单独编写一个故事,在form中插入faq的意图。
5.7 训练数据 首先,需要添加配置,在config.yml中,language 和 pipeline 指定模型用于NLU预测的组件。policies 定义模型用于预测下一步动作的策略。
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 recipe: default.v1 assistant_id: 20230604 -204819 -obliging-stave language: zh pipeline: - name: JiebaTokenizer token_pattern: (?u)\b\w+\b dictionary_path: "data/" - name: RegexFeaturizer - name: LexicalSyntacticFeaturizer - name: CountVectorsFeaturizer OOV_token: oov - name: CountVectorsFeaturizer analyzer: char_wb min_ngram: 1 max_ngram: 4 - name: DIETClassifier epochs: 200 ranking_length: 5 - name: EntitySynonymMapper - name: RegexEntityExtractor use_word_boundaries: false use_lookup_tables: true use_regexes: true - name: ResponseSelector epochs: 100 retrieval_intent: faq - name: FallbackClassifier threshold: 0.7 policies: - name: RulePolicy core_fallback_threshold: 0.3 core_fallback_action_name: "action_default_fallback" enable_fallback_prediction: true - max_history: 6 name: AugmentedMemoizationPolicy - name: TEDPolicy max_history: 10 epochs: 40 batch_size: - 32 - 64
这里每一个name都是训练模型需要经过的一个组件,其中主要分为以下几块
分词器,这里使用中文的 Jieba 分词器
文本特征化器:主要返回特征向量
意图分类器:提取意图
实体提取器:提取实体
选择器:FAQ
这些组件可以根据具体的情况进行更换,rasa对这些基础的算法做了集成和封装,极大的简化了非专业人员入手机器人的门槛。
5.8 其他修改 5.8.1 开启自定义动作服务器 在endpoints.yml中,配置动作服务器的地址
1 2 action_endpoint: url: "http://localhost:5055/webhook"
5.8.2 开启websocket 这里通过一个页面来访问写好的机器人,在 credentials.yml 文件中配置websocket
1 2 3 4 socketio: user_message_evt: user_uttered bot_message_evt: bot_uttered session_persistence: false
5.8.3 编写一个访问页面 该前端页面使用了开源的项目rasa-webchat(https://github.com/botfront/rasa-webchat)进行构建。
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 27 28 29 30 31 32 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Demo for bot</title > </head > <body > <script > !(function ( ) { let e = document .createElement ("script" ), t = document .head || document .getElementsByTagName ("head" )[0 ]; (e.src = "https://cdn.jsdelivr.net/npm/rasa-webchat@1.x.x/lib/index.js" ), (e.async = !0 ), (e.onload = () => { window .WebChat .default ( { customData : { "language" : "en" }, socketUrl : "http://127.0.0.1:5005" , socketPath : "/socket.io" , title : "请假机器人" , initPayload : "hi" }, null ); }), t.insertBefore (e, t.firstChild ); })(); </script > </body > </html >
5.9 启动项目 5.9.1 训练模型 打开终端,输入:rasa train
,训练完成可以看到类似信息
1 Your Rasa model is trained and saved at 'models\20230604-223615-numerous-dune.tar.gz'.
5.9.2 启动rasa 在终端中输入:rasa run --cors "*"
,启动完成后,可以看到如下日志信息
1 2023-06-04 22:57:20 INFO root - Rasa server is up and running.
5.9.3 启动自定义动作服务 新开一个终端,输入:rasa run actions
,启动完成,可以看到如下日志信息
1 2023-06-04 21:35:43 INFO rasa_sdk.endpoint - Action endpoint is up and running on http://0.0.0.0:5055
5.9.4 启动web服务器 新开一个终端,输入:python -m http.server,启动完成,可以看到如下日志信息
1 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
注意:总共需要3个终端分别启动3个服务
5.9.5 在浏览器访问 现在可以在浏览器输入:http://localhost:8000/ 来体验机器人