Skip to content

Architecture

toncho11 edited this page Jul 26, 2019 · 89 revisions

Related pages: Philosophy

We call "architecture" the model we are proposing and which is implemented in KorraAI. KorraAI provides the means to easily implement a new bot following this architecture. The model focuses on certain aspects of the human behavior. These are how to choose and initiate interaction with a human subject and how the behavior changes over time and in respect to the human's responses. It also proposes ways to encode some knowledge and reactions (such as surprise) while interacting with user.

Items Database

Below is the classification of items, often called "interactions". Each interaction usually has a category or "action group".

Pure Facts

Facts are complex items. Pure Facts stored exact information such as as: age, location, binary responses to questions, etc. Pure facts are mainly:

  • question about the user
  • information about the bot

There are also a few additional types of pure facts: UIQuestion, JokeQuestion, System.

Questions and Answers

Facts can contain: a positive response, negative or acknowledgement.

new PureFact
   ("UserLikesBoss", PureFactType.AboutUser, "Do you like your boss?", 
    new string[] { phrases.Yes(), phrases.No() }, "", 
    UIAnswer.Binary,
    "Seriously? Lucky you.", //user's response is "yes"
    "True. Nobody likes his boss!"  //user's response is "no"
   )
);

Alternatively a Fact can use a function that: receives the user's response, validates it, consults other facts or/and the probabilistic models and it generates a response.

new PureFact("UserAge", PureFactType.AboutUser, "How old are you?", phrases.ProcessAge, UIAnswer.Text));

In the example above this is: phrases.ProcessAge.

A Fact can also accept a function that will construct the question. This is needed because for example a question can vary on the information stored in other facts.

More on how to construct a response that looks natural can be found in Building a response.

Uncertain Facts

The Uncertain Fact type stores variable information. Examples are: the user being tired, sleepy, in a good mood etc. The level of uncertainty is always defined in [0..1]. An Uncertain Fact can also be linked to:

  • the bot
  • the user

An uncertain fact is always linked to a probabilistic variable that stores the uncertainty. It usally has 3 predefined answers and each one corresponds to a predefined probability.

new UncertainFact("UserIsTired", 
                   false, 
                   "Do you feel tired?",
                   new VarRef<FiniteDist<bool>>(() => ProbVariables.User.Tired, val => { ProbVariables.User.Tired = val; }),
                   new string[3] { "No", "A little bit", "Yes" }, new double[3] { 0.2, 0.6, 0.9 },
                   UIAnswer.MultiAnswer
                 ));

In this example the probabilistic variable ProbVariables.User.Tired already exists and as the name says it is a characteristic of the user.

Non-Facts

Non-facts are items that usually contain just a text such as: joke, sport recommendation, music suggestion, etc. It can be also non-verbal, for example the list of outfits the bot can choose from.

Interaction loop and Main distribution

We can describe the actions performed by humans with a probabilistic distribution. When we wake up we are mostly hungry, so interactions related to food are more likely. After work interactions related to amusement are also more likely. So a bot can act accordingly. For example the bot can start offering more food suggestions in the morning, at noon and in the evening compared to when it is not the time for eating. This is equivalent to sampling from several categories and increasing the probability of "Food suggestions" around the times when the user eats.

Currently encoded categories with example items (interactions):

              MakeSuggestion  Say a joke, suggest a movie to watch, play a song
     AskUncertanFactQuestion  Ex. "Are you tired?" , how much tired can vary
AskPureFactQuestionAboutUser  Ex. "How old are you?", an exact fact about the user
   SharePureFactInfoAboutBot  Ex. "I am 30 years old", an exact fact about the bot
      ChangeVisualAppearance  Changing clothes from time to time.
       ExpressingMentalState  Ex. "I am definitely in a good mood today!", how much happy can vary

For each category a probability can be assigned depending on the behavior we want to encode. The following is an example of an initial configuration:

              MakeSuggestion  37.5% #####################################
     AskUncertanFactQuestion  0.791% 
AskPureFactQuestionAboutUser  27.7% ###########################
   SharePureFactInfoAboutBot  31.6% ###############################
      ChangeVisualAppearance  1.19% #
       ExpressingMentalState  1.19% #

So here the encoded behavior is focused on three categories which will result in: questions that the bot asks the user, information about bot that is to be shared with the user and also the bot will make a lot of suggestions (for example new movie to watch).

We can have several categories and we can increase or decrease the probability of taking a sample (an item, an interaction) depending on the communication with the user, the time of the day, time elapsed etc. In another example we can increase the "Suggestions" category after 10 minutes of communication. We name "Main distribution" the top distribution that governs the principal categories used to model the bot.

The following is a diagram of the interaction loop:

Once the bot is started it loads a list of its categories, probabilities for each category, items for each category. Next it builds the "Main distribution" and it samples 100 items to be used in interacting with the user. Re-sampling is an expensive operation so a certain delay is encoded between each re-sampling. Every change in the probabilistic model can request a re-sampling. So a check is performed every 5 minutes and if such a requested is made, the re-sampling is performed.

How to store uncertain information

Single state

A single state can be modeled using the Bernoulli distribution.

public static FiniteDist<bool> InAGoodMood = BernoulliF(Prob(0.6)); //tuned by a natural question

0.6 is the required parameter of the Bernoulli distribution where 0.6 is probability of the user who interacting with bot being tired.

Bayesian networks

We are using Probabilistic Programming (PP) to encode Bayesian networks. Let's have a Bayesian network:

It includes three probabilistic variables. This is the equivalent C# probabilistic code:

