Rasa基础-rules和stories对话定义的区别

rules 是一种基于规则的对话流程定义方式,它的作用是根据用户输入的意图和实体,触发相应的机器人响应。每一次用户的输入都会被独立处理,与之前的输入没有关系,因此在 rules 中是没有上下文的。

特别说明:使用rules定义的action,在action方法里面是获取不到槽的。需要使用槽,请使用基于stories的对话流程定义方式。

为了说明rules和stories的区别,我们先使用rules来定义对话:

rules定义对话:

定义意图:

- intent: query_weekday
  examples: |
    - [今天](date_time)星期几?
    - [明天](date_time)星期几?
    - [昨天](date_time)星期几?
    - [今天](date_time)星期几?
    - 星期几?

定义rules

- story: ask weekday path
  steps:
  - intent: query_weekday
    entities:
    - date_time: 今天
  - action: action_query_weekday

定义domain

intents:
  - bot_challenge
  - query_weekday


entities:
  - date_time
slots:
  date_time:
    type: text
    influence_conversation: false
    mappings:
    - type: from_entity
      entity: date_time

actions:
  - action_query_weekday

config.yml

# The config recipe.
# https://rasa.com/docs/rasa/model-configuration/
recipe: default.v1

# Configuration for Rasa NLU.
# https://rasa.com/docs/rasa/nlu/components/
language: zh

pipeline:
  - name: JiebaTokenizer
  - name: LanguageModelFeaturizer
    model_name: bert
    model_weights: bert-base-chinese
  - name: "DIETClassifier"
    epochs: 100
#    learning_rate: 0.001
#    intent_classification: true
#    entity_recognition: true
#  - name: ResponseSelector
#    epochs: 100

# Configuration for Rasa Core.
# https://rasa.com/docs/rasa/core/policies/
policies:
  - name: MemoizationPolicy
  - name: TEDPolicy
    max_history: 5
    epochs: 200
  - name: RulePolicy

编写action

在actions目录下,创建queryWeekday.py

from typing import Any, Text, Dict, List
from datetime import datetime,timedelta

from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher

def text_date_to_int(text_date):
    if text_date=="今天":
        return  0
    if text_date  =="明天":
        return  1
    if text_date=="昨天":
        return  -1
    #  in  other  case
    return None

weekday_mapping = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
def  weekday_to_text(weekday):
    return  weekday_mapping[weekday]

class ActionQueryWeekday(Action):

    def name(self) -> Text:
        return "action_query_weekday"

    def run(self, dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

        # 如果是使用rules定义的对话,想要使用实体,可以使用tracker.latest_message["entities"]来找
        # 但是rules定义的,tracker.get_slot("XX")无法使用,因为rules不存在上下文
        text_date_entity = next((entity for entity in tracker.latest_message["entities"] if entity['entity'] == 'date_time'), None)
        if text_date_entity:
            text_date = text_date_entity['value']

        # 使用stories定义的对话,可以使用tracker.get_slot("XX")获取词槽,因为stories就是为多轮对话服务的,前提是slot需要在domain中定义
        # text_date = tracker.get_slot("date_time")

        int_date = text_date_to_int(text_date)
        if  int_date is not None:
            delta = timedelta(days=int_date)
            current_date = datetime.now()
            target_date = current_date  +  delta
            dispatcher.utter_message(text=weekday_to_text(target_date.weekday()))
        else:
            dispatcher.utter_message(text="系统暂不支持'{}'的星期查询".format(text_date))
        return []

action方法说明:

    def name(self) -> Text:
        return "action_query_weekday"

这个name方法定义的返回值,要和domain.yml里面一致,Rasa是根据这个来找对应的action动作的。

测试:

训练模型

rasa train

启动actions动作服务器,另外开一个窗口执行:

rasa run actions

使用shell测试

rasa shell
rasa shell --debug   启动,可以看到debug日志,方便排查问题。

Your input ->  明天星期几
系统暂不支持'None'的星期查询

 rasa train nlu   测试意图和实体正常识别

{
  "text": "今天星期几",
  "intent": {
    "name": "query_weekday",
    "confidence": 0.7667776942253113
  },
  "entities": [
    {
      "entity": "date",
      "start": 0,
      "end": 2,
      "confidence_entity": 0.7740038633346558,
      "value": "今天",
      "extractor": "DIETClassifier"
    }
  ],
....

说明虽然意图和实体已经识别出来了,但是使用rules定义的对话,在aciton中获取不到槽,

text_date = tracker.get_slot("date")获取的结果为空,

只能使用tracker.latest_message["entities"],获取实体

print(tracker.latest_message["intent"]) 
#结果:{'name': 'query_weekday', 'confidence': 0.4339539706707001}

print(tracker.latest_message["entities"])   
#结果:[{'entity': 'date', 'start': 0, 'end': 2, 'confidence_entity': 0.608760416507721, 'value': '明天', 'extractor': 'DIETClassifier'}]

stories定义对话:

下面,我们把rules定义的改到stories定义中。

注意:删掉默认的story,不然会影响到我们自己的query_weekday故事。

version: "3.1"

stories:
- story: greet path
  steps:
  - intent: greet
  - action: utter_greet

- story: ask weekday path
  steps:
  - intent: query_weekday
    entities:
    - date_time: 今天
  - action: action_query_weekday

在修改action,使用slot直接获取槽值:

        # 如果是使用rules定义的对话,想要使用实体,可以使用tracker.latest_message["entities"]来找
        # 但是rules定义的,tracker.get_slot("XX")无法使用,因为rules不存在上下文
        # text_date_entity = next((entity for entity in tracker.latest_message["entities"] if entity['entity'] == 'date'), None)
        # if text_date_entity:
        #     text_date = text_date_entity['value']
        print(tracker.latest_message["intent"]) #结果:{'name': 'query_weekday', 'confidence': 0.4339539706707001}
        print(tracker.latest_message["entities"])   #结果:[{'entity': 'date', 'start': 0, 'end': 2, 'confidence_entity': 0.608760416507721, 'value': '明天', 'extractor': 'DIETClassifier'}]

        # 使用stories定义的对话,可以使用tracker.get_slot("XX")获取词槽,因为stories就是为多轮对话服务的,前提是slot需要在domain中定义
        text_date = tracker.get_slot("date_time")

再重新训练和测试,

 

遇到action不执行的情况,可以删掉自己手写的部分,使用交互式学习来让rasa帮我们生成,然后再修改即可,命令如下:

rasa interactive

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值