Rasa Chinese Chatbot Development Guide (3): Core

Article Directory
1. Dialogue Management
1.1 Multi-round Dialogue
1.2 Dialogue Management
2. Rasa Core
2.1 Stories 2.2
Domain
2.3 Responses
2.4 Actions 2.5
Policies
2.6 Slots
2.6.1 Slots Type
2.6.2 Slots Set
2.6.3 Slots Get
2.7 Form
2.8 Interactive Lear ning
3 . Improve ChitChatAssistant project
3.1 config.yml
3.2 weather_stories.md
RASA development Chinese guide series blog posts:

Rasa Chinese Chatbot Development Guide (1): Getting Started
Rasa Chinese Chatbot Development Guide (2): NLU
Rasa Chinese Chatbot Development Guide (3): Core
Rasa Chinese Chatbot Development Guide (4): RasaX Rasa
Chinese Chatbot Development Guide (5): Action Note
: This series of blogs is translated from Rasa official documents, and integrates my own understanding and project practice. At the same time, the technical points involved in the documents have been expanded to a certain extent. Better understand the working mechanism of Rasa. The GitHub address of the project supporting this series of blog posts : ChitChatAssistant, welcome stars and issues, let's discuss and learn together !

1. Dialogue management
1.1 Multi-round dialogue
 Multi-round dialogue is relative to single-round dialogue. Single-round dialogue focuses on one question and one answer , that is, to give accurate answers directly to users' questions. Question answering is closer to an information retrieval process . Although it may also involve simple context processing , it is usually done by referring to resolution and query completion , while multi-round dialogue focuses on the need maintain a representation of the user's goal state and a The decision-making process is used to complete the task. Specifically, the user comes with a clear purpose, hoping to obtain information or services that meet specific constraints, such as: ordering meals, ordering tickets, looking for music, movies, or certain commodities. Because the user's needs can be more complex, it may need to be stated in multiple rounds, and the user may also constantly modify or improve their needs during the dialogue. In addition, when the user's stated needs are not specific or clear enough, the machine can also help the user find a satisfactory result by asking, clarifying, or confirming. Therefore, task-driven multi-round dialogue is not a simple process of natural language understanding plus information retrieval, but a decision-making process, which requires the machine to continuously decide the optimal action to take in the next step based on the current state during the dialogue process (such as: providing results, asking for specific constraints, clarifying or confirming requirements, etc.) to most effectively assist users in their information or service acquisition tasks.


Note: The task-driven multi-round dialogue system is usually a closed domain (domain) (chat system is an open domain ), and the specific restriction corresponds to the slot (Slot ), that is, the user is a slot value once when the specific restriction is met In the filling process, if the user can satisfy all the constraints in one session , then the user can directly obtain satisfactory information or services without having to conduct multiple rounds of dialogue .

1.2 Dialogue management
 Dialogue management, Dialog Management (DM), which controls the process of man-machine dialogue , is an important part of man-machine dialogue system. DM will update and track the dialogue state according to the semantic representation output by the NLU module, and select corresponding candidate actions according to a certain strategy. To put it simply, the DM will decide the reaction to the user at the moment based on the dialogue history information. For example, in a task-driven multi-round dialogue system, the user has a clear purpose such as ordering a meal, booking a ticket, etc. The user's needs are more complicated, and there are many Constraints may need to be presented in multiple rounds. On the one hand, users can continuously modify or improve their needs during the dialogue process. On the other hand, when the user's stated needs are not specific or clear enough, the machine can also ask , clarification, or confirmation to help users find satisfactory results. As shown in the figure below, the input of DM is the semantic expression of user input (or user behavior, which is the output of NLU) and the current dialogue state, and the output is the next system behavior and updated dialogue state. This is a process that goes back and forth until the task is completed.

 In essence, **Task-driven dialogue management is actually a decision-making process. During the dialogue process, the system continuously determines the optimal action that should be taken next according to the current state (such as: provide results, ask for specific constraints, clarify or confirm needs, etc.), so as to most effectively assist users to complete the task of obtaining information or services. **Dialogue management tasks roughly include:

Dialog state tracking (dialog state tracking, DST)


 The dialog state refers to recording which slots have been filled, what to do next, what slot to fill, or what to do. Expressed in mathematical form, the dialog state S(t+1) at time t+1 depends on the state St at the previous time t, the system behavior At at the previous time t, and the user behavior O( t+1). It can be written as S(t+1)←St+At+O(t+1).

Generate system decision (dialog policy)


 According to the dialog state (DS) in DST, generate system behavior (dialog act), decide what to do next. dialog act can represent the observed user input (user input -> DA, which is the process of NLU), and the feedback behavior of the system (DA -> System Feedback is the process of NLG).

Interact with the backend/task model as an interface
2. Rasa Core
 Rasa Core is a dialog management module provided by the Rasa framework, which is similar to the brain of a chat robot. The main task is to maintain and update the dialog state and action selection, and then input to the user respond. The so-called dialogue state is a representation of chat data that can be processed by the machine. The dialogue state contains all the information that may affect the next step decision, such as the output of the natural language understanding module, the characteristics of the user, etc.; the so-called action selection refers to based on In the current dialogue state, select the next appropriate action, such as asking the user for information to be supplemented, performing the action requested by the user, etc. To give a specific example, the user says "order a bouquet of flowers for my mother", at this time the dialogue state includes the output of the natural language understanding module, the user's location, historical behavior and other features. In this state, the next action of the system may be:

Ask the user the acceptable price, such as "What is the expected price?";
confirm the acceptable price to the user, such as "Is it okay to buy flowers worth 200 like last time?"
Directly book for the user
2.1 Stories
 Rasa's story It is a form of training data used to train Rasa's dialogue management model. A story is a representation of a conversation between a user and an AI assistant, translated into a specific format where user input is represented as corresponding intents (and necessary entities), and the assistant's responses are represented as corresponding action names. A training example for Rasa's core dialogue system is called a story . This is a guide to the format of the story data. Example of two dialogue samples:

