基于Rasa框架搭建中文机器人对话系统

Rasa是一个能用于构建机器人对话系统的框架,基于Rasa框架搭建机器人对话系统,可以使用于工业各类语音智能服务场景,如:远程医疗问诊、智能客户服务、保险产品销售、金融催收服务、手机智能助手等领域。支持基于规则、填槽和机器学习来构建对话系统。主要模块包括:NLU(意图识别和实体提取)和Core(基于模型及规则进行回复)。提供了搭建对话系统的脚手架。

常用命令有:

rasa init 创建项目

rasa train 训练NLU和Core模型

rasa run actions 启动动作服务(主要是自己写的动作,系统默认的动作,不需要单独启动)

rasa shell 启动对话机器人 (会自动启动默认动作服务)

涉及配置文件有:

config.yml 即对NLU和Core模型的配置

Configuration for Rasa NLU.

https://rasa.com/docs/rasa/nlu/components/
language: zh

pipeline:
# No configuration for the NLU pipeline was provided. The following default pipeline was used to train your model.

# If you'd like to customize it, uncomment and adjust the pipeline.

# See https://rasa.com/docs/rasa/tuning-your-model for more information.

  - name: WhitespaceTokenizer
   - name: JiebaTokenizer #支持中文
   - name: RegexFeaturizer
   - name: LexicalSyntacticFeaturizer
   - name: CountVectorsFeaturizer
   - name: CountVectorsFeaturizer
     analyzer: char_wb
     min_ngram: 1
     max_ngram: 4
   - name: DIETClassifier
     epochs: 100
     constrain_similarities: true
   - name: EntitySynonymMapper
   - name: ResponseSelector
     epochs: 100
     constrain_similarities: true
   - name: FallbackClassifier
     threshold: 0.3
     ambiguity_threshold: 0.1

Configuration for Rasa Core.

https://rasa.com/docs/rasa/core/policies/
policies:
# No configuration for policies was provided. The following default policies were used to train your model.

# If you'd like to customize them, uncomment and adjust the policies.

# See https://rasa.com/docs/rasa/policies for more information.

   - name: MemoizationPolicy
   - name: TEDPolicy
     max_history: 5
     epochs: 100
     constrain_similarities: true
   - name: RulePolicy

domain.yml 领域配置

version: '2.0'
config:
  store_entities_as_slots: true
session_config:
  session_expiration_time: 60
  carry_over_slots_to_new_session: true
intents:
- greet:
    use_entities: true
- deny:
    use_entities: true
- request_names:
    use_entities: true
- goodbye:
    use_entities: true
- affirm:
    use_entities: true
- mood_great:
    use_entities: true
- mood_unhappy:
    use_entities: true
- bot_challenge:
    use_entities: true
entities: []
slots:
  first_name:
    type: rasa.shared.core.slots.TextSlot
    initial_value: null
    auto_fill: true
    influence_conversation: true
  last_name:
    type: rasa.shared.core.slots.TextSlot
    initial_value: null
    auto_fill: true
    influence_conversation: true
  name_spelled_correctly:
    type: rasa.shared.core.slots.BooleanSlot
    initial_value: null
    auto_fill: true
    influence_conversation: true
  requested_slot:
    type: rasa.shared.core.slots.UnfeaturizedSlot
    initial_value: null
    auto_fill: true
    influence_conversation: false
responses:
  utter_greet:
  - text: 嗨,你好吗?

  utter_cheer_up:
  - image: https://i.imgur.com/nGF1K8f.jpg
    text: '这是某些使你嗨起来的东西:'
  utter_did_that_help:
  - text: 这对你有帮助吗?

  utter_happy:
  - text: 好极了,继续!

  utter_goodbye:
  - text: 再见
  utter_iamabot:
  - text: 我是个机器人,由Rasa框架提供支持.

  utter_ask_first_name:
  - text: 你贵姓?

  utter_ask_last_name:
  - text: 你的名字?

  utter_ask_name_spelled_correctly:
  - buttons:
    - payload: /affirm
      title: 是
    - payload: /deny
      title: 否
    text:  姓 {first_name} 拼写对了吗?

  utter_submit:
  - text: 好的,谢谢!
  utter_slots_values:
  - text: 我记住你了, {first_name} {last_name}!

