QiChatbot – Mastering Dynamic concept

Goal

In this tutorial, we will create a dynamic QiChatbot, using Dynamic concepts.

For further details, see: QiChat dynamic.

Prerequisites

Before stepping in this tutorial, you should:

Let’s start a new project

  • Start a new project, let’s call it DynamicConceptsPepper.
  • Robotify it and make sure it implements the QiSDK & the Robot Life Cycle.

For further details, see: Creating a robot application.

Creating the topic file

Create a new topic file named greetings_dynamic.top for the English (en) language.

Add the following content to this file:

topic: ~greetings_dynamic()

dynamic: greetings

u:(~greetings) ~greetings

For more details about the syntax, see: QiChat - Syntax.

Getting a dynamic concept

In this section, we will see how to retrieve the greetings dynamic concept present in our topic.

A dynamic concept is represented by an EditablePhraseSet. It contains a list of Phrase objects that constitute the elements related to the dynamic concept.

Store an EditablePhraseSet in your MainActivity:

// Store the greetings dynamic concept.
private EditablePhraseSet greetings;

To retrieve a dynamic concept, use the dynamicConcept method on a QiChatbot instance. It takes the dynamic concept name as parameter (here “greetings”).

In the onRobotFocusGained method, add the following code:

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

// Create a new QiChatbot.
QiChatbot qiChatbot = QiChatbotBuilder.with(qiContext)
            .withTopic(topic)
            .build();

// Create a new Chat action.
Chat chat = ChatBuilder.with(qiContext)
            .withChatbot(qiChatbot)
            .build();

// Get the greetings dynamic concept.
greetings = qiChatbot.dynamicConcept("greetings");

// Run the Chat action asynchronously.
chat.async().run();

Updating a dynamic concept

Add content

To add a Phrase to a dynamic concept, use the addPhrases method. Add the following code to your MainActivity class:

private void addGreeting(final String greeting) {
    if (greetings != null) {
        greetings.async().addPhrases(Collections.singletonList(new Phrase(greeting)));
    }
}

Remove content

To remove a Phrase from a dynamic concept, use the removePhrases method. Add the following code to your MainActivity class:

private void removeGreeting(final String greeting) {
    if (greetings != null) {
        greetings.async().removePhrases(Collections.singletonList(new Phrase(greeting)));
    }
}

Testing the update

Let’s test our code using a list representing the greetings.

Modify your activity_main.xml file with the following code:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusableInTouchMode="true"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:hint="Greeting"
        android:inputType="text"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintRight_toLeftOf="@+id/add_button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/add_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Add"
        app:layout_constraintBottom_toBottomOf="@+id/editText"
        app:layout_constraintLeft_toRightOf="@+id/editText"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/editText" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:fadeScrollbars="false"
        android:scrollbarStyle="outsideInset"
        android:scrollbars="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText" />

</android.support.constraint.ConstraintLayout>

The dynamic concept content must represent the greetings of the list.

Add the following field to the MainActivity class:

private GreetingAdapter greetingAdapter;

And add the following code in the onCreate method:

final EditText greetingEditText = findViewById(R.id.editText);

// Create adapter for recycler view.
greetingAdapter = new GreetingAdapter(this::removeGreeting);

// Setup recycler view.
RecyclerView recyclerView = findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(greetingAdapter);

// Add greeting on add button clicked.
Button addButton = findViewById(R.id.add_button);
addButton.setOnClickListener(v -> {
    String greeting = greetingEditText.getText().toString();
    greetingEditText.setText("");
    // Add greeting only if new.
    if (!greeting.isEmpty() && !greetingAdapter.containsGreeting(greeting)) {
        addGreeting(greeting);
    }
});

The GreetingAdapter implementation is available here: GitHub.

Modify the addGreeting and removeGreeting methods to update the list:

private void addGreeting(final String greeting) {
    if (greetings != null) {
        greetings.async().addPhrases(Collections.singletonList(new Phrase(greeting)))
                .andThenConsume(Qi.onUiThread((Consumer<Void>) ignore -> greetingAdapter.addGreeting(greeting)));
    }
}

private void removeGreeting(final String greeting) {
    if (greetings != null) {
        greetings.async().removePhrases(Collections.singletonList(new Phrase(greeting)))
                .andThenConsume(Qi.onUiThread((Consumer<Void>) ignore -> greetingAdapter.removeGreeting(greeting)));
    }
}

Let’s try it

github_icon The sources for this tutorial are available on GitHub.

Step Action

Install and run the application.

For further details, see: Running an application.

Choose “Mastering dynamic concept”.

The list of greetings contains “Hello” and “Hi”.

Say “Hello”.

Pepper says “Hello”.

Add “Good morning” and say “Hi”.

Pepper says “Good morning”.

/sites/default/files/repository/64_rst_pepper/public/source/_build/html/_images/dynamic_concept.png

You are now able create a dynamic QiChatbot!