<!-- ##Indicates the description of the story, which has no practical effect -->
## greet + location/price + cuisine + num people
* greet
   - utter_greet
* inform{"location": "rome", "price": "cheap "}
   - action_on_it
   - action_ask_cuisine
* inform{"cuisine": "spanish"}
   - action_ask_numpeople    
* inform{"people": "six"}
   - action_ack_dosearch
  
<!-- Form Action-->
## happy path 
* request_weather
   - weather_form
   - form{"name": "weather_form"}
   - form{"name": null}

The Story format roughly consists of three parts:

1. User Input (User Messages)


 Use the sentence starting with * to represent the user's input message. We don't need to use the input containing a specific content, but use the intent and entities output by the NLU pipeline to represent the possible input. It should be noted that if the user's input may contain entities, it is recommended to include them, which will help policies predict the next action. This part roughly includes three forms, examples are as follows:

(1) * greet means that the user input does not have an entity;
(2) * inform{"people": "six"} means that the user input contains an entity, and the response to this type of intent is a normal action; (3
) * request_weather means that the user enters a Message The corresponding intent is a form action;

2. Actions (Actions)
 use a sentence beginning with - to indicate that an action (Action) is to be executed, which can be divided into utterance actions and custom actions . Among them, the former is defined in domain.yaml and prefixed with utter_ , such as the intent named greet , Its reply should be utter_greet; the latter is a custom action, and the specific logic is implemented by ourselves. Although there is no limit when defining the action name, it is recommended to prefix it with action_, such as the intent named inform fetch_profile, Its response can be action_fetch_profile.

3. Events (Events)
 Events also start with -, mainly including slot value setting (SlotSet) and activation/logout form (Form), which is part of Story and must be displayed and written out. The functions of Slot Events and Form Events are as follows:

(1)Slot Events

 The role of Slot Events When we set a slot value in a custom Action, then we need to mark the SlotSet event prominently after the Action in the Story is executed, the format is - slot{"slot_name": "value"} . For example, we set the value of Slot named account_type in action_fetch_profile, the code is as follows:

from rasa_sdk.actions import Action
from rasa_sdk.events import SlotSet
import requests

class FetchProfileAction(Action):
    def name(self):
        return "fetch_profile"

    def run(self, dispatcher, tracker, domain):
        url = "http://myprofileurl.com"
        data = requests.get(url).json
        return [SlotSet("account_type", data["account_type"])]

 then , you need to add - slot{"account_type" : "premium"} after executing action_fetch_profile in Story . Although, it seems a bit redundant to do so, but Rasa stipulates that it is necessary to improve the accuracy of training.

## fetch_profile
* fetch_profile
   - action_fetch_profile
   - slot{"account_type" : "premium"}
   - utter_welcome_premium

 Of course, if you reset the slot value to None in your custom Action, the corresponding event is -slot{"slot_name": null }.

(2)Form Events

 There are three main forms of form events (Form Events) in Story, which can be expressed as:

Form Action event
 Form Action is a form action event , which is a kind of custom Action and is used for a form operation. Examples are as follows:

- restaurant_form
1
Form activation event
 form activation is to activate the form event. When the form action event is executed, the event will be executed immediately. Examples are as follows:

- form{"name": "restaurant_form"}
1
Form deactivation event
 form deactivation is a logout form event, and its function is opposite to form activation. Examples are as follows:

- form{"name": null}
1
 In short, when we build a Story, it can be said to be diverse, because the designed storylines are diverse, which means that the combination of the above three contents is also very flexible of . In addition, when designing Story, Rasa also provides two functions of Checkpoints and OR statements to improve the flexibility of building Story, but it should be noted that although things are good, don’t be too greedy. Excessive use will not only increase the complexity At the same time, it will also slow down the speed of training. Among them, Checkpoints are used to modularize and simplify training data, examples are as follows:

## first story
* greet
   - action_ask_user_question
> check_asked_question

## user affirms question
> check_asked_question
* affirm
  - action_handle_affirmation
> check_handled_affirmation

## user denies question
> check_asked_question
* deny
  - action_handle_denial
> check_handled_denial

## user leaves
> check_handled_denial
> check_handled_affirmation
* goodbye
  - utter_goodbye

 In the above example, you can use > check_asked_question to represent the first story, so that in other stories, if there is the same part of the first story, you can directly use > check_asked_question instead. And OR Statements are mainly used to realize that an action can respond to multiple intents at the same time, such as the following example:

## story
* affirm OR thankyou
  - action_handle_affirmation
1
2
3
2.2 Domain
 Domain, translated as **"domain"**, it describes all the information that a dialogue robot should know, similar to the "human brain", which stores intents, Information such as entity entities, slots, and actions. Among them, intents and entities are defined in the NLU training samples, and slots correspond to the types of entities, but in different forms. The structure of the domain.yml file is as follows:

Composition Function
intents This field lists the Bot’s ability to identify which intents
session_config This field describes the timeout period of a session and the behavior of the next session after the timeout
slots This field lists the Bot’s ability to fill which slot values
​​entities This field lists The Bot has the ability to identify which entities
actions This field lists the executable behavior
forms of the Bot This field lists the form action
responses     of the Bot This field lists the text that the Bot can use to automatically reply when an intent is triggered
The details are as follows:

1. intents

Intents:
  - affirm
  - deny
  - greet
  - request_weather
  - request_number
  - inform
  - inform_business
  - stop
  - chitchat

 Intents, that is, intents, mean that we enter a piece of text and hope Bot can understand what the text means. In the Rasa framework, the definition of intent is implemented in NLU samples , and under each intent, we need to enumerate as many samples as possible for training, so that the Bot can accurately identify the sentence we input. what to do.

