• Rasa Core实践 报时机器人


    learn from https://github.com/Chinese-NLP-book/rasa_chinese_book_code

    rasa core 对话记录 和 选择下一个动作

    1. 领域 domain

    定义了所有信息:

    • 意图、实体、词槽、动作、表单、回复

    意图、实体 应该 跟 rasa nlu 中的保持一致

    utter_ 开头的回复 表示 渲染同名模板发送给用户

    responses:
    	utter_greet:
    	- "你好 {name}!" # {name} 是模板变量
    
    • 1
    • 2
    • 3

    回复 还支持 富文本,指定通道

    会话配置:会话过期时间,是否继承历史词槽

    2. 故事 story

    version: "3.0"
    stories:
      - story: happy path
        steps:
          - intent: greet
          - action: utter_greet
      - story: query time
        steps:
          - intent: query_time
          - action: action_query_time
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    必须要有的 key 是 story、steps
    steps 表示用户和机器人之间的交互

    用户消息

    	- intent: inform  # 用户意图
    	  entities:
    	  - location: "上海" # 实体信息
    	  - price: "实惠"
    
    • 1
    • 2
    • 3
    • 4

    机器人动作与事件

    动作: action
    返回事件:词槽事件(对词槽的值进行变更)、active_loop 事件(激活or取消激活表单)

    辅助符号

    • 检查点符号,checkpoint 减少故事中重复的部分,名字相同的检查点可以互相跳转
      不同的故事之间,可以通过一个尾部,一个首部 相同的 checkpoint 连接成一个新的故事

    • or 语句

    stories:
    - story:
      steps:
      # 上一个step...
      - action: utter_ask_confirm
      - or:
        - intent: affirm
        - intent: thankyou
      - action: action_handle_affirmation
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    大部分相同,仅有其中一个步骤用户的意图不同

    3. 动作 action

    接受用户输入、对话状态信息,按照业务逻辑处理,并输出改变对话状态的事件和回复消息

    回复动作

    与 domain 里的 回复 关联在一起

    当调用这类动作时,会自动查找回复中的同名的模板并渲染

    表单

    收集任务所需的所有要素

    默认动作

    rasa内置的一些默认动作

    自定义动作

    满足后端交互计算需求,如查数据库、第三方api请求

    4. 词槽 slot

    词槽必须要有 名字类型

    slots:
      slot_name: # 名字
        type: text  # 类型
        influence_conversation: false
        initial_value: "hello"  # 初始值
        mappings: # 映射
        - type: from_entity
          entity: entity_name
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    词槽和对话行为

    设置 influence_conversation bool 选项: 词槽是否影响对话行为

    词槽类型

    text、bool、category(枚举)、float(需要设置取值范围)、list、any(不影响系统动作预测)

    词槽映射

    如上mappings 字段,from_entity 表示将读取某个实体(entity指定)的值来赋值词槽

    5. 策略 policy

    策略负责学习故事,从而预测动作

    有一些内置的策略,他们有优先级,除非是专家,不要随意修改优先级

    数据增强: 使用 Rasa 命令时,添加 -- augmentation 来设定数据增强的数量

    6. 端点 endpoints.yml

    定义了 rasa core 和 其他服务进行连接的配置信息

    7. rasa SDK、自定义动作

    安装 rasa时,默认安装
    单独安装 pip install rasa-sdk

    自定义动作

    class ActionQueryTime(Action):
        def name(self) -> Text:
            return "action_query_time"
    
        def run(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
        ) -> List[Dict[Text, Any]]:
    
            current_time = datetime.now().strftime("%H:%M:%S")
            dispatcher.utter_message(text=current_time)
    
            return []
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 重写 name() 向服务器申明动作名字
    • 重写 run() 获取当前对话信息
      tracker 对象(对话状态追踪,获取历史实体、词槽等)
      domain 对象
      用户消息对象 dispatcher
      根据这些信息完成业务动作,如想改变对话状态,需要返回事件发送给 rasa服务器,没有的话,返回 []

    运行自定义动作

    跟rasa一起安装的sdk,rasa run actions
    单独安装的 python -m rasa_sdk --actions actions

    8. rasa 支持的客户端

    支持 Facebook、Rasa Webchat、Chatroom

    跟 IM 连接的组件 称为 connector 其负责实现通信协议

    rasa支持自定义 连接器,支持同时使用多个连接器连接IM,需要在 credentials.yml 文件中配置如何连接客户端

    9. 实战:报时机器人

    tree

    .
    ├── actions.py
    ├── config.yml
    ├── credentials.yml
    ├── data
    │   ├── nlu.yml
    │   └── stories.yml
    ├── domain.yml
    ├── endpoints.yml
    ├── __init__.py
    ├── media
    │   └── demo.png
    ├── README.md
    └── tests
        └── conversation_tests.md
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    nlu.yml

    version: "3.0"
    nlu:
      - intent: greet
        examples: |
          - 你好
          - 您好
          - hello
          - hi
          - 喂
          - 在么
      - intent: goodbye
        examples: |
          - 拜拜
          - 再见
          - 拜
          - 退出
          - 结束
      - intent: query_time
        examples: |
          - 现在几点了
          - 什么时候了
          - 几点了
          - 现在什么时候了
          - 现在的时间
      - intent: query_date
        examples: |
          - [今天](date)几号
          - [今天](date)是几号
          - [昨天](date)几号
          - [明天](date)几号
          - [今天](date)的日期
          - [今天](date)几号了
          - [明天](date)的日期
          - 几号
      - intent: query_weekday
        examples: |
          - [今天](date)星期几
          - [明天](date)星期几
          - [昨天](date)星期几
          - [今天](date)是星期几
          - 星期几
    
    • 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

    stories.yml

    version: "3.0"
    stories:
      - story: happy path
        steps:
          - intent: greet
          - action: utter_greet
      - story: query time
        steps:
          - intent: query_time
          - action: action_query_time
      - story: query date
        steps:
          - intent: query_date
          - action: action_query_date
      - story: query weekday
        steps:
          - intent: query_weekday
          - action: action_query_weekday
      - story: say goodbye
        steps:
          - intent: goodbye
          - action: utter_goodbye
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    domain.yml

    version: "3.0"
    session_config:
      session_expiration_time: 60
      carry_over_slots_to_new_session: true
    intents:
      - greet
      - goodbye
      - query_time
      - query_date
      - query_weekday
    entities:
      - date
    slots:
      date:
        type: text
        influence_conversation: false
        mappings:
          - type: from_entity
            entity: date
    responses:
      utter_greet:
        - text: 你好,我是 Silly,我可以帮你查询时间、日期和星期几。你可以对我说「现在几点了?」、「今天几号?」或者「明天星期几?」。
      utter_goodbye:
        - text: 再见!
    actions:
      - action_query_time
      - action_query_date
      - action_query_weekday
      - utter_goodbye
      - utter_greet
    
    • 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

    config.yml

    recipe: default.v1
    language: zh
    pipeline:
      - name: JiebaTokenizer
      - name: LanguageModelFeaturizer
        model_name: "bert"
        model_weights: "bert-base-chinese"
      - name: DIETClassifier
        epochs: 100
        tensorboard_log_directory: ./log
        learning_rate: 0.001
    policies:
      - name: MemoizationPolicy
      - name: TEDPolicy
        max_history: 5
        epochs: 100
      - name: RulePolicy
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    endpoints.yml

    action_endpoint:
     url: "http://localhost:5055/webhook"
    
    • 1
    • 2

    actions.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 ActionQueryTime(Action):
        def name(self) -> Text:
            return "action_query_time"
    
        def run(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
        ) -> List[Dict[Text, Any]]:
    
            current_time = datetime.now().strftime("%H:%M:%S")
            dispatcher.utter_message(text=current_time)
    
            return []
    
    
    class ActionQueryDate(Action):
        def name(self) -> Text:
            return "action_query_date"
    
        def run(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
        ) -> List[Dict[Text, Any]]:
            text_date = tracker.get_slot("date") or "今天"
    
            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=target_date.strftime("%Y-%m-%d"))
            else:
                dispatcher.utter_message(text="系统暂不支持'{}'的日期查询".format(text_date))
    
            return []
    
    
    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]]:
            text_date = tracker.get_slot("date") or "今天"
    
            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 []
    
    • 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

    测试

    • rasa run actions 运行动作服务器
    rasa run actions
    2022-11-28 09:50:58 INFO     rasa_sdk.endpoint  - Starting action endpoint server...
    2022-11-28 09:50:58 INFO     rasa_sdk.executor  - Registered function for 'action_query_time'.
    2022-11-28 09:50:58 INFO     rasa_sdk.executor  - Registered function for 'action_query_date'.
    2022-11-28 09:50:58 INFO     rasa_sdk.executor  - Registered function for 'action_query_weekday'.
    2022-11-28 09:50:58 INFO     rasa_sdk.endpoint  - Action endpoint is up and running on http://0.0.0.0:5055
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • rasa train
    • rasa shell
    2022-11-28 21:16:49 INFO     root  - Rasa server is up and running.
    Bot loaded. Type a message and press enter (use '/stop' to exit): 
    Your input ->  你好呀                                                                               
    Building prefix dict from the default dictionary ...
    Loading model from cache /tmp/jieba.cache
    Loading model cost 1.346 seconds.
    Prefix dict has been built successfully.
    你好,我是 Silly,我可以帮你查询时间、日期和星期几。你可以对我说「现在几点了?」、「今天几号?」或者「明天星期几?」。
    Your input ->  bye                                                                                  
    你好,我是 Silly,我可以帮你查询时间、日期和星期几。你可以对我说「现在几点了?」、「今天几号?」或者「明天星期几?」。
    Your input ->  拜拜                                                                                 
    再见!
    Your input ->  现在几点                                                                             
    21:18:11
    Your input ->  今天是几号                                                                           
    2022-11-28
    Your input ->  明天是几号                                                                           
    2022-11-29
    Your input ->  后天是几号                                                                           
    系统暂不支持'后天'的日期查询
    Your input ->  昨天是几号                                                                           
    2022-11-27
    Your input ->  今天星期几                                                                           
    星期一
    Your input ->  明天周几                                                                             
    星期二
    Your input ->  现在几点了?                                                                         
    2022-11-29
    
    • 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

    修改:
    nlu里添加 - [后天](date)的日期
    actions.py 添加 if text_date == "后天": return 2

    重新训练,测试

    Your input ->  后天几号                                                                                                               
    2022-11-30
    Your input ->  后天星期几                                                                                                             
    星期三
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    CVE-2023-32315:Openfire管理控制台身份验证绕过到RCE的复现
    IDEA-2023-jdk8 HelloWorld的实现
    基于Flume+Kafka+Hbase+Flink+FineBI的实时综合案例(一)案例需求
    【金三银四】Java基础知识面试题(2021最新版)
    Fullcalendar(简单的日程管理)
    Kotlin高仿微信-第35篇-支付-二维码收款(二维码)
    MySQL数据库期末考试试题及参考答案(05)
    react native 安卓打包报这个错误> Task :app:mergeDexRelease
    JAVA面试大全之微服务篇
    我更看好开源大模型的发展前景
  • 原文地址:https://blog.csdn.net/qq_21201267/article/details/127841846