actions:
- utter_greet
- utter_slots_values
- utter_submit
- validate_name_form
forms:
  name_form:
    first_name:
    - type: from_text
    last_name:
    - type: from_text
e2e_actions: []

credentials.yml 证书配置,用于调用语音通道的接口

This file contains the credentials for the voice & chat platforms
which your bot is using.

https://rasa.com/docs/rasa/messaging-and-voice-channels

rest:
 # you don't need to provide anything here - this channel doesn't
 # require any credentials

#facebook:
 verify: "<verify>"
 secret: "<your secret>"
 page-access-token: "<your page access token>"

#slack:
 slack_token: "<your slack token>"
 slack_channel: "<the slack channel>"
 slack_signing_secret: "<your slack signing secret>"

#socketio:
 user_message_evt: <event name for user message>
 bot_message_evt: <event name for bot messages>
 session_persistence: <true false>

#mattermost:
 url: "https://<mattermost instance>/api/v4"
 token: "<bot token>"
 webhook_url: "<callback url>"

This entry is needed if you are using Rasa X. The entry represents credentials
for the Rasa X "channel", i.e. Talk to your bot and Share with guest testers.

rasa:
  url: "http://localhost:5002/api"
</callback></bot></mattermost></true></event></event></your></the></your></your></your></verify>

endpoints.yml 端点配置,如:机器人要使用的模型、动作、存储服务等。

This file contains the different endpoints your bot can use.

Server where the models are pulled from.

https://rasa.com/docs/rasa/model-storage#fetching-models-from-a-server

#models:
 url: http://my-server.com/models/default_core@latest
 wait_time_between_pulls:  10   # [optional](default: 100)

Server which runs your custom actions.

https://rasa.com/docs/rasa/custom-actions

#action_endpoint:
 url: "http://localhost:5055/webhook"
action_endpoint:
    url: "http://localhost:5055/webhook"

Tracker store which is used to store the conversations.

By default the conversations are stored in memory.

https://rasa.com/docs/rasa/tracker-stores

#tracker_store:
   type: redis
   url: <host of the redis instance, e.g. localhost>
   port: <port 6379 of your redis instance, usually>
   db: <number 0 of your database within redis, e.g.>
   password: <password used for authentication>
   use_ssl: <whether or not the communication is encrypted, default false>

#tracker_store:
   type: mongod
   url: <url to your mongo instance, e.g. mongodb: localhost:27017>
   db: <name of the db within your mongo instance, e.g. rasa>
   username: <username used for authentication>
   password: <password used for authentication>
tracker_store:
  type: SQL
  dialect: sqlite
  db: trackers.db

Event broker which all conversation events should be streamed to.

https://rasa.com/docs/rasa/event-brokers

#event_broker:
 url: localhost
 username: username
 password: password
 queue: queue
event_broker:
  type: SQL
  dialect: sqlite
  db: events.db
</password></username></name></url></whether></password></number></port></host>

names.txt 本案例使用的姓名列表。

&#x5B59;&#x609F;&#x7A7A;
&#x732A;&#x516B;&#x6212;
&#x5510;&#x4E09;&#x85CF;
&#x6C99;&#x609F;&#x51C0;
&#x8BF8;&#x845B;&#x9752;&#x4E91;

数据,主要包括:

nlu.yml 用于训练nlu模型的训练数据

version: "2.0"
nlu:
- intent: greet
  examples: |
    - &#x4F60;&#x597D;
    - &#x4E0A;&#x5348;&#x597D;
    - &#x4E2D;&#x5348;&#x597D;
    - &#x55E8;
- intent: goodbye
  examples: |
    - &#x518D;&#x89C1;
    - &#x56DE;&#x5934;&#x89C1;
    - &#x665A;&#x5B89;