2. session_config

session_config:
  carry_over_slots_to_new_session: true
  session_expiration_time: 60 session_config, that is, session configuration, this part is used to configure whether there is a timeout limit for

a conversation session . The above example demonstrates that the timeout period of each session is 60s. If the user does not enter any information within 60s after starting a session, the session will be terminated, and then the Bot will start a new session and will Copy the Slot value from the previous session. Of course, we want to discard the value of the last session Slot, we can set carry_over_slots_to_new_session to false. In addition, when session_expiration_time is set to 0, Bot will never end the current session and wait for user input (note: executing action_session_start can still start a new session if it is set to 0).

3. slots

slots:
  date_time:
    type: unfeaturized
    auto_fill: false
  address:
    type: unfeaturized
    auto_fill: false

 Slots, that is, slots, are like the memory of a dialogue robot, which can be used to collect and store user-input information (entities) in the form of key-value pairs Or query the data in the database, etc. For details on the design and use of Slots, please refer to Section 2.6 of this article.

4. entities

entities:
  - date_time
  - address

 entities, that is, entities, similar to keywords in the input text, need to be marked in the NLU sample, and then the Bot will perform entity recognition and fill it into the Slot slot to facilitate subsequent related business operations .

5. actions

actions:
  - utter_answer_affirm # utter_ starts with utter actions
  - utter_answer_deny
  - utter_answer_greet
  - utter_answer_goodbye
  - utter_answer_thanks
  - utter_answer_whoareyou
  - utter_answer_whattodo
  - utter_ask_date_time
  - utter ter_ask_address
  - utter_ask_number
  - utter_ask_business
  - utter_ask_type
  - action_default_fallback # default actions

 when Rasa NLU recognizes the user input Message After the intention , the Rasa Core dialogue management module will respond to it, and the module that completes the response is the action. Rasa Core supports three kinds of actions, namely default actions, utter actions and custom actions. About how to implement Actions and process business logic, we will talk about it in detail in an article, here is just a brief understanding.

6. forms

forms:
  - weather_form

 forms, that is, the form, which lists which Form Actions are defined in the NLU sample . For the knowledge about Form Actions, please move to section 2.7 of this article.

7. responses

responses:
  utter_answer_greet:
    - text: "Hello! May I help you?"
    - text: "Hello! I am glad to serve you. Please tell me the function you are looking for?"
    
  utter_ask_date_time:
    - text: "Excuse me What day do you want to check the weather?"

  utter_ask_address:
    - text: "Where do you want to check the weather?"
    
  utter_default:
    - text: "I don't understand, please put it another way~"

 The responses part is to describe the specific reply content of UtterActions, and each UtterAction can be defined For multiple messages, when the user initiates an intent, such as "Hello!", the utter_answer_greet operation will be triggered, and Rasa Core will automatically select one of the messages from the action template as the result to feed back to the user.

2.3 Responses
 The role of Responses is to automatically respond to the information entered by the user, so we need to manage these responses (Responses). The Rasa framework provides three ways to manage Responses, they are:

Store Responses in the domain.yaml file;
store Responses in the training data;
customize an NLG service to generate Responses.
 Since the first one has been introduced in section 2.2(7) of this article, the creation of NLG services is as follows:

nlg:
  url: http://localhost:5055/nlg    # url of the nlg endpoint
  # you can also specify additional parameters, if you need them:
  # headers:
  #   my-custom-header: value
  # token: "my_authentication_token"    # will be passed as a get parameter
  # basic_auth:
  #   username: user
  #   password: pass
# example of redis external tracker store config
tracker_store:
  type: redis
  url: localhost
  port: 6379
  db: 0
  password: password
  record_exp: 30000
# example of mongoDB external tracker store config
#tracker_store:
  #type: mongod
  #url: mongodb://localhost:27017
  #db: rasa
  #user: username
  #password: password


2.4 Actions
 When Rasa NLU recognizes the user's intention to input a Message, the Rasa Core dialogue management module will respond to it, and the module that completes this response is the action. Rasa Core supports three kinds of actions, namely default actions, utter actions and custom actions. About how to implement Actions and process business logic, we will talk about it in detail in an article, here is just a brief understanding.

1. default actions

 DefaultAction is the default set of actions of Rasa Core, we don't need to define them, they can be used directly in story and domain. Including the following three actions:

action_listen: listen to the action, Rasa Core usually calls the action automatically during the session;
action_restart: reset the state, than initialize the value of Slots (slots), etc.;
action_default_fallback: when the confidence obtained by Rasa Core is lower than the set threshold , execute the action by default;
2. utter actions

UtterAction starts with utter_ and is only used to send a message to the user as feedback. Defining a UtterAction is very simple, you only need to define an action starting with utter_ in the actions: field in the domain.yml file, and the specific reply content will be defined in the templates: section, which we will explain in detail below. An example of defining utter actions is as follows:

actions:
  - utter_answer_greet
  - utter_answer_goodbye
  - utter_answer_thanks
  - utter_introduce_self
  - utter_introduce_selfcando
  - utter_introduce_selffrom

3. custom actions

CustomAction, that is, custom action , allows developers to perform any operation and feedback to users, such as simply returning a string of strings, or controlling home appliances, checking bank account balances, and so on. It is different from DefaultAction. Custom action requires us to define it first in the actions section of the domain.yml file, and then implement it in the specified webserver, where the url address of the webserver is specified in the endpoint.yml file, and the webserver It can be implemented in any language. Of course, python is recommended first. After all, Rasa Core has packaged a rasa-core-sdk for us to handle custom actions. Regarding the construction of action web and the specific implementation of action, we will explain in detail later, here we look at what needs to be done in the Rasa Core project. If we need to provide two services of querying weather and air quality in the man-machine dialogue system of weather information, then we need to define the action of querying weather and air quality in the domain.yml file, namely:

