BaseChatbot


level_3


What is it

A BaseChatbot is an abstract class that is the parent class of all custom Chatbot implementations. This class must be inherited to implement your own Chatbot on the tablet.

See also javadoc: BaseChatbot.

How to use it

Create a class that inherits BaseChatbot and implement the required methods, especially replyTo.

An instance of this custom class can then be provided to the method that creates a Chat action, along with any other chatbot.

Warning

A custom Chatbot requires an available remote speech recognition.

In order to handle properly any error or slowness, it is recommended to create a standard QiChatbot, able to provide a minimal vocal interaction to the robot and to catch the not understood cases.

For further details, see: Managing not understood cases.

It is also possible to implement a simple fallback behavior thanks to a ReplyReaction with ReplyPriority.FALLBACK.

For further details see: StandardReplyReaction.

Chatbot interface

To be used within a Chat, a Chatbot should at least implement:

  • replyTo(phrase, locale): Produces a ReplyReaction based on a given input phrase.
  • acknowledgeHeard(phrase, locale): Informs the Chatbot with the last phrase heard by the robot. It will be called anytime a reply not given by this Chatbot has been chosen.
  • acknowledgeSaid(phrase, locale): Informs the Chatbot with the last phrase said by the robot. It will be called anytime a ChatbotReaction not given by this Chatbot has been chosen.

Extend BaseChatbot to implement your own Chatbot, according to this interface.

See also javadoc: Chatbot and BaseChatbot.

Implementing replyTo

This method is called by the chat when the robot hears something recognized as a Phrase. The returned value is a possible reply that the chat may select as its answer, among other chatbots replies (if any).

The replyTo implementation must return a StandardReplyReaction which is the standard implementation of ReplyReaction. The ReplyReaction that is returned may obviously be run as an uttered sentence, but it may also be any other action or combination of actions, such as an animation synchronized with an uttered answer for example.

The different effective behaviors of the replies, according to the input phrase, may be provided by several implementations of BaseChatbotReaction that can be passed as a parameter of the returned StandardReplyReaction.

If the chatbot has no answer for the input phrase, the implementation of replyTo must throw a RuntimeException.

String heard = phrase.getText();

if (heard.equals("hello")) {
    return new StandardReplyReaction(
                new MyChatbotReaction(getQiContext(), "Hi"),
                ReplyPriority.NORMAL);
} else if (heard.contains("dance")) {
    return new StandardReplyReaction(
                new MyAnimatedChatbotReaction(getQiContext()),
                ReplyPriority.NORMAL);
} else {
    return new StandardReplyReaction(
                new MyDefaultChatbotReaction(getQiContext(), heard),
                ReplyPriority.FALLBACK);
}

For further details, see: StandardReplyReaction.

ReplyReaction

As an answer to a phrase, a Chatbot will create a ReplyReaction. A reply reaction contains at least:

  • The ReplyPriority, used by the chat to determine which ReplyReaction is chosen for a given user sentence.
  • The ChatbotReaction, executed if the chat chooses it to answer a given user sentence.

ReplyReaction implementations to be used StandardReplyReaction and StandardAutonomousReaction.

See also javadoc:

ChatbotReaction

A ChatbotReaction should at least have the following interface:

  • runWith(SpeechEngine): runs the ChatbotReaction. The ChatbotReaction will most likely make the robot speak but can also make him move, display things on the tablet and so on.
  • stop(): stops the ChatbotReaction. The stop method will be automatically called when Chat action stopped. Developer should ensure every action, robotic or not, will be stopped.

Extend BaseChatbotReaction to implement your own ChatbotReaction.

See also javadoc: ChatbotReaction and BaseChatbotReaction.

Optional methods to implement

The acknowledgeHeard and acknowledgeSaid methods may be implemented if necessary. Their default implementation is to do nothing. These methods are called by the chat to inform your custom chatbot that another chatbot’s reply has been chosen.

This is an opportunity for a chatbot to keep the context of the discussion, even if its own replies are not selected by the chat engine.

@Override
public void acknowledgeHeard(Phrase phrase, Locale locale) {
    Log.i(TAG, "Last phrase heard by the robot and whose selected answer is not mine: " + phrase.getText());
}

@Override
public void acknowledgeSaid(Phrase phrase, Locale locale) {
    Log.i(TAG, "Another chatbot answered: " + phrase.getText());
}

If the chat contains only one chatbot, these methods will never be called.

Getting started

Creating a simple greeting chatbot

public class GreetingChatbot extends BaseChatbot {

    private static final String TAG = "GreetingChatbot";

    static private List<String> greetings = Arrays.asList( "hello", "hi", "good morning", "good afternoon", "good evening" );

    public GreetingChatbot(QiContext context) {
        super(context);
    }

    @Override
    public StandardReplyReaction replyTo(@NonNull Phrase phrase, Locale locale) {
        if (greetings.contains(phrase.getText())) {
            return new StandardReplyReaction(
                new MyChatbotReaction(getQiContext(), "Hello you"),
                ReplyPriority.NORMAL);
        } else {
            return new StandardReplyReaction(
                new MyChatbotReaction(getQiContext(), "I can just greet you"),
                ReplyPriority.FALLBACK);
        }
    }

    @Override
    public void acknowledgeHeard(Phrase phrase, Locale locale) {
        Log.i(TAG, "Last phrase heard by the robot and whose chosen answer is not mine: " + phrase.getText());
    }

    @Override
    public void acknowledgeSaid(Phrase phrase, Locale locale) {
        Log.i(TAG, "Another chatbot answered: " + phrase.getText());
    }


    class MyChatbotReaction extends BaseChatbotReaction {

        private String answer;
        private Future<Void> fsay;

        MyChatbotReaction(final QiContext context, String answer) {
            super(context);
            this.answer = answer;
        }

        @Override
        public void runWith(SpeechEngine speechEngine) {

            Say say = SayBuilder.with(speechEngine)
                                .withText(answer)
                                .build();
            fSay = say.async().run();

            try {
                fSay.get(); // Do not leave the method before the actions are done
            } catch (ExecutionException e) {
                Log.e(TAG, "Error during Say", e);
            } catch (CancellationException e) {
                Log.i(TAG, "Interruption during Say");
            }
        }

        @Override
        public void stop() {
            if (fSay != null) {
                fSay.cancel(true);
            }
        }
    }
}