背景
为了展示Rasa聊天机器人的使用效果以及如何将Rasa应用到业务系统中(这里将Python Turtle模块作为业务系统),用户将语音或者文本输入至Rasa,经过处理后调用Python Turtle的功能。
turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行的路径上绘制了图形。
前进功能实现
效果
Rasa聊天机器人控制Python Turtle
配置意图、训练数据、标记实体
nlu.yml
- intent: forward
examples: |
- 前进
- 前进一下
- 向前进
- 向前进一下
- 前进[50](distance)
- 前进[30](distance)像素
- 前进[200](distance)像素
- 向前走[25.5](distance)
- 往前移动[39.0](distance)像素
- 往前挪[39.0](distance)像素
- [1号](turtle_no)乌龟前进
- 向前进[二号](turtle_no)乌龟
- [11号](turtle_no)乌龟前进[200](distance)像素
- [五号](turtle_no)乌龟向前走[25.5](distance)
- [9号](turtle_no)乌龟往前移动[39.0](distance)像素
- 往前挪[39.0](distance)像素[六号](turtle_no)小乌龟
- 乌龟[1](turtle_no)前进
- 向前进乌龟[二](turtle_no)
- 乌龟[11](turtle_no)前进[200](distance)像素
- 乌龟[五](turtle_no)向前走[25.5](distance)
- 乌龟[9](turtle_no)往前移动[39.0](distance)像素
- 往前挪[39.0](distance)像素小乌龟[六](turtle_no)
- 定义’forward’意图、增加示例数据、标记实体
domain.yml
intents:
- forward
entities:
- distance
- turtle_no
slots:
s_turtle_no:
type: text
mappings:
- type: from_entity
entity: turtle_no
s_distance:
type: float
influence_conversation: false
mappings:
- type: from_entity
entity: distance
responses:
...省略...
forms:
...省略...
- 在intents中增加意图’forward’
- 在entities中增加实体’distance’ ‘turtle_no’
- 在slots中增加slot(插槽)‘s_turtle_no’ ‘s_distance’,并设置类型、mapping
配置回复和动作
domain.yml
intents:
...省略...
entities:
...省略...
slots:
...省略...
responses:
utter_forwrad_success:
- text: 前进完成
utter_forwrad_fail:
- text: 前进失败,{turtleno}号小乌龟不存在
forms:
...省略...
actions:
- action_forward
- 在responses中配置文本回复
- 在actions中配置动作即函数
- 可以在action_forward函数中直接将文本’前进完成’输出,也可以配置到responses下,然后在action_forward函数中输出
utter_forwrad_success
或者utter_forwrad_fail
,这样有利于复用
编写对话脚本
stories.yml
- story: turtle forward
steps:
- intent: forward
- action: action_forward
- 将意图(通过用户输入推断出意图)和动作(由bot执行一个函数)连接起来构成单轮对话
action.py函数定义
class ActionForward(Action):
def name(self) -> Text:
return "action_forward"
def run(self, dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
slots = {"s_turtle_no":None,"s_distance":None}
if len(g_TurtleDict) == 0:
t = Util.create_new_turtle()
g_TurtleDict[0] = t
'''
1. s_distance s_turtle_no 都没有指定
2. s_turtle_no 指定了
3. s_distance 指定了
4. s_distance s_turtle_no 都指定了
'''
isSuccess = True
turtle_no = "" # 去掉xx号后的xx
sturtle_no = tracker.get_slot('s_turtle_no')
sdistance = tracker.get_slot('s_distance')
if sturtle_no == None and sdistance == None:
for t in g_TurtleDict.values():
t.forward(MOVE_STEP)
# mainloop()
elif sturtle_no != None and sdistance == None:
turtle_no = Util.get_real_turtle_no(sturtle_no)
if turtle_no in g_TurtleDict.keys():
g_TurtleDict[turtle_no].forward(MOVE_STEP)
# mainloop()
else:
isSuccess = False
dispatcher.utter_message(response="utter_forwrad_fail",turtleno=turtle_no)
elif sturtle_no == None and sdistance != None:
for t in g_TurtleDict.values():
t.forward(float(sdistance))
# mainloop()
else:
turtle_no = Util.get_real_turtle_no(sturtle_no)
if turtle_no in g_TurtleDict.keys():
g_TurtleDict[turtle_no].forward(float(sdistance))
# mainloop()
else:
isSuccess = False
dispatcher.utter_message(response="utter_forwrad_fail",turtleno=turtle_no)
if isSuccess == True:
dispatcher.utter_message(response="utter_forwrad_success")
return [SlotSet(slot,value) for slot,value in slots.items()]
- 获取slot:
s_turtle_no
和s_distance
的值,明确用户指定哪个小乌龟前进以及前进像素数 - 调用turtle库
forward
函数执行前进动作
运行turtle demo功能实现
效果
配置意图、训练数据、标记实体
nlu.yml
- intent: show_turtledemo
examples: |
- 展示小乌龟的demo
- demo
- turtle demo
- turtledemo
- show demos
- run demos
- 展示小乌龟的能力
- intent: select_turtledemo
examples: |
- bytedesign
- chaos
- clock
- 定义’show_turtledemo’意图、增加示例数据
- 定义’select_turtledemo’意图、增加示例数据,该意图用于回复Button格式数据,详见下节
domain.yml
intents:
- select_turtledemo
- show_turtledemo
entities:
...省略...
slots:
...省略...
responses:
...省略...
forms:
...省略...
actions:
...省略...
配置form
domain.yml
intents:
...省略...
entities:
- demo_type
slots:
s_demo_type:
type: text
influence_conversation: true
mappings:
- type: from_entity
entity: demo_type
conditions:
- active_loop: turtle_demo_form
responses:
...省略...
forms:
turtle_demo_form:
required_slots:
- s_demo_type
actions:
...省略...
- 首先在domain.yml中forms中配置form名称:
turtle_demo_form
,需要的slot:s_demo_type
- 在entities中配置实体
demo_type
,用于标识想运行的demo - 在s_demo_type中配置slot
s_demo_type
,用户输入包含实体demo_type
后,将s_demo_type
赋值,并且只有在turtle_demo_form
激活时才为s_demo_type
赋值
配置form要求的slot回复和动作
domain.yml
intents:
...省略...
entities:
...省略...
slots:
...省略...
responses:
utter_ask_turtle_demo_form_s_demo_type:
- buttons:
- title: bytedesign
payload: /select_turtledemo{{"demo_type":"bytedesign"}}
- title: chaos
payload: /select_turtledemo{{"demo_type":"chaos"}}
- title: clock
payload: /select_turtledemo{{"demo_type":"clock"}}
- title: colormixer
payload: /select_turtledemo{{"demo_type":"colormixer"}}
- title: flyobjs
payload: /select_turtledemo{{"demo_type":"flyobjs"}}
- title: forest
payload: /select_turtledemo{{"demo_type":"forest"}}
- title: fractalcurves
payload: /select_turtledemo{{"demo_type":"fractalcurves"}}
- title: lindenmayer
payload: /select_turtledemo{{"demo_type":"lindenmayer"}}
- title: minimal_hanoi
payload: /select_turtledemo{{"demo_type":"minimal_hanoi"}}
- title: nim
payload: /select_turtledemo{{"demo_type":"nim"}}
- title: paint
payload: /select_turtledemo{{"demo_type":"paint"}}
- title: peach
payload: /select_turtledemo{{"demo_type":"peach"}}
- title: penrose
payload: /select_turtledemo{{"demo_type":"penrose"}}
- title: planet_and_moon
payload: /select_turtledemo{{"demo_type":"planet_and_moon"}}
- title: rosette
payload: /select_turtledemo{{"demo_type":"rosette"}}
- title: round_dance
payload: /select_turtledemo{{"demo_type":"round_dance"}}
- title: sorting_animate
payload: /select_turtledemo{{"demo_type":"sorting_animate"}}
- title: trees
payload: /select_turtledemo{{"demo_type":"trees"}}
- title: two_canvases
payload: /select_turtledemo{{"demo_type":"two_canvases"}}
- title: yinyang
payload: /select_turtledemo{{"demo_type":"yinyang"}}
text: 请选择想要运行的demo
forms:
...省略...
actions:
- action_run_demo
- 在responses中配置回复
utter_ask_turtle_demo_form_s_demo_type
,规则如下utter_ask_
表示要求用户输入文本,turtle_demo_form
表示form名称,s_demo_type
标识form需要的slot名称 - buttons表示回复的格式是button,
title
为按钮显示文本,payload
为上一节定义的意图select_turtledemo
,用户点击对应按钮后,会将实体demo_type
赋值 - 在actions中配置
action_run_demo
,该在函数中调用对应turtle demo
编写对话脚本
stories.yml
- story: turtle demo
steps:
- intent: show_turtledemo //用户输入问题推断意图为运行turtle demo
- action: turtle_demo_form //激活turtle_demo_form
- active_loop: turtle_demo_form //循环运行form
- slot_was_set: //只有s_demo_type slot被填充后才能跳出循环
- requested_slot: s_demo_type
- active_loop: null
- slot_was_set:
- requested_slot: null
- action: action_run_demo //然后运行函数action_run_demo
- 详见注释
action.py函数定义
...省略...
from .turtledemos.rosette import *
from .turtledemos.round_dance import *
from .turtledemos.sorting_animate import *
from .turtledemos.tree import *
from .turtledemos.two_canvases import *
from .turtledemos.yinyang import *
class ActionRunDemo(Action):
def name(self) -> Text:
return "action_run_demo"
def run(self, dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
slots = {
"s_demo_type":None
}
screen = turtle.Screen()
screen.setup (width=1280, height=720, startx=0, starty=0)
demo_type = tracker.get_slot('s_demo_type')
eval(demo_type)()
mainloop()
dispatcher.utter_message(text="demo运行完成")
return [SlotSet(slot,value) for slot,value in slots.items()]
- 根据slot:
s_demo_type
值调用对应demo