actions:
  ...    
  - action_search_weather

 In addition, FormAction is also a custom action, but it needs to be declared in the forms field of the domainl.yaml file.

forms:
  - weather_form
1
2
2.5 Policies
 Policies is a policy module in Rasa Core, corresponding to the class rasa_core.policies.Policy, its role is to use the appropriate policy (Policy) to predict the behavior (Actions) to be executed after a conversation. The principle of prediction is to measure which policies are hit with high confidence, and the policy with high confidence selects the appropriate Action to execute. If different policies have the same confidence, then it is determined by their priority, that is, the policy with higher priority is selected. Rasa prioritizes the provided Policies, as shown in the following table:

Priority (decreasing) policies (each line has the same priority)
5 FormPolicy
4 FallbackPolicy and TwoStageFallbackPolicy
3 MemoizationPolicy and AugmentedMemoizationPolicy 2
MappingPolicy
1 TEDPolicy, EmbeddingPolicy, KerasPolicy and SklearnPolicy
Their descriptions and functions are as follows:

Memoization Policy
 Memoization Policy only remembers (memorizes) the dialogue in the training data. If such a dialogue exists in the training data, then it will predict the next action with a confidence of 1.0, otherwise it will predict None with a confidence of 0.0. The following demonstrates how to configure the MemoizationPlicy policy in the policy configuration file config.yml file, where max_history (hyperparameter) determines how many dialog histories the model looks at to determine the next action to execute.

 policies:
    - name: "MemoizationPolicy"
    max_history: 5
1
2
3
Note: The larger the max_history value is, the larger the model will be trained and the training time will be longer. Regarding how much this value should be set, we can give such an example, such as There is such an Intent: out_of_scope to describe the off-topic message input by the user. When the user triggers the out_of_scope intent three times in a row, we need to actively inform the user that he needs to provide help. If Rasa Core can learn this model , max_history should be at least 3. The performance in story.md is as follows:

* out_of_scope
   - utter_default
* out_of_scope
   - utter_default
* out_of_scope
   - utter_help_message

Keras Policy
 The Keras Policy policy is a neural to predict and choose to execute the next action . Its default framework uses LSTM (Long Short-Term Memory, long-term short-term memory network ) algorithm, but we can also rewrite the KerasPolicy.model_architecture function to implement our own framework (architecture). The model of KerasPolicy is very simple, just a single LSTM+Dense+softmax, which requires us to constantly improve our story to supplement the stories in various situations. The following demonstrates how to configure the KerasPolicy policy in the policy configuration file config.yml file, where epochs represents the number of training times, and max_history is the same as above.

policies:
  - name: KerasPolicy
    epochs: 100
    max_history: 5

Embedding Policy
 Machine learning-based dialog management is able to learn complex behaviors to accomplish tasks, but extending its capabilities to new domains is not straightforward, especially with different policies dealing with uncooperative user behavior and how to reapply completion of one task (e.g., restaurant reservations) to that task while learning a new one (e.g., hotel reservations). EmbeddingPolicy, Recurrent Embedding Dialogue Policy (REDP), which can achieve better results by embedding actions and dialogue states into the same vector space (vector space), REDP contains an improved Neural Turing Machine based on The memory component and attention mechanism of , significantly outperform the baseline LSTM classifier on this task.

 EmbeddingPolicy is better than KerasPolicy in effect, but it has a problem that it is time-consuming because it does not use GPU and does not make full use of CPU resources. The comparison diagram of KerasPolicy and EmbeddingPolicy is as follows:

Configure EmbeddingPolicy parameters:

policies:
  - name: EmbeddingPolicy
    epochs: 100
    featurizer:
    - name: FullDialogueTrackerFeaturizer
      state_featurizer:
        - name: LabelTokenizerSingleStateFeaturizer
1
2
3
4
5
6
7
Note: The new version of Rasa renames EmbeddingPolicy to TEDPolicy, but I am in config. yml configuration file will After its replacement, it prompts that the TEDPolicy exception cannot be found. The specific reason is unknown, and the source code analysis has not yet been involved.

Form Policy
 FormPolicy is an extension of MemoizationPolicy, which is used to handle (form) form filling matters. When a FormAction is called, the FormPolicy will continue to predict the form action until all the slots in the form are filled, and then execute the corresponding FormAction. If FormActions is used in the Bot system, it needs to be configured in the config.yml configuration file.

policies:
  - name: FormPolicy
1
2
Mapping Policy
 MappingPolicy can be used to directly map the intent to the action to be executed, so that the mapped action will always be executed, and this mapping is implemented through the triggers attribute. Take a chestnut (in the domain.yml file):

intents:
 - greet: {triggers: utter_goodbye}
1
2
 Among them, greet is the intention; utter_goodbye is the action. An intent can only be mapped to at most one action. Once our robot receives the message of the mapped intent, it will execute the corresponding action. Then, continue to listen to the next message. It should be noted that for the above mapping, we also need to add the following samples in the story.md file, otherwise, any machine learning strategy may be confused by the sudden appearance of the predicted action_greet in the dialouge history.

Fallback Policy
 If the confidence of intent recognition is lower than nlu_threshold, or the confidence of action predicted by any dialog strategy is higher than core_threshold, FallbackPolicy will execute the fallback action. In layman's terms, the confidence of our dialogue robot's intent recognition and action prediction does not meet the corresponding threshold, and this strategy will make the robot execute the specified default action. configs.yml is configured as follows:

policies:
  - name: "FallbackPolicy"
    # Intent understanding confidence threshold
    nlu_threshold: 0.3
    # Action prediction confidence threshold
    core_threshold: 0.3
    # fallback action
    fallback_action_name: 'action_default_fallback'
1
2
3
4
5
6
7
8
 Among them, action_default_fallback is Rasa Core in A default action which will send the utter_default template message to the user, so we need to make sure to specify this template in the domain.yml file. Of course, we can also customize the action of the default reply in the fallback_action_name field, such as my_fallback_cation, which can be changed like this:

