赞
踩
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,开启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训练数据如下,intent指划分好的意图(即短文本分类的类),训练数据的格式默认使用Markdown,还可使用JSON格式
## intent:greet
- hey
- hello
- hi
- good morning
- good evening
- hey there
## intent:goodbye
- bye
- goodbye
- see you around
- see you later
对话管理训练数据,由Rasa Code处理
Rasa Code从真实的对话数据中学习,是用户和聊天机器人之间的真实对话。
意图(intent)和实体(entity)反映用户的输入,操作(action)显示助理应如何响应。
一个简单的story:
## story1
* greet
- utter_greet
greet
是用户输入中的意图,utter_greet
是助理响应的操作
Rasa NLU和Rasa Core的配置文件,定义模型使用的NLU和Core组件,如NLU使用的pipeline(传递过程)是supervised_embeddings
,也可以选择其他pipeline
language: en
pipeline: supervised_embeddings
policies:
- name: MemoizationPolicy
- name: KerasPolicy
- name: MappingPolicy
聊天机器人的定义
能够理解哪些意图和实体,用什么对话或自定义动作来响应,在对话过程中应该记住哪些信息,在特定上下文中使用这些信息
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
自定义操作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
实现自然语言理解(即NLU)功能,本质上就是识别句子的意图和实体。
如“买一张去北京的票”,那么可以定义意图是“购票”,实体是“北京”和“一张”。
Rasa NLU主要使用各种开源技术,并没有追求SOTA,包括Spacy
、sklearn-crfsuite
Rasa的核心部分,主要完成基于故事的对话管理,包括解析故事并生成对话系统中的对话管理模型(Dialog Management),输出系统决策(System Action/System Policy)。
这部分包含两个模型:
对于1,Rasa实现很简单,就是简单地基于策略的槽状态替换。
对于2,Rasa使用基于LSTM的排序学习,大体上是将当前轮用户意图、上一轮系统行为、当前槽值状态向量化,然后与所有系统行为做相似度学习,以此决定当前轮次的一个或多个系统行为
Rasa的可视化编辑工具
pipeline定义了输入到输出经过哪些处理,如:
记忆策略只记录训练数据中的对话
若训练数据存在这样的对话,则以置信度1.0预测下一个动作,否则以0.0预测
一般不单独使用
映射策略将意图映射为操作
无视之前对话,一旦触发意图就操作
映射是传递intent属性给triggers
实现的,修改domain.yml
intents:
- ask_is_bot:
triggers: action_is_bot
一般不单独使用
Keras策略使用神经网络预测下一步操作,默认基于LSTM
Rasa的最新技术,在多轮对话中表现比Keras Policy好
与其他RNN机器学习算法不同,它利用transformer学习模式并进行预测。能更好处理不同语料库间的低纠缠,能更好地处理意外的用户输入,如闲聊
表单策略,收集指定信息,如性别年龄地址
需要实现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
回退策略,聊天机器人不可避免需要的回退情况,例如用户问了让机器人理解不了的东西时需要回退
需要提供阈值
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 | 置信度低于阈值要调用的回退操作 |
不直接回退而是让用户选,尝试消除用户输入的歧义,从而在多个阶段处理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格式
UnicodeEncodeError: 'ascii' codec can't encode characters
,entity命名应使用英文test.py
,启动API服务时会运行该文件,可能会报错"
包围起来,特别为了调用Rasa API时。如- payload: "/inform{\"gender\": \"男\"}"
Failed to extract slot xxx with action xxx_form
,可在Stories中添加action_deactivate_form
停止Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。