Discuss


level_1 - [Deprecated: use Chat with a QiChatbot instead]


Goal - Give Pepper the ability to discuss around a topic.

// Create a topic.
Topic topic = TopicBuilder.with(qiContext)
                          .withResource(R.raw.animals)
                          .build();

// Build the action.
Discuss discuss = DiscussBuilder.with(qiContext)
                                .withTopic(topic)
                                .build();

// Run the action asynchronously.
discuss.async().run();

Typical usage - You want Pepper to have an elaborate conversation with someone.


How it works

Discuss with topics

To build a Discuss, you use Topics:

A Topic is made of rules that describe the logic of the conversation. It mostly contains what Pepper should answer when someone talks to him.

Typically, a Topic is created from a topic file (.top), and uses QiChat syntax.

See also QiChat Language.

Preparing a discuss

You want Pepper to be able to discuss around a topic.

Topic topic = TopicBuilder.with(qiContext)
                          .withResource(R.raw.animals)
                          .build();

Discuss discuss = DiscussBuilder.with(qiContext)
                                .withTopic(topic)
                                .build();

discuss.async().run();

Managing discuss end

You want to handle the different cases leading to the end of the discuss.

Topic topic = TopicBuilder.with(qiContext)
                          .withResource(R.raw.game)
                          .build();

Discuss discuss = DiscussBuilder.with(qiContext)
                                .withTopic(topic)
                                .build();

String endReason = discuss.run();
switch (endReason) {
    case "sword":
        buySword();
        break;
    case "bow":
        buyBow();
        break;
}

game.top content:

topic: ~game()

u: (buy) Do you want to buy a sword or a bow?
    u1: (sword) This is a really sharp sword. ^endDiscuss(sword)
    u1: (bow) This bow can draw arrows far away. ^endDiscuss(bow)

Retrieving recommendations

Recommendations give you access to the verbal inputs available to the user to interact with the robot when a Discuss action is running.

The Discuss action provides 3 different recommendation types:

  • global recommendations,
  • focused topic recommendations,
  • scope recommendations.

Global recommendations:

Global recommendations correspond to all the activated u: rules loaded in the Discuss action.

PhraseSet globalRecommendations = discuss.globalRecommendations();

Focused topic recommendations:

Focused topic recommendations correspond to all the activated u: rules in the currently focused topic.

PhraseSet focusedTopicRecommendations = discuss.focusedTopicRecommendations();

Scope recommendations:

Scope recommendations correspond to all the activated sub-rules of the current scope.

PhraseSet scopeRecommendations = discuss.scopeRecommendations();

Example:

top1.top:

topic:~top1()

u:(color) what's your favourite color
    u1:(blue) marine blue or sky blue
        u2:(marine) Oh, like the sea then $color=marineblue
        u2:(sky) Oh, like the sky then $color=skyblue
    u1:(yellow) Oh, like the sand then $color=yellow
    u1:(green) Oh, like the grass then $color=green

top2.top:

topic:~top2()

u:(dogs) so you want to speak about dogs?
u:(cats) so you want to speak about cats?

Recommendation results:

// Discuss is running

discuss.globalRecommendations().getPhrases(); // ["color", "dogs", "cats"]

// User says "color"

discuss.globalRecommendations().getPhrases(); // ["color", "dogs", "cats"]
discuss.focusedTopicRecommendations().getPhrases(); // ["color"]
discuss.scopeRecommendations().getPhrases(); // ["yellow", "blue", "green"]

// User says "dogs"

discuss.globalRecommendations().getPhrases(); // ["color", "dogs", "cats"]
discuss.focusedTopicRecommendations().getPhrases(); // ["dogs", "cats"]
discuss.scopeRecommendations().getPhrases(); // []

Observing the Discuss states

Listening

To be understood, the user should only speak to the robot when the Discuss is in a listening state.

The listening state of the Discuss is accessible at any time, via the getListening method and a listener:

Boolean isListening = discuss.getListening();
discuss.addOnListeningChangedListener(new Discuss.OnListeningChangedListener() {
    @Override
    public void onListeningChanged(Boolean listening) {
        // Called when the listening state changes.
    }
});

Hearing

You can be notified when the robot hears human voice via the getHearing method and a listener:

Boolean isHearing = discuss.getHearing();
discuss.addOnHearingChangedListener(new Discuss.OnHearingChangedListener() {
    @Override
    public void onHearingChanged(Boolean hearing) {
        // Called when the hearing state changes.
    }
});

Saying

The phrase the robot is saying is accessible via the getSaying method and a listener:

Phrase saying = discuss.getSaying();
discuss.addOnSayingChangedListener(new Discuss.OnSayingChangedListener() {
    @Override
    public void onSayingChanged(Phrase sayingPhrase) {
        // Called when the robot speaks.
    }
});

When the robot is not saying anything, the String contained in the Phrase is empty.

Observing the user input

You can observe what the robot hears via a listener:

discuss.addOnHeardListener(new Discuss.OnHeardListener() {
    @Override
    public void onHeard(Phrase heardPhrase) {
        // Called when a phrase was recognized.
    }
});

Sometimes the robot detects human voice but cannot determine the content of the phrase said:

discuss.addOnNoPhraseRecognizedListener(new Discuss.OnNoPhraseRecognizedListener() {
    @Override
    public void onNoPhraseRecognized() {
        // Called when no phrase was recognized.
    }
});

Observing the reply type

After the robot heard human speech, there can be 3 different cases:

  • Normal reply
  • Fallback reply
  • No reply

Normal reply

The type of the reply is normal when the robot provides a provides an answer provided by any rule except fallback rules.

my_topic.top:

topic: ~normal_topic()

u: (hello) Hello!

It is accessible via a listener:

discuss.addOnNormalReplyFoundForListener(new Discuss.OnNormalReplyFoundForListener() {
    @Override
    public void onNormalReplyFoundFor(Phrase input) {
        // Called when the reply has a normal type.
    }
});

Fallback reply

The type of the reply is fallback when a phrase was heard but the robot cannot provide a good answer, for example it matches a rule containing a e:Dialog/NotUnderstood:

fallback_reply.top:

topic: ~fallback_reply()

u: (e:Dialog/NotUnderstood) I don't understand

In the case where the robot determined the content of the phrase said, the input parameter will contain the phrase, otherwise, it will be empty.

discuss.addOnFallbackReplyFoundForListener(new Discuss.OnFallbackReplyFoundForListener() {
    @Override
    public void onFallbackReplyFoundFor(Phrase input) {
        // Called when the reply has a fallback type.
    }
});

No reply

If the user input doesn’t match a rule and there is no fallback reply, the robot will not reply.

In the case where the robot determined the content of the phrase said, the input parameter will contain the phrase, otherwise, it will be empty.

discuss.addOnNoReplyFoundForListener(new Discuss.OnNoReplyFoundForListener() {
    @Override
    public void onNoReplyFoundFor(Phrase input) {
        // Called when no reply was found for the input.
    }
});

Performance & Limitations

Discuss or Say/Listen?

Using Discuss is relevant when you want Pepper to be able to answer with relevance to a human input. If you want Pepper to ultimately say something specific or listen to a precise human input, you should use Say and Listen instead.

Exclusions with other actions

Do not start a Discuss while a Chat, Say or a Listen is running: the Discuss would fail.