Skip to content

ResponseSelectors

Dilyara Zharikova (Baymurzina) edited this page Dec 28, 2022 · 2 revisions

Response Selectors in Dream

Dialogue Management Schema

Dream is built upon an open-source DeepPavlov Agent framework, so Dream is based on DeepPavlov Agent Architecture. Dialogue management in DeepPavlov Agent Framework is a coordinated orchestra of Skill Selector and Response Selector components. The Skill Selector picks up a list of skills that will try to generate responses for the current context. The Response Selector chooses the final response that can also be composed of several different hypotheses.

Unlike Skill Selector, Response Selector service should select the final version of response. The service returns a name of the selected skill, text (might be overwritten from the original skill response) and confidence (also might be overwritten):

{"skill_name": "chitchat",
 "text": "Hello, Joe!",
 "confidence": 0.3}

Also it’s possible for a Response Selector to overwrite any human or bot attributes:

{"skill_name": "chitchat",
 "text": "Hello, Joe!",
 "confidence": 0.3,
 "human_attributes": {"name": "Ivan"}}

Response Selector's Approaches

An Empirical Formula to Enforce the Confidence-based Bot Responses

In a modular dialogue system each skill usually returns a response candidate and confidence in the given response candidate. The confidence is a floating-point value from 0 to 1, where 1 corresponds to the highest level of skill’s confidence.

Let’s describe a response selection algorithm based on confidence maximization. This approach has two major disadvantages: (1) several candidate responses could have equal confidence values, (2) confidence values from different skills have different origins. While the first problem can be solved with random choice or choice based on some rules, the second problem`s solution would lead to the unfairness of the comparison. Indeed, the distributions of confidence values for neural network models can differ significantly, and, moreover, confidence values for template-based skills are usually assigned by the developer. Wherein, (1) skills are usually developed by different authors, so it is impossible to create a standard confidence-assignment methodology due to a wide variety of scripts and approaches; (2) there is no guarantee that a developer tuned the confidence values; (3) there could be a necessity to take into account an additional information about the current candidate response.

Therefore, during the “Alexa Prize Challenge 3”, the Response Selector of the Dream Socialbot was based on the empirical formula combining skill’s confidence and candidate response evaluation. The latter is provided by CoBot Conversation Evaluation model that evaluates the response in the dialogue context according to the following parameters:

  • correspondence to the topic;
  • whether the response is interesting;
  • user`s engagement;
  • comprehensiveness of the response;
  • correctness.

Firstly, the Response Selector filters out “bad” response candidates, e.g. containing obscenity, inappropriate expressions, toxicity, or having a high probability the user will stop the dialogue after the given response. In order to diversify the social bot’s lexicology, we decrease the confidence value if the sentence in the candidate responses is repeated within the dialogue in the short term.

Secondly, the Response Selector utilizes an empirical formula to calculate a final score combining confidence value and candidate response evaluation predictions. By the way, the Response Selector can combine multiple response candidates into a final response. The Response Selector may add linking questions to some of the statements and point the dialogue to one of the scripted skills. Thus we can smoothly move a user from one scripted topic to another one.

Response Selector based on tags

The Dream combines many different skills, including template-based, retrieval, and generative skills. Based on the “Alexa Prize Challenge 3” other teams`technical reports, we found out that they covered the most popular topics (e.g., movies, books, sports, and others) and created scripts to ensure a deep controllable conversation. We added some prioritization rules for scripted responses, but in general we were not able to provide a smooth dialogue flow using the different types of skills. Thus, during the “Alexa Prize Challenge 4” we were focusing on a new Response Selector that can smoothly combine skills of different origins. The generalized approaches to dialogue management are described in the figure below.

We proposed two additional tags for each response candidate: (1) continuation flag, (2) response parts. Both tags are assigned by the skill proposing it, so there could be response candidates with the same tags or tags with none of the response candidates assigned to it. The continuation flag is built in order to show the ability to continue the conversation on the next turn after the proposed response candidate. Response parts for each response candidate is a list indicating which response parts are present in the response candidate. There are three types of the response parts: acknowledgement (a rephrasing of what the user just said), body (the main part of the response), and a prompt (phrase for further development of the dialogue).

Generally, in the tag-based Response Selector all response candidates based on the annotations and tags assigned by skills are divided into priority groups, and the final response candidate is chosen within the group with the highest priority as one with the highest score from the trainable ranking model.

Firstly, the selection algorithm checks for the special user intents that a special component can immediately respond to. If the user wants to switch or request a particular topic, priority is given to candidates with prompts. Finally, if the user’s dialogue act requires some action by the socialbot (for example, if a user requests an opinion, an expression of opinion is expected from the socialbot), priority is given to response candidates containing the required dialogue acts. In other cases, the algorithm uses the following priorities:

(1) candidate response by a scripted skill with which a dialogue is in progress;

(2) script-part candidate responses containing entities (not necessarily named entities) from the last user’s utterance;

(3) one-step candidate responses containing entities from the last user’s utterance;

(4) other script-part candidate responses;

(5) other one-step candidate responses.

Script-part candidate responses are those from scripted skills which will be able to continue the script if the current candidate will be returned to the user. One-step candidate responses are not a part of the script or the last utterance in the script.

Developing Own Response Selector

You can use the following code as the foundation of your own rule-based Response Selector:

#!/usr/bin/env python

import logging
import numpy as np
import time

from flask import Flask, request, jsonify
from os import getenv
import sentry_sdk


logging.basicConfig(format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO)
logger = logging.getLogger(__name__)

app = Flask(__name__)


@app.route("/respond", methods=["POST"])
def respond():
    st_time = time.time()

    dialogs = request.json["dialogs"]
    response_candidates = [dialog["utterances"][-1]["hypotheses"] for dialog in dialogs]

    selected_skill_names = []
    selected_responses = []
    selected_confidences = []

    for i, dialog in enumerate(dialogs):
        confidences = []
        responses = []
        skill_names = []

        for skill_data in response_candidates[i]:
            if skill_data["text"] and skill_data["confidence"]:
                logger.info(f"Skill {skill_data['skill_name']} returned non-empty hypothesis with non-zero confidence.")

            confidences += [skill_data["confidence"]]
            responses += [skill_data["text"]]
            skill_names += [skill_data["skill_name"]]

        best_id = np.argmax(confidences)

        selected_skill_names.append(skill_names[best_id])
        selected_responses.append(responses[best_id])
        selected_confidences.append(confidences[best_id])

    total_time = time.time() - st_time
    logger.info(f"rule_based_response_selector exec time = {total_time:.3f}s")
    return jsonify(list(zip(selected_skill_names, selected_responses, selected_confidences)))


if __name__ == "__main__":
    app.run(debug=False, host="0.0.0.0", port=3000)

Registering Own Response Selector

Registering a new response selector is done by adding its configuration to the docker-compose.yml located in the root directory, and to pipeline_conf.json located in the /agent subdirectory of the repository. After adding new skill, it should be built and run using docker-compose -f docker-compose.yml up --build _response_selector_name_, followed by building and running agent by running command docker-compose -f docker-compose.yml build agent followed by docker-compose -f docker-compose.yml up agent.

You must register a response selector before you can test it with your own copy of Deepy.

Resources