- intent: affirm
  examples: |
    - &#x662F;&#x7684;
    - &#x6709;
    - &#x5F53;&#x7136;
    - &#x542C;&#x4E0A;&#x53BB;&#x4E0D;&#x9519;
- intent: deny
  examples: |
    - &#x4E0D;
    - &#x4E0D;&#x8981;
    - &#x6CA1;&#x6709;
    - &#x6CA1;&#x6709;
    - &#x6211;&#x4E0D;&#x559C;&#x6B22;
- intent: mood_great
  examples: |
    - &#x592A;&#x597D;&#x4E86;
    - &#x611F;&#x89C9;&#x4E0D;&#x9519;
    - &#x975E;&#x5E38;&#x597D;
- intent: mood_unhappy
  examples: |
    - &#x4E0D;&#x5F00;&#x5FC3;
    - &#x611F;&#x5230;&#x6CAE;&#x4E27;
    - &#x4E0D;&#x9AD8;&#x5174;
    - &#x4E0D;&#x592A;&#x597D;
- intent: bot_challenge
  examples: |
    - &#x4F60;&#x662F;&#x4E2A;&#x673A;&#x5668;&#x4EBA;&#x5417;?

    - &#x4F60;&#x662F;&#x4EBA;&#x7C7B;&#x5417;?

    - &#x6211;&#x662F;&#x5728;&#x548C;&#x673A;&#x5668;&#x4EBA;&#x8BB2;&#x8BDD;&#x5417;?

    - &#x6211;&#x662F;&#x5728;&#x548C;&#x4EBA;&#x7C7B;&#x8BB2;&#x8BDD;&#x5417;?

- intent: request_names
  examples: |
    - &#x6211;&#x60F3;&#x544A;&#x8BC9;&#x4F60;&#x59D3;&#x540D;
    - &#x4F60;&#x77E5;&#x9053;&#x6211;&#x7684;&#x59D3;&#x540D;&#x5417;&#xFF1F;
- lookup: names
  examples: |
    - &#x732A;&#x516B;&#x6212;
    - &#x5B59;&#x609F;&#x7A7A;
    - &#x6C99;&#x609F;&#x51C0;
    - &#x5510;&#x4E09;&#x85CF;

rules.yml 规则,根据用户意图,进行具体的动作(包括查询、填槽、回复等)

version: "2.0"

rules:

- rule: Say goodbye anytime the user says goodbye
  steps:
  - intent: goodbye
  - action: utter_goodbye

- rule: Say 'I am a bot' anytime the user challenges
  steps:
  - intent: bot_challenge
  - action: utter_iamabot

- rule: Activate form
  steps:
  - intent: request_names
  - action: name_form
  - active_loop: name_form

- rule: Submit form
  condition:
  - active_loop: name_form
  steps:
  - action: name_form
  - active_loop: null
  - slot_was_set:
    - requested_slot: null
  - action: utter_submit
  - action: utter_slots_values

stories.yml 故事情节,描述对话的流程

version: "2.0"

stories:

- story: happy path
  steps:
  - intent: greet
  - action: utter_greet
  - intent: mood_great
  - action: utter_happy

- story: sad path 1
  steps:
  - intent: greet
  - action: utter_greet
  - intent: mood_unhappy
  - action: utter_cheer_up
  - action: utter_did_that_help
  - intent: affirm
  - action: utter_happy

- story: sad path 2
  steps:
  - intent: greet
  - action: utter_greet
  - intent: mood_unhappy
  - action: utter_cheer_up
  - action: utter_did_that_help
  - intent: deny
  - action: utter_goodbye

- story: interactive_story_1
  steps:
  - intent: greet
  - action: utter_greet
  - intent: request_names
  - action: name_form
  - active_loop: name_form
  - slot_was_set:
    - requested_slot: first_name
  - slot_was_set:
    - name_spelled_correctly: None
  - slot_was_set:
    - first_name: None
  - slot_was_set:
    - requested_slot: last_name
  - slot_was_set:
    - name_spelled_correctly: None
  - slot_was_set:
    - last_name: None
  - slot_was_set:
    - requested_slot: null
  - active_loop: null
  - action: utter_submit
  - action: utter_slots_values