policies:
  - name: "FallbackPolicy"
    nlu_threshold: 0.4
    core_threshold: 0.3
    fallback_action_name: "my_fallback_action"
1
2
3
4
5
2.6 Slots
 Slots, slot values, are equivalent to the memory of the robot, they exist in the form of key-value pairs, use It is more important information when storing user input messages, and this information will provide key data for the execution of Action. The definition of Slots is located in the domain.yaml file. They usually correspond to Entities, that is, there are Entities and Slots, and the value stored in Slots is the value of Entities extracted by the NLU model.

2.6.1 Slots Type
1. Text type

text    
role Preference, if you only care about whether the slot is specified or not
Description If any value is set, it will cause the slot's characteristic value to be set to 1, otherwise the characteristic value will be set to 0 (no value is set) Example
 :

# domain.yaml
slots:
   cuisine:
      type: text
1
2
3
4
2. Boolean类型

bool    
function True or False
description Checks if slot is set and if True
 Example:

slots:
   is_authenticated:
      type: bool
1
2
3
3. categorical类型

The categorical    
function specifies that the value of the slot is one of a certain range.
The description is similar to the enumeration
 example:

slots:
   risk_level:
      type: categorical
      values:
      - low
      - medium
      - high
1
2
3
4
5
6
7
4. Float类型

Float    
function Continuous value
Description Default max_value=1.0, min_value=0.0, when it is lower than min_value, take min_value; when it exceeds max_value, take max_value.
 Example:

slots:
   temperature:
      type: float
      min_value: -100.0
      max_value:  100.0
1
2
3
4
5
5. List类型

list    
role list value
description If a value with a list is set, and the list is not empty, this slot's property is set to 1. This property is 0 if no value is set, or an empty list is a set value. The length of the list stored in the slot does not affect the dialog.
 Example:

slots:
   shopping_items:
      type: list
1
2
3
6. Unfeaturized 类型

Text    
role The data to be stored should not affect the dialogue flow
description This slot will not have any featurization, so its value will not affect the dialogue flow and is ignored when predicting the next action the bot should run.
 Example:

slots:
   internal_user_id:
      type: unfeaturized
1
2
3
2.6.2 Slots Set
 There are many ways to fill the Slots value, and their operations are as follows:

1. Slots Initial

# domain.yaml
slots:
  name:
    type: text
    initial_value: "human"
1
2
3
4
5
 When declaring slots in the domain.yaml file, you can provide an initial value for the current slot through the initial_value field, that is, when the session starts , the slot whose initial value is set has been filled. Of course, this operation is not necessary.

2. Slots Set from NLU

# stories.md
# story_01
* greet{"name": "Ali"}
  - slot{"name": "Ali"}
  - utter_greet
1
2
3
4
5If
 you add a story containing -slot{} to the stories.md file , which means that when the NLU model extracts an entity named name and this entity is defined in domain.yaml, then the entity value extracted by the NLU model will be automatically filled in the name slot. In fact, for Rasa, even if you don't add the -slot{} field, the entity value will be extracted and automatically filled into the name slot. Of course, if you want to disable this automatic filling behavior, add -slot{} field filling instead, you can set the value of auto_fill to False when defining the slot in domain.yaml, namely:

# domain.yaml
slots:
  name:
    type: text
    auto_fill: False
1
2
3
4
5
3. Slots Set By Clicking Buttons

# domain.yaml
utter_ask_color:
- text: "what color would you like?"
  buttons:
  - title: "blue"                           
    payload: '/choose{"color": "blue"}' # format'/intent{"entity": "value",...}' 
  - title: "red"
    payload: '/choose{"color": "red"}'   
1
2
3
4
5
6
7
8
 Fill the value of Slots when Button is clicked, which means when When our Bot (Rasa Core) replies to the user, it can attach Button information to the reply message. This kind of Button is similar to a shortcut key. Identify the intent and extract the entity, and fill the value of the entity into the slot. For example, if you want users to choose a color by clicking a button, you can add buttons to the reply of utter_ask_color in domain.yaml: /choose{"color": "blue"} and /choose{"color": "red"}. Note: Usually each button consists of title and payload fields.

4. Slots Set by Actions

from rasa_sdk.actions import Action
from rasa_sdk.events import SlotSet
import requests

class FetchProfileAction(Action):
    def name(self):
        return "fetch_profile"

    def run(self, dispatcher, tracker, domain):
        url = "http://myprofileurl.com"
        data = requests.get(url).json
        return [SlotSet("account_type", data["account_type"])]
1
2
3
4
5
6
7
8
9
10
11
12
 This example demonstrates how to fill the value of Slots by returning an event in Custom Action, that is, call the SlotSet event function and return the event. It should be noted that in order to achieve this purpose, we must include the Slot when writing the Story, that is, use -slot{} to achieve it. Only in this way will Rasa Core learn from the information provided and decide to execute the correct action. The Story.md example is as follows:

# story_01
* greet
  - action_fetch_profile
  - slot{"account_type" : "premium"}
  - utter_welcome_premium

# story_02
* greet
  - action_fetch_profile
  - slot{"account_type" : "basic"}
  - utter_welcome_basic
1
2
3
4
5
6
7
8
9
10
11
 Among them, account_type is defined in domain.yaml as follows:

slots:
   account_type:
      type: categorical
      values:
      - premium
      - basic
1
2
3
4
5
6
2.6.3 Slots Get
 There are currently two ways to obtain Slots values:

1. Get Slot in responses

responses:
  utter_greet:
  - text: "Hey, {name}. How are you?"
1
2
3
 In the responses section of domain.yaml, the slot value can be obtained in the form of {slotname}.

2. Get Slot in Custom Action

from rasa_sdk.actions import Action
from rasa_sdk.events import SlotSet
import requests