private static Func<bool, bool, Prob> TellJokeProb = (likesJoke, inGoodMood) => //used below in "TellJoke"
            {
                if (likesJoke && inGoodMood) return Prob(0.4);  //good mood translates to average amount of jokes
                if (likesJoke && !inGoodMood) return Prob(0.9); //not good mood requires more jokes

                return Prob(0.2); //does not like jokes, then the mood does not matter, the result is less jokes
            };
public static FiniteDist<bool> TellJoke =
            from like in User.JokeRate    //tuned by natural question
            from mood in User.InAGoodMood //tuned by natural question
            from joke in BernoulliF(TellJokeProb(like, mood))
            select joke;

A bot designer can set the probabilistic variables himself with some prior knowledge and adjust them alter using a connected fact that will ask the user a natural question that will be translated to the parameters of type of probabilistic variable used. Bayesian network is a compact model that allows us to ask questions for each one of the variables, no matter the direction of causality.

Note on Probabilistic programming (PP)

  • Inference and modelling are completely separate; we can define models without caring how we're going to do inference
  • Probabilistic inference is built-in and its intrinsic remain hidden
  • Models can be specified in a declarative manner
  • Models compose freely, allowing us to construct complex models from simpler ones

Here we are using the Probabilistic Programming library that uses C# as base language. This library calculates an exact solution and it uses the three rules of probabilistic reference: the chain rule, the total probability rule (the law of total probability) and the Bayes’ rule. For complex Bayes networks with more dependencies and a large number of variables an exact factored or sampling algorithm should be used such as Variable Elimination and Importance Sampling.

KorraAI uses a single programming language C# for all generic code, bot control and probabilistic programming. Sometimes this is not the case and incorporating several programming languages in one project leads to many problems.

More examples can be found in Probabilistic Examples.

Encoding surprise

Another behavior pattern is surprise. It can be modeled by a Bayesian network where a probability of observed evidence (POE) is used to calculate the probability of the information provided by the user. We can have directly the answer of the user and we can also infer it from a model, a Bayesian network. Some inference algorithms are specifically designed for calculating POE. We can design a threshold whether the system should issue a statement expressing a surprise/disbelief or ask for confirmation.

Handling depleted categories

While performing sampling from par example the Main distribution we can run out items for a specific category. In this case a solution is to for example set the probability of this category to 0 and continue the sampling. Unfortunately that creates a problem because after normalization the probability that was before taken by the depleted category will now go proportionally to the other categories that still have items. While this sounds logical increasing the probability of a certain category might be unwanted. KorraAI provides a place, a C# method to handle these situations. A solution is to provide new probabilities for each category once a depleted category is detected. This might be difficult to encode and manage. Another solution is to set some categories to be fixed while others are allowed to shrink or expand in therms of probability. This means that the normalization is applied to only the categories that are allowed to shrink and expand and not on all categories.

Examples of adjusting the main distribution and speech adaptation

Once the interactions are generated additional operations are performed by the "SpeechAdaptation" module in KorraAI:

  • if the name of the user is available, the name is used for certain Suggestions "Peter, I suggest going out for a pizza this evening"
  • adding a distribution where in 1/3 of the cases after a joke the bot makes a pause and it says "That was joke, you got that, right?".
  • two interactions are always put together "the bot presents his/hers name" and the "bot asks about the user's name". It is because this is how it happens in real human to human conversation
  • some interactions are removed in the beginning. For example after the initial greeting it would not be very smart to play a song, this might actually bore the user, who usually has high expectations when the user starts the interaction with the bot

All these are already used in KorraAI and can be easily re-used for new bots.

Selecting an item inside a category

Please refer to Distribution inside a category.

Repeatable questions

These are questions usually that are related to uncertain information or state. Certain states can change over time. A distribution can say that a repeatable question "Are you tired" should be asked no sooner than 30 minutes.

Cognitive distributions

The bot actor appearance provided by KorraAI can be further adjusted by providing distributions over:

  • time between interactions, for example Normal(3.7, 0.25) where mean = 3.7, variance = 0.25, in seconds
  • smiles - how often the bot smiles, for example Normal(12, 3) where mean = 12, variance = 3, in seconds
  • timeout of questions, for example Normal(25, 4) where mean = 25, variance = 4, in seconds
  • time the bot's eyes stay focused on the user after started talking, Normal(7, 1.2) where mean = 7, variance = 1.2, in seconds

We can also improve things by making a difference between a new interaction and an interaction that is a reaction to the user's response. A reaction is one of the three "PositiveResponse", "NegativeResponse" or "Acknowledgement". In this case we can choose to decrease the time between interactions to another distribution for example Uniform(0.3,0.8) seconds in believing that reactions are usually faster then starting a completely new topic.

Memory between sessions

All the items that are used, should not be repeated on the next session with the bot. That is not entirely true, it actually depends on the amount of time that has elapsed between the sessions and how good is the human memory. Would the human interlocutor remember the bot's name, age, jokes said by the bot from the previous session? These are subject to research. KorraAI saves the already used interactions using the PersistentData class. The bot also plays music, but songs are not saved for the next session. A human can listen to a song more than one time and considering the number of songs available it seems reasonable. On the hand in KorraAI there is an option to activate a condition where if the time between sessions is more than 2 days, then the bot will again present himself: name, age, etc. Indeed what should be re-enabled is a question of design.

Supporting several languages

The provided example Joi is encoded in English which means that the items in each category are in English. KorraAI can speak in another language and this has already been done to some degree for French and Japanese.

Next you should continue with the Tutorial.