下面举例创建mybot的过程:

1、使用rasa init 创建mybot项目,目录结果如下:

基于Rasa框架搭建中文机器人对话系统

涉及的配置文件在上文已经逐一列出,下面看看自定义的action是如何写的,主要完成了输入验证的过程,默认的action是以utter_打头,系统默认支持。

actions.py

import yaml
import pathlib
from typing import Text, List, Any, Dict, Optional

from rasa_sdk import Tracker, FormValidationAction
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict

names = pathlib.Path("names.txt").read_text().split("\n")

class ValidateNameForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_name_form"

    async def required_slots(
        self,
        slots_mapped_in_domain: List[Text],
        dispatcher: "CollectingDispatcher",
        tracker: "Tracker",
        domain: "DomainDict",
    ) -> Optional[List[Text]]:
        first_name = tracker.slots.get("first_name")
        if first_name is not None:
            if first_name not in names:
                return ["name_spelled_correctly"] + slots_mapped_in_domain
        return slots_mapped_in_domain

    async def extract_name_spelled_correctly(
        self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> Dict[Text, Any]:
        intent = tracker.get_intent_of_latest_message()
        return {"name_spelled_correctly": intent == "affirm"}

    def validate_name_spelled_correctly(
        self,
        slot_value: Any,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate first_name value."""
        if tracker.get_slot("name_spelled_correctly"):
            return {"first_name": tracker.get_slot("first_name"), "name_spelled_correctly": True}
        return {"first_name": None, "name_spelled_correctly": None}

    def validate_first_name(
        self,
        slot_value: Any,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate first_name value."""

        # If the name is super short, it might be wrong.

        print(f"&#x59D3; = {slot_value} &#x957F;&#x5EA6; = {len(slot_value)}")
        if len(slot_value) <=1: dispatcher.utter_message(text="f"&#x59D3;&#x592A;&#x77ED;&#x4E86;&#xFF0C;&#x4F60;&#x786E;&#x5B9A;&#x62FC;&#x5199;&#x5BF9;&#x4E86;&#xFF1F;")" return {"first_name": none} else: slot_value} def validate_last_name( self, slot_value: any, dispatcher: collectingdispatcher, tracker: tracker, domain: domaindict, ) -> Dict[Text, Any]:
        """Validate last_name value."""

        # If the name is super short, it might be wrong.

        print(f"&#x540D;&#x5B57; = {slot_value} &#x957F;&#x5EA6; = {len(slot_value)}")
        if len(slot_value) <= 1: dispatcher.utter_message(text="f"&#x540D;&#x5B57;&#x592A;&#x77ED;&#x4E86;&#xFF0C;&#x4F60;&#x786E;&#x5B9A;&#x62FC;&#x5199;&#x5BF9;&#x4E86;&#xFF1F;")" return {"last_name": none} else: slot_value}< code></=></=1:>

2、启动自动定义的actions服务:

基于Rasa框架搭建中文机器人对话系统

3、训练NLU和Core模型:

基于Rasa框架搭建中文机器人对话系统

基于Rasa框架搭建中文机器人对话系统

4、启动机器人进行对话

基于Rasa框架搭建中文机器人对话系统

分期业务效果:

基于Rasa框架搭建中文机器人对话系统

基于Rasa框架搭建中文机器人对话系统

基于Rasa框架搭建中文机器人对话系统

基于Rasa框架搭建中文机器人对话系统

实际尝试:可以自动完成正常的分期业务流程,中间可以穿插其它的对话内容,如:分期时间长、手续费太贵、担心被套路等。

Original: https://blog.csdn.net/wxl781227/article/details/122321464
Author: wxl781227
Title: 基于Rasa框架搭建中文机器人对话系统

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/528341/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球