class FetchProfileAction(Action):
    def name(self):
        return "fetch_profile"

    def run(self, dispatcher, tracker, domain):
        # Get the value of slot account_type
        account_type = tracker.get_slot('account_type')
        return []
1
2
3
4
5
6
7
8
9
10
11
12
 Tracker, which can be understood as a tracker , the role is to maintain the dialog state between the assistant and the user in the form of a session session. Through Tracker, the entire dialogue information can be easily obtained, including the value of the Slot.

2.7 Form
 In Rasa Core, when we execute an action and need to fill multiple slots at the same time, we can use FormAction to implement it, because FormAction will traverse all the slots supervised, and when it finds that the relevant slot is not filled, it will actively notify the user Initiate a query, and the next business logic will not be executed until all slots are filled. The steps to use are as follows:

(1) Construct story

 In the story, it is not only necessary to consider that the user accurately provides valid information according to our design, but also considers that the user changes the intention to be executed in the middle process or enters invalid information, because for FormAction, if the expected information cannot be obtained An error will be reported. Here we call these two situations happy path and unhappy path respectively. Examples are as follows:

## happy path
* request_weather
    - weather_form
    - form{"name": "weather_form"}  激活form
    - form{"name": null}  使form无效
## unhappy path
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* stop
    - utter_ask_continue
* deny
    - action_deactivate_form
    - form{"name": null}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Note: * request_restaurant is the intent; - restaurant_form is the form action; - form{"name": "restaurant_form"} is the activation form; - form{"name": null} is the logout form; - action_deactivate_form is the default action, its The effect is that the user may change his mind during the form operation and decide not to proceed with the original request. We use this default action to disable (cancel) the form and reset all slots to be requested.

It is best to use the official Interactive Learning to build stroy to prevent missing information, see section 2.8 of this article for details.

(2) Add form field to Domain

 Add the forms: section under the doamin file, and add all the used form names to this field:

intents:
  - request_weather

forms:
  - weather_form
1
2
3
4
5
(3) Deployment FormPolicy

 In the configuration file configs.yml of the project, add the FormPolicy strategy:

policies:
  - name: EmbeddingPolicy
    epochs: 100
    max_history: 5
  - name: FallbackPolicy
    fallback_action_name: 'action_default_fallback'
  - name: MemoizationPolicy
    max_history: 5
  - name: FormPolicy
1
2
3
4
5
6
7
8
9
(4)Form Action实现

