简介
Rasa是一套开源机器学习框架,用于构建基于上下文的聊天机器人
Rasa有两个主要模块:Rasa NLU用于理解用户消息;Rasa Core用于管理对话
Rasa提供了一套交互工具RasaX,帮助用户部署聊天机器人
安装
pip install rasa-x -i https://pypi.rasa.com/simple
直接pip会报错:pip install rasa-x
Rasa使用TensorFlow2,请谨慎安装。
Rasa需要Python 3.5.3+
Rasa版本1.7到1.8区别较大,具体查看迁移指南
初试
创建项目:rasa init --no-prompt
启动对话:rasa shell
退出:/stop
新一轮对话:/restart
带置信度:rasa shell nlu
Next message:
Hi
{
"intent": {
"name": "greet",
"confidence": 0.9438605904579163
},
"entities": [],
"intent_ranking": [
{
"name": "greet",
"confidence": 0.9438605904579163
},
{
"name": "bot_challenge",
"confidence": 0.023507937788963318
},
{
"name": "deny",
"confidence": 0.015569652430713177
},
{
"name": "mood_unhappy",
"confidence": 0.006939413491636515
},
{
"name": "affirm",
"confidence": 0.004430832341313362
},
{
"name": "mood_great",
"confidence": 0.0033575778361409903
},
{
"name": "goodbye",
"confidence": 0.0023339807521551847
}
],
"text": "Hi"
}
Debug模式:rasa shell --debug
可视化:rasa x
启动Rasa API服务:rasa run --enable-api
允许跨域:rasa run --enable-api --cors "*"
Python调用Rasa API服务(不要命名为test.py)
解析意图
import json
import requests
url = "http://localhost:5005/model/parse"
data = {"text": "hello"}
data = json.dumps(data, ensure_ascii=False)
data = data.encode(encoding="utf-8") # 如果text带中文需要转编码
r = requests.post(url=url, data=data)
print(json.loads(r.text))
结果
{'intent': {'name': 'greet', 'confidence': 0.9930983185768127}, 'entities': [], 'intent_ranking': [{'name': 'greet', 'confidence': 0.9930983185768127}, {'name': 'mood_unhappy', 'confidence': 0.0036425672005861998}, {'name': 'bot_challenge', 'confidence': 0.002293727360665798}, {'name': 'mood_great', 'confidence': 0.00035825479426421225}, {'name': 'goodbye', 'confidence': 0.00032570294570177794}, {'name': 'affirm', 'confidence': 0.00022301387798506767}, {'name': 'deny', 'confidence': 5.849302760907449e-05}], 'text': 'hello'}
进行聊天
import json
import secrets
import requests
def post(url, data=None):
data = json.dumps(data, ensure_ascii=False)
data = data.encode(encoding="utf-8")
r = requests.post(url=url, data=data)
r = json.loads(r.text)
return r
sender = secrets.token_urlsafe(16)
url = "http://localhost:5005/webhooks/rest/webhook"
while True:
message = input("Your input -> ")
data = {
"sender": sender,
"message": message
}
result = post(url, data)
for i in result:
print(i)
启动Action:rasa run actions
其他命令
查看所有命令:rasa -h
交互式运行:rasa interactive
,运行过程中可视化查看到哪一步http://localhost:5006/visualization.html
转换为JSON格式:rasa data convert nlu --data data/nlu.md --out data/nlu.json -f json
前端UI
本人开发了一个前端UI,开启API后即可打开HTML使用,欢迎Star
项目文件
文件 | 用途 |
---|---|
data/nlu.md | Rasa NLU训练数据 |
data/stories.md | 对话管理训练数据 |
models/xxx-xxx.tar.gz | 机器学习模型 |
__init__.py | 帮助查找的空文件 |
actions.py | 自定义操作 |
config.yml | Rasa NLU和Rasa Core的配置文件 |
credentials.yml | 连接到其他服务的信息,如接口证书 |
domain.yml | 聊天机器人的定义 |
endpoints.yml | 对接外部服务的信息,如fb messenger |
nlu.md
部分NLU训练数据如下,intent指划分好的意图(即短文本分类的类),训练数据的格式默认使用Markdown,还可使用JSON格式
## intent:greet
- hey
- hello
- hi
- good morning
- good evening
- hey there
## intent:goodbye
- bye
- goodbye
- see you around
- see you later
stories.md
对话管理训练数据,由Rasa Code处理
Rasa Code从真实的对话数据中学习,是用户和聊天机器人之间的真实对话。
意图(intent)和实体(entity)反映用户的输入,操作(action)显示助理应如何响应。
一个简单的story:
## story1
* greet
- utter_greet
greet
是用户输入中的意图,utter_greet
是助理响应的操作
config.yml
Rasa NLU和Rasa Core的配置文件,定义模型使用的NLU和Core组件,如NLU使用的pipeline(传递过程)是supervised_embeddings
,也可以选择其他pipeline
language: en
pipeline: supervised_embeddings
policies:
- name: MemoizationPolicy
- name: KerasPolicy
- name: MappingPolicy
domain.yml
聊天机器人的定义
能够理解哪些意图和实体,用什么对话或自定义动作来响应,在对话过程中应该记住哪些信息,在特定上下文中使用这些信息
intents:
- greet
templates:
utter_greet:
- text: Hey! How are you?
actions:
- utter_greet
构成 | 含义 |
---|---|
intents | 意图 |
actions | 操作 |
templates | 回答模板 |
entities | 实体 |
slots | 词槽 |
Rasa Core在每一步对话选择正确的操作
示例中的操作是反馈一条消息,聊天机器人会根据templates
返回一条消息
除发消息外,还可构建其他操作,参阅自定义操作
忽略实体
intents:
- greet:
use_entities:
- name
- first_name
ignore_entities:
- location
- age
触发动作
intents:
- greet: {triggers: action_greet}
- bye
- thank
- faq
- contact_sales
- inform
actions:
- action_greet
actions.py
- 官方提供了sdk方便用户编写自定义action
actions.py
自定义操作
from rasa_sdk import Action
from rasa_sdk.events import SlotSet
class ActionAskWeather(Action):
def name(self):
return 'action_ask_weather'
def run(self, dispatcher, tracker, domain):
dispatcher.utter_message(f'您问的天气地点是哪里呢')
return [SlotSet('city', '深圳')]
domain.yml
添加意图、实体、槽位、模板和操作
intents:
- ask_weather
- weather_state
entities:
- city
slots:
city:
type: text
templates:
utter_weather_good:
- text: "{city}天气很好呢"
actions:
- action_ask_weather
- utter_weather_good
nlu.md
添加数据
## intent:ask_weather
- 今天天气怎么样
- 今天天气
## intent:weather_city
- 深圳
stories.md
添加数据
## story_ask_weather
* ask_weather
- action_ask_weather
* weather_city
- utter_weather_good
endpoints.yml
开启服务
action_endpoint:
url: "http://localhost:5055/webhook"
config.yml
设为中文
language: zh
pipeline: tensorflow_embedding
- 重新训练
rasa train
- 启动
rasa shell --endpoints endpoints.yml
训练模型
每当添加新的NLU或Core,或更新domains、config时,都需要重新训练
训练模型:rasa train
数据增强:rasa train --augmentation 20
Rasa组成
1. Rasa NLU
实现自然语言理解(即NLU)功能,本质上就是识别句子的意图和实体。
如“买一张去北京的票”,那么可以定义意图是“购票”,实体是“北京”和“一张”。
Rasa NLU主要使用各种开源技术,并没有追求SOTA,包括Spacy
、sklearn-crfsuite
2. Rasa Code
Rasa的核心部分,主要完成基于故事的对话管理,包括解析故事并生成对话系统中的对话管理模型(Dialog Management),输出系统决策(System Action/System Policy)。
这部分包含两个模型:
- 对话状态跟踪(Dialog State Tracking / Belief Tracking)
- 对话策略(Dialog Policy / Policy Optimization)
对于1,Rasa实现很简单,就是简单地基于策略的槽状态替换。
对于2,Rasa使用基于LSTM的排序学习,大体上是将当前轮用户意图、上一轮系统行为、当前槽值状态向量化,然后与所有系统行为做相似度学习,以此决定当前轮次的一个或多个系统行为
3. Rasa X
Rasa的可视化编辑工具
传递过程
- 用户输入,送入Rasa NLU
- NLU给出结果
- Tracker用于跟踪对话状态,输出Embedding
用户意图的Embedding
上一步系统动作的Embedding
实体的Embedding - Policy输出系统行为
- Tracker记录系统行为,下一次提供给Policy使用
- 返回消息给用户
综合示例
自然语言处理组件
pipeline定义了输入到输出经过哪些处理,如:
词向量
- MitieNLP
- SpacyNLP
- HFTransformersNLP
分词器
- WhitespaceTokenizer:空格分词器
- JiebaTokenizer:结巴分词器
- MitieTokenizer:MITIE分词器
- SpacyTokenizer:spaCy分词器
- ConveRTTokenizer:ConveRT分词器
- LanguageModelTokenizer
特征提取器
- MitieFeaturizer:MITIE特征提取器
- SpacyFeaturizer:spaCy特征提取器
- ConveRTFeaturizer:ConveRT特征提取器
- LanguageModelFeaturizer
- RegexFeaturizer:正则表达式特征提取器
- CountVectorsFeaturizer:词袋模型特征提取器,结合用户消息、意图和响应
- LexicalSyntacticFeaturizer:词法语法特征提取器
意图分类器
- MitieIntentClassifier:MITIE意图分类器
- SklearnIntentClassifier:Sklearn意图分类器
- EmbeddingIntentClassifier:嵌入意图分类器(即将被DIETClassifier替代)
- KeywordIntentClassifier:关键词意图分类器,适合小项目
- DIETClassifier:意图分类和实体提取的双向转换器
实体提取器
- MitieEntityExtractor:MITIE实体提取器
- SpacyEntityExtractor:spaCy实体提取器
- EntitySynonymMapper:同义词匹配实体提取器
- CRFEntityExtractor:条件随机场实体提取器
- DucklingHTTPExtractor:常见实体提取器
- DIETClassifier:意图分类和实体提取的双向转换器
选择器
- ResponseSelector:响应选择器
合并的实体提取器和意图分类器
- DIETClassifier:意图分类和实体提取的双向转换器
对话策略
1. Memoization Policy
记忆策略只记录训练数据中的对话
若训练数据存在这样的对话,则以置信度1.0预测下一个动作,否则以0.0预测
一般不单独使用
2. Mapping Policy
映射策略将意图映射为操作
无视之前对话,一旦触发意图就操作
映射是传递intent属性给triggers
实现的,修改domain.yml
intents:
- ask_is_bot:
triggers: action_is_bot
一般不单独使用
3. Keras Policy
Keras策略使用神经网络预测下一步操作,默认基于LSTM
4. Embedding Policy (TEDP)
Rasa的最新技术,在多轮对话中表现比Keras Policy好
与其他RNN机器学习算法不同,它利用transformer学习模式并进行预测。能更好处理不同语料库间的低纠缠,能更好地处理意外的用户输入,如闲聊
5. Form Policy
表单策略,收集指定信息,如性别年龄地址
需要实现FormAction,在domain.yml
中指定,在stories.md
中使用
from rasa_sdk import Tracker
from rasa_sdk.forms import FormAction
from typing import Dict, Text, Any, List
from rasa_sdk.executor import CollectingDispatcher
class FacilityForm(FormAction):
def name(self) -> Text:
return "facility_form"
@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
return ["facility_type", "location"]
def slot_mappings(self) -> Dict[Text, Any]:
return {"facility_type": self.from_entity(entity="facility_type", intent=["inform", "search_provider"]),
"location": self.from_entity(entity="location", intent=["inform", "search_provider"])}
def submit(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict]:
location = tracker.get_slot('location')
facility_type = tracker.get_slot('facility_type')
dispatcher.utter_button_message("Here is home health agency near you")
return []
forms:
- facility_form
6. Fallback Policy
回退策略,聊天机器人不可避免需要的回退情况,例如用户问了让机器人理解不了的东西时需要回退
需要提供阈值
policies:
- name: FallbackPolicy
nlu_threshold: 0.3
ambiguity_threshold: 0.1
core_threshold: 0.3
fallback_action_name: 'action_default_fallback'
参数 | 含义 |
---|---|
nlu_threshold | 接受的最低置信度 |
ambiguity_threshold | 最高置信度的意图超过第二意图的最小值 |
core_threshold | 进行操作的最低置信度 |
fallback_action_name | 置信度低于阈值要调用的回退操作 |
7. Two-Stage Fallback Policy
不直接回退而是让用户选,尝试消除用户输入的歧义,从而在多个阶段处理NLU可信度较低的问题。
nlu.md和domain.yml意图要有out_of_scope
需要提供阈值
policies:
- name: TwoStageFallbackPolicy
nlu_threshold: 0.3
ambiguity_threshold: 0.1
core_threshold: 0.3
fallback_core_action_name: "action_default_fallback"
fallback_nlu_action_name: "action_default_fallback"
deny_suggestion_intent_name: "out_of_scope"
参数 | 含义 |
---|---|
nlu_threshold | 接受的最低置信度 |
ambiguity_threshold | 最高置信度的意图超过第二意图的最小值 |
core_threshold | 进行操作的最低置信度 |
fallback_core_action_name | 置信度低于core_threshold调用的回退操作,这个动作指出识别的意图 |
fallback_nlu_action_name | 置信度低于nlu_threshold调用的回退操作,当用户第二次拒绝时调用 |
deny_suggestion_intent_name | 用户拒绝的意图的名称 |
验证模型
交叉验证rasa test nlu -u data/nlu.md --config config.yml --cross-validation
2020-01-22 15:18:54 INFO rasa.test - CV evaluation (n=5)
2020-01-22 15:18:54 INFO rasa.test - Intent evaluation results
2020-01-22 15:18:54 INFO rasa.nlu.test - train Accuracy: 1.000 (0.000)
2020-01-22 15:18:54 INFO rasa.nlu.test - train F1-score: 1.000 (0.000)
2020-01-22 15:18:54 INFO rasa.nlu.test - train Precision: 1.000 (0.000)
2020-01-22 15:18:54 INFO rasa.nlu.test - test Accuracy: 0.605 (0.156)
2020-01-22 15:18:54 INFO rasa.nlu.test - test F1-score: 0.584 (0.131)
2020-01-22 15:18:54 INFO rasa.nlu.test - test Precision: 0.622 (0.101)
更多详情查看Evaluating Models
标注工具
下载为JSON格式
槽位类型
- Text:文本
- Boolean:布尔型
- Categorical:多个值中的一个
- Float:浮点数
- List:
- Unfeaturized:不影响对话的数据
中文系统
遇到的坑
- 训练数据JSON格式实体entity为中文,报错
UnicodeEncodeError: 'ascii' codec can't encode characters
,entity命名应使用英文 - 根目录不要有文件
test.py
,启动API服务时会运行该文件,可能会报错 - 项目名不要带中文,启动Rasa X时可能报错
- YAML文件涉及字符串最好用
"
包围起来,特别为了调用Rasa API时。如- payload: "/inform{\"gender\": \"男\"}"
- 一个Form激活时输入了无关数据报错
Failed to extract slot xxx with action xxx_form
,可在Stories中添加action_deactivate_form
停止
官方视频
参考文献
- Rasa Tutorial
- Rasa介绍 对话系统、产品与技术
- rasa对话系统踩坑记
- Rasa使用指南01
- Rasa使用指南02
- Rasa 入坑指南一:初识 Rasa
- Learn how to Build a Chatbot in Minutes using Rasa
- Rasa 入门教程 NLU 系列
- Rasa Masterclass Developing Contextual AI assistants with Rasa tools
- 使用 Rasa NLU 构建一个中文 ChatBot
- 基于rasa的对话系统搭建(上)
- 使用 Rasa 构建天气查询机器人
- 使用rasa构建任务型聊天机器人
- python - How to send POST request?
- NLU server - ParsingError · Issue #4024
- Configuring the HTTP API
- Rasa HTTP API
- Rasa中文聊天机器人开发指南(2):NLU篇
- 默认动作
相关产品
- Wit.ai,自然语言处理接口
- Dialogflow,Google建立自然和丰富的对话体验
- LUIS,Microsoft语言理解
- UNIT,百度智能对话定制与服务平台
- 一个AI,世纪佳缘让对话无处不在