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
For further details, see: Creating a robot application.
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.
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 var greetings: EditablePhraseSet? = null
// 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.
val topic: Topic = TopicBuilder.with(qiContext)
.withResource(R.raw.greetings_dynamic)
.build()
// Create a new QiChatbot.
val qiChatbot: QiChatbot = QiChatbotBuilder.with(qiContext)
.withTopic(topic)
.build()
// Create a new Chat action.
val 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()
// 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();
Add content
To add a Phrase to a dynamic concept, use the addPhrases
method.
Add the following code to your MainActivity
class:
private fun addGreeting(greeting: String) {
greetings?.async()?.addPhrases(Collections.singletonList(Phrase(greeting)))
}
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 fun removeGreeting(greeting: String) {
greetings?.async()?.removePhrases(Collections.singletonList(Phrase(greeting)))
}
private void removeGreeting(final String greeting) {
if (greetings != null) {
greetings.async().removePhrases(Collections.singletonList(new Phrase(greeting)));
}
}
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/greeting_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/greeting_editText"
app:layout_constraintLeft_toRightOf="@+id/greeting_editText"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/greeting_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/greeting_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 var greetingAdapter: GreetingAdapter? = null
private GreetingAdapter greetingAdapter;
And add the following code in the onCreate
method:
// Create adapter for recycler view.
greetingAdapter = GreetingAdapter(this::removeGreeting)
// Setup recycler view.
recyclerView.layoutManager(LinearLayoutManager(this))
recyclerView.adapter(greetingAdapter)
// Add greeting on add button clicked.
add_button.setOnClickListener {
val greeting: String = greeting_editText.text
greetingEditText.text = ""
// Add greeting only if new.
if (greeting.isNotEmpty() && !greetingAdapter.containsGreeting(greeting)) {
addGreeting(greeting)
}
}
final EditText greetingEditText = findViewById(R.id.greeting_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:
greetings.async().addPhrases(listOf(Phrase(greeting))).andThenConsume(Qi.onUiThread(Consumer {
greetingAdapter.addGreeting(greeting)
}))
private fun addGreeting(greeting: String) {
greetings?.async()?.addPhrases(singletonList(Phrase(greeting)))
?.andThenConsume(Qi.onUiThread(Consumer<Void> { greetingAdapter?.addGreeting(greeting) }))
}
private fun removeGreeting(greeting: String) {
greetings?.async()?.removePhrases(singletonList(Phrase(greeting)))
?.andThenConsume(Qi.onUiThread(Consumer<Void> { greetingAdapter?.removeGreeting(greeting) }))
}
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)));
}
}
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”. |
You are now able create a dynamic QiChatbot!