class WeatherForm(FormAction):

    def name(self) -> Text:
        """Unique identifier of the form"""

        return "weather_form"

    @staticmethod
    def required_slots(tracker: Tracker) -> List[Text]:
        """A list of required slots that the form has to fill"""

        return ["date_time", "address"]

    def submit(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> List[Dict]:
        """Define what the form has to do
            after all required slots are filled"""
        address = tracker.get_slot('address')
        date_time = tracker.get_slot('date_time')

        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  When the form action is first called, the form will be activated and enter the FormPolicy strategy mode
. Every time the form action is executed, required_slots will be called. When it is found that a certain slot has not been filled, it will actively call the template in the form of uter_ask_{slotname} (note: defined in the templates field of domain.yml); when all slots After being filled, the submit method will be called, and the form operation will be deactivated at this time.



2.8 Interactive Learning
 Although we can easily construct story sample data manually, there are often some problems such as incomplete consideration and even errors. Based on this, the Rasa Core framework provides us with an interactive learning (Interactive Learning) to obtain the required sample data. In interactive learning mode, you provide feedback to the robot as you talk to it, which is a powerful way to explore what your robot can do and the easiest way to fix mistakes it makes. One of the advantages of machine learning-based dialogue is that you can directly teach your bot how to do something when it doesn't yet know how to do it.

(1) Open Action Server

python -m rasa run actions --port 5055 --actions actions --debug
1
(2)开启Interactive Learning

python -m rasa interactive -m models/20200313-101055.tar.gz --endpoints configs/endpoints.yml --config configs/config.yml 

# Or (no trained model)
# rasa will train the model first, and then open the interactive learning session
python -m rasa interactive --data /data --domain configs/domain.yml --endpoints configs/endpoints.yml - -config configs/config.yml 
1
2
3
4
5
 After executing the (1) and (2) commands respectively, we can preset an interactive scene and operate according to the prompts of the terminal. If all the processes of an interactive scene have been executed, press Ctrl+C to end and select Start Fresh to enter the next scene. Of course, Rasa also provides a visual interface to help you understand the process of building each Story sample, URL: http://localhost:5005/visualization.html.

 The execution process is roughly as follows:

Bot loaded. Visualisation at http://localhost:5006/visualization.html .
Type a message and press enter (press 'Ctr-c' to exit).
? Your input -> 查询身份证439912199008071234
? Is the intent 'request_idcard' correct for '查询身份证[439912199008071234](id_number)' and are all entities labeled correctly?  Yes
------
Chat History

 #BotYou       
───────────────────────────────────────────────────────────────────────────────────────── ────────────────────────────────────────────────────────────────────────────────────────────────────────────
 _
_ ───────────────────────────────────────
 2 查询身份证[439912199008071234](id_number)
                                       intent : request_idcard 1.00


Current slots:
        address: None, business: None, date-time: None, id_number: None, requested_slot: None

------
? The bot wants to run 'number_form', correct?  Yes
Chat History

 #    Bot                                                                                                                              You       
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 1    action_listen
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 2                                                                                                      查询身份证[439912199008071234](id_number)
                                                                                                                      intent: request_idcard 1.00
──────────────────────────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────────────────────────── ───────────────────────────────────────────────eng
 _
      _ The ID number 439912199008071234 to be inquired belongs to Zhang San, a native of Changsha, Hunan, and is currently working in Global Village Property.
      form{"name": "number_form"}
      slot{"id_number": "439912199008071234"}
      form{"name": null}
      slot{"requested_slot": null}


Current slots:
        address: None, business: None, date-time: None, id_number: 439912199008071234, requested_slot: None

------
? The bot wants to run 'action_listen', correct?  Yes

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 Generated a Story  Examples are as follows :























## interactive_story_10
# unhappy path:chitchat stop but continue path
* greet
    - utter_answer_greet
* request_number{"type": "身份证号码"}
    - number_form
    - form{"name": "number_form"}
    - slot{"type": "身份证号码"}
    - slot{"number": null}
    - slot{"business": null}
    - slot{"requested_slot": "number"}
* chitchat
    - utter_chitchat
    - number_form
    - slot{"requested_slot": "number"}
* stop
    - utter_ask_continue
* affirm
    - number_form
    - slot{"requested_slot": "number"}
* form: request_number{"number": "440123199087233467"}
    - form: number_form
    - slot{"number": "440123199087233467"}
    - slot{"type": "身份证号码"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_noworries

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 3. Improve ChitChatAssistant project 3.1 config.yml # zh_jieba_mitie_embeddings_config.yml
















language: "zh"

pipeline:
- name: "MitieNLP"
  model: "data/total_word_feature_extractor_zh.dat"
- name: "JiebaTokenizer"
  dictionary_path: "data/dict"
- name: "MitieEntityExtractor"
- name: "EntitySynonymMapper"
- name: "RegexFeaturizer"
- name: "MitieFeaturizer"
- name: "EmbeddingIntentClassifier"

policies:
  - name: FallbackPolicy
    nlu_threshold: 0.5
    ambiguity_threshold: 0.1
    core_threshold: 0.5
    fallback_action_name: 'action_default_fallback'
  - name: MemoizationPolicy
    max_history: 5
  - name: FormPolicy
  - name: MappingPolicy
  - name: EmbeddingPolicy
    epochs: 500

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
27Considering
 that there are few samples in the current project, the combination of MITIE+EmbeddingPolicy is used here, although the training is a bit slower, However, the accuracy of entity extraction can be guaranteed, and the hit rate of intent recognition can be improved at the same time.

3.2 weather_stories.md
## happy path
* request_weather
    - weather_form
    - form{"name": "weather_form"}
    - form{"name": null}
    
## happy path
* greet
    - utter_answer_greet
* request_weather
    - weather_form
    - form{"name": "weather_form"}
    - form{"name": null}
* thanks
    - utter_noworries

## unhappy path
* greet
    - utter_answer_greet
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* chitchat
    - utter_chitchat
    - weather_form
    - form{"name": null}
* thanks
    - utter_noworries

## very unhappy path
* greet
    - utter_answer_greet
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* chitchat
    - utter_chitchat
    - weather_form
* chitchat
    - utter_chitchat
    - weather_form
* chitchat
    - utter_chitchat
    - weather_form
    - form{"name": null}
* thanks
    - utter_noworries

## stop but continue path
* greet
    - utter_answer_greet
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* stop
    - utter_ask_continue
* affirm
    - weather_form
    - form{"name": null}
* thanks
    - utter_noworries

## stop and really stop path
* greet
    - utter_answer_greet
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* stop
    - utter_ask_continue
* deny
    - action_deactivate_form
    - form{"name": null}

## chitchat stop but continue path
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* chitchat
    - utter_chitchat
    - weather_form
* stop
    - utter_ask_continue
* affirm
    - weather_form
    - form{"name": null}
* thanks
    - utter_noworries

## stop but continue and chitchat path
* greet
    - utter_answer_greet
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* stop
    - utter_ask_continue
* affirm
    - weather_form
* chitchat
    - utter_chitchat
    - weather_form
    - form{"name": null}
* thanks
    - utter_noworries

## chitchat stop but continue and chitchat path
* greet
    - utter_answer_greet
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* chitchat
    - utter_chitchat
    - weather_form
* stop
    - utter_ask_continue
* affirm
    - weather_form
* chitchat
    - utter_chitchat
    - weather_form
    - form{"name": null}
* thanks
    - utter_noworries

## chitchat, stop and really stop path
* greet
    - utter_answer_greet
* request_weather
    - weather_form
    - form{"name": "weather_form"}
* chitchat
    - utter_chitchat
    - weather_form
* stop
    - utter_ask_continue
* deny
    - action_deactivate_form
    - form{"name": null}
        
## interactive_story_1
## 天气 + 时间 + 地点 + 地点
* request_weather
    - weather_form
    - form{"name": "weather_form"}
    - slot{"requested_slot": "date_time"}
* form: inform{"date_time": "明天"}
    - form: weather_form
    - slot{"date_time": "明天"}
    - slot{"requested_slot": "address"}
* form: inform{"address": "广州"}
    - form: weather_form
    - slot{"address": "广州"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"date_time": "后天"} OR request_weather{"date_time": "后天"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "明天"}
    - slot{"address": "广州"}
    - slot{"date_time": "后天"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_answer_thanks

## interactive_story_1
## 天气 + 时间 + 地点 + 时间
* request_weather
    - weather_form
    - form{"name": "weather_form"}
    - slot{"requested_slot": "date_time"}
* form: inform{"date_time": "明天"}
    - form: weather_form
    - slot{"date_time": "明天"}
    - slot{"requested_slot": "address"}
* form: inform{"address": "广州"}
    - form: weather_form
    - slot{"address": "广州"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"address": "上海"} OR request_weather{"address": "深圳"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "明天"}
    - slot{"address": "广州"}
    - slot{"address": "上海"}
    - form{"name": null}
    - slot{"requested_slot": null}
* affirm
    - utter_answer_affirm

## interactive_story_2
## weather/time/location+location
* request_weather{"date_time": "tomorrow", "address": "Shanghai"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time" : "Tomorrow"}
    - slot{"address": "Shanghai"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"address": "Guangzhou"} OR request_weather{"address ": "Guangzhou"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "Tomorrow"}
    - slot{"address": "Shanghai"}
    - slot{"address":"广州"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_answer_thanks

## interactive_story_3
## weather/time/place+time
* request_weather{"address": "Shenzhen", "date_time": "the day after tomorrow"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time" : "The day after tomorrow"}
    - slot{"address": "Shenzhen"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"date_time": "The day after tomorrow"} OR request_weather{"date_time ": "The day after tomorrow"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "The day after tomorrow"}
    - slot{"address":"深圳"}
    - slot{"date_time": "大后天"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_answer_thanks

## interactive_story_2
## weather/time/place+ place+time
* request_weather{"date_time": "tomorrow", "address": "Shanghai"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{" date_time": "tomorrow"}
    - slot{"address": "Shanghai"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"address": "Beijing"} OR request_weather{ "address": "Beijing"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "tomorrow"}
    - slot{"address":"上海"}
    - slot{"address": "北京"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"date_time": "后天"} OR request_weather{"date_time": "后天"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "明天"}
    - slot{"address": "北京"}
    - slot{"date_time": "后天"}
    - form{"name": null}
    - slot{"requested_slot": null}
* affirm
    - utter_answer_affirm

## interactive_story_3
## weather/time/location+location+location
* request_weather{"date_time": "the day after tomorrow", "address": "Beijing"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{" date_time": "The day after tomorrow"}
    - slot{"address": "Beijing"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"address": "Shenzhen"} OR request_weather{ "address": "Shenzhen"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "The day after tomorrow"}
    - slot{"address":"北京"}
    - slot{"address": "深圳"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"address": "南京"} OR request_weather{"address": "南京"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "后天"}
    - slot{"address": "深圳"}
    - slot{"address": "南京"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_answer_thanks

## interactive_story_4
## weather/time/location+time+location
* request_weather{"date_time": "tomorrow", "address": "Changsha"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{" date_time": "Tomorrow"}
    - slot{"address": "Changsha"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"date_time": "The day after tomorrow"} OR request_weather{ "date_time": "the day after tomorrow"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "tomorrow"}
    - slot{"address":"Changsha"}
    - slot{"date_time": "The day after tomorrow"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"date_time": "The day after tomorrow"} OR request_weather{"date_time" : "The day after tomorrow"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "后天"}
    - slot{"address": "长沙"}
    - slot{"date_time": "大后天"}
    - form{"name": null}
    - slot{"requested_slot": null}
* affirm
    - utter_answer_affirm

## interactive_story_5
## weather/time/place+time+time
* request_weather{"date_time": "the day after tomorrow", "address": "Shenzhen"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{" date_time": "the day after tomorrow"}
    - slot{"address": "Shenzhen"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"date_time": "tomorrow"} OR request_weather{ "date_time": "tomorrow"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "the day after tomorrow"}
    - slot{"address":"深圳"}
    - slot{"date_time": "明天"}
    - form{"name": null}
    - slot{"requested_slot": null}
* inform{"address": "广州"} OR request_weather{"address": "广州"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "明天"}
    - slot{"address": "深圳"}
    - slot{"address": "广州"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_answer_thanks

## interactive_story_4
## weather/time + location + time
* request_weather{"date_time": "tomorrow"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "tomorrow"}
    - slot{ "requested_slot": "address"}
* form: inform{"address": "Guangzhou"}
    - form: weather_form
    - slot{"address": "Guangzhou"}
    - form{"name": null}
    - slot{"requested_slot" ": null}
* inform{"date_time": "The day after tomorrow"} OR request_weather{"date_time": "The day after tomorrow"}
    - weather_form
    - form{"name":"weather_form"}
    - slot{"date_time": "明天"}
    - slot{"address": "广州"}
    - slot{"date_time": "后天"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_answer_thanks

## interactive_story_5
## Weather/Location + Time + Time
* request_weather{"address": "Guangzhou"}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"address": "Guangzhou"}
    - slot{ "requested_slot": "date_time"}
* form: inform{"date_time": "The day after tomorrow"}
    - form: weather_form
    - slot{"date_time": "The day after tomorrow"}
    - form{"name": null}
    - slot{"requested_slot" ": null}
* inform{"date_time": "Tomorrow"} OR request_weather{"date_time": "Tomorrow"}
    - weather_form
    - form{"name":"weather_form"}
    - slot{"date_time": "后天"}
    - slot{"address": "广州"}
    - slot{"date_time": "明天"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_answer_thanks
    
## interactive_story_1
## weather/time/location + chit + chit(restart) + ask weather
* request_weather{"date_time": "today", "address": "Guangzhou "}
    - weather_form
    - form{"name": "weather_form"}
    - slot{"date_time": "Today"}
    - slot{"address": "Guangzhou"}
    - form{"name": null}
    - slot{" requested_slot":null}
* chitchat
    - utter_chitchat
* chitchat
    - utter_chitchat
    - action_restart
* request_weather
    - weather_form
    - form{"name": "weather_form"}
    - slot{"requested_slot": "date_time"}
* form: inform{"date_time": "今天"}
    - form: weather_form
    - slot{"date_time": "今天"}
    - slot{"requested_slot": "address"}
* form: inform{"address": "广州"}
    - form: weather_form
    - slot{"address": "广州"}
    - form{"name": null}
    - slot{"requested_slot": null}
* thanks
    - utter_answer_thanks

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

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289

 When constructing Story samples, the Interactive Learning tool is mainly used to ensure that as many unhappy stories as possible can be enumerated, and at the same time, information omission can be prevented when constructing samples Case. In addition, in addition to the case of querying the weather, other cases have been added in this version, and how to use synonyms, custom dictionaries, and regular expressions are listed. For details, see the latest version of the project.

Guess you like

Origin blog.csdn.net/qq_39970492/article/details/131740705