如果您曾经与基于语音的个人助理(例如Siri或Google Now)交谈过,或者与活跃在消息传递平台(如Facebook Messenger和Kik)上的众多基于文本的机器人之一聊天,您可能会意识到它的乐趣,直观性和趣味性。强大的会话用户界面即可。 但是,由于大多数自然语言都极其复杂,因此从头开始创建此类接口往往很困难。 幸运的是,有IBM Watson 。
通过使用IBM Watson Conversation服务,您可以在几分钟内创建AI驱动的对话用户界面,通常只需几行代码。 在本教程中,我将向您介绍该服务,并向您展示如何在Android应用中使用它。
先决条件
要充分利用本教程,您需要具备以下条件:
- IBM Bluemix帐户
- 最新版本的Android Studio
- 运行Android 4.4或更高版本的设备
1.创建对话服务
在使用IBM Watson Conversation API之前,必须在IBM Bluemix平台上创建一个Conversation服务并获取其登录凭证。 为此,登录到Bluemix 控制台 ,导航至Services> Watson ,然后按Create Watson服务按钮。 在下一个屏幕上,从可用服务目录中选择“ 对话 ”。
在接下来显示的配置表单中,为服务键入一个适当的名称,然后按“ 创建”按钮。
2.创建一个对话工作区
对话服务只有在至少具有一个与其相关联的对话工作空间时才能工作。 现在,您可以将工作空间视为规则和配置详细信息的集合,这些规则和配置详细信息定义了会话UI的功能和个性。
Bluemix控制台具有一个易于使用的工具,使您可以创建和管理工作空间。 要启动它,请按启动工具按钮。
在下一个屏幕中,按创建按钮创建一个新的工作区。 在弹出的对话框中,给工作区起一个有意义的名称,并为其选择一种语言。
一旦创建了工作空间,就应该向它添加意图,实体和对话框详细信息。
在意图定义用户可以使用您的会话UI执行的动作的同时,实体定义与这些动作相关的对象。 例如,在句子“为我预订从纽约到芝加哥的机票”中,“预订机票”将是意图,而“纽约”和“芝加哥”将是实体。 对话框详细信息定义了对话UI生成的实际响应以及对话如何进行。
步骤1:建立意图
在本教程中,我们将创建一个非常简单的Android聊天机器人,该机器人能够执行以下操作:
- 问候用户
- 自我介绍
- 引用励志名言
因此,我们的聊天机器人需要三个意图。
按创建新按钮创建第一个意图。 在显示的表单中,将意图命名为#Greeting ,提供一些用户可能用于该意图的示例单词或句子,例如“ hi”和“ hello”,然后按“ 完成”按钮。
Watson Conversation服务的最好之处在于,它会使用您提供给意图的样本用户输入来智能地自我训练。 因此,它将能够响应那些样本输入的多种变化。 例如,它将能够正确匹配单词和短语,例如“ howdy”,“ good morning”和“ yo!”。 遵守#Greeting意图。
再次按下创建新按钮以创建下一个意图。 将其命名为#Name ,并提供以下用户示例。
同样,将第三个意图命名为#RequestQuote ,并提供以下用户示例。
步骤2:建立对话方块
我们的聊天机器人非常简单,我们不需要为其定义任何实体。 因此,我们现在可以直接开始指定它如何响应我们创建的每个意图。
首先转到“ 对话框”选项卡,然后按“ 创建”按钮。 在下一个屏幕中,您会看到自动为您创建了两个对话框节点:一个名为Welcome的对话框,用来迎接用户,另一个名为Anything else ,用于捕获机器人无法理解的输入。
现在,让我们保持“ 其他”节点不变 ,并配置“ 欢迎”节点。 在弹出的对话框中, 如果机器人识别出字段中输入#Greeting ,然后添加一些响应。 显然,您添加的响应越多,聊天机器人将变得更像人类。
接下来,通过单击“ 添加节点”按钮为#Name意图创建一个新节点。 再次填写适当的表格。
#RequestQuote意图的节点将略有不同。 我们不会手动输入一些鼓舞人心的引号作为该节点的响应,因为这样做会使我们的漫游器过于静态和无趣。 相反,我们的Android chatbot应该能够从外部API获取引号。 因此,此节点的响应应为句子,要求机器人在机器人搜索新报价时等待。
至此,我们的工作区已准备就绪。 您可以通过单击语音气球图标立即对其进行测试。 随意用各种句子进行测试,以确保它与正确的意图相关联。
步骤3:确定凭证
为了能够在Android应用中使用会话服务,您需要其用户名和密码。 此外,您将需要“对话”工作区的ID。 因此,转到“ 部署”部分并切换到“ 凭据”选项卡。
现在,您应该能够看到所需的凭据。 记下它们之后,您可以关闭Bluemix控制台。
3. Android Studio项目设置
尽管可以使用任何Android网络库与对话服务进行交互,但是使用Watson Java SDK是一个更好的主意,因为它提供了非常直观和高级的API。 要将其添加到您的Android Studio项目中,请在app
模块的build.gradle文件中添加以下compile
依赖项 :
compile 'com.ibm.watson.developer_cloud:java-sdk:3.7.2'
此外,我们将需要Fuel网络库从远程服务器上获取鼓舞人心的报价,还需要设计支持库来使用一些Material Design小部件。
compile 'com.android.support:design:23.4.0'
compile 'com.github.kittinunf.fuel:fuel-android:1.9.0'
Fuel和Watson Java SDK都要求您的应用程序具有INTERNET
权限,因此不要忘记在项目的清单文件中要求它:
<uses-permission android:name="android.permission.INTERNET"/>
最后,打开res / values / strings.xml文件,并添加会话服务的用户名和密码,以及会话工作区的ID作为<string>
标签:
<string name="username">1234567890-abde-12349-abdef</string>
<string name="password">ABCD123456</string>
<string name="workspace">abdefg1234567890-abcdef</string>
现在,您可以按立即同步按钮以完成项目设置。
4.定义布局
在本教程中,我们将创建一个基于文本的机器人。 因此,我们的应用布局应包含一个EditText
小部件(用户可以在其中键入消息)和一个TextView
小部件(可以在其中显示用户与机器人的对话)。 (可选)您可以将EditText
小部件放置在TextInputLayout
容器内,以确保其遵循“材料设计”准则。
将TextView
小部件放置在ScrollView
容器内也是一个好主意,以确保长时间的对话不会被截断。
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:id="@+id/user_input_container">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Message"
android:id="@+id/user_input"
android:imeOptions="actionDone"
android:inputType="textShortMessage"/>
</android.support.design.widget.TextInputLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/user_input_container">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/conversation"
android:textSize="16sp"
/>
</ScrollView>
请注意,我们已经将EditText
小部件的imeOptions
属性的值设置为actionDone
。 这使用户可以在完成输入消息后,按下虚拟键盘上的“完成”按钮。
5.使用对话服务
Watson SDK的ConversationService
类具有与会话服务进行通信所需的所有方法。 因此,在Activity
类中需要做的第一件事就是创建它的实例。 它的构造函数要求版本日期,服务的用户名和密码。
final ConversationService myConversationService =
new ConversationService(
"2017-05-26",
getString(R.string.username),
getString(R.string.password)
);
接下来,要能够使用布局XML文件中存在的小部件,必须使用findViewById()
方法获取对它们的引用。
final TextView conversation = (TextView)findViewById(R.id.conversation);
final EditText userInput = (EditText)findViewById(R.id.user_input);
用户完成输入消息的键入后,将按其虚拟键盘上的“完成”按钮。 为了能够收听该按钮按下事件,必须将OnEditorActionListener
添加到EditText
小部件。
userInput.setOnEditorActionListener(new TextView
.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView tv,
int action, KeyEvent keyEvent) {
if(action == EditorInfo.IME_ACTION_DONE) {
// More code here
}
return false;
}
});
在侦听器内部,可以调用EditText
小部件的getText()
方法来获取用户的消息。
TextView
小部件将同时显示用户的消息和机器人的回复。 因此,使用消息的append()
方法将消息追加到TextView
小部件。
final String inputText = userInput.getText().toString();
conversation.append(
Html.fromHtml("<p><b>You:</b> " + inputText + "</p>")
);
// Optionally, clear edittext
userInput.setText("");
用户的消息必须发送到包装在MessageRequest
对象中的“对话”服务。 您可以使用MessageRequest.Builder
类轻松创建一个。
MessageRequest request = new MessageRequest.Builder()
.inputText(inputText)
.build();
请求准备就绪后,必须将其连同工作区的ID一起传递给ConversationService
对象的message()
方法。 最后,要将消息实际发送到对话服务,必须调用enqueue()
方法。
由于enqueue()
方法是异步运行的,因此,您还需要一个ServiceCallback
对象来获取服务的响应。
myConversationService
.message(getString(R.string.workspace), request)
.enqueue(new ServiceCallback<MessageResponse>() {
@Override
public void onResponse(MessageResponse response) {
// More code here
}
@Override
public void onFailure(Exception e) {}
});
在onResponse()
方法内部,可以调用MessageResponse
对象的getText()
方法来获取会话服务的响应。
final String outputText = response.getText().get(0);
现在,您可以使用其append()
方法再次将响应附加到TextView
小部件。 但是,请确保在runOnUiThread()
方法中执行此操作,因为您当前位于其他线程上。
runOnUiThread(new Runnable() {
@Override
public void run() {
conversation.append(
Html.fromHtml("<p><b>Bot:</b> " +
outputText + "</p>")
);
}
});
我们的机器人几乎准备就绪。 如果您尝试运行该应用程序,则可以针对#Greeting和#Name意图从应用程序中获取正确的响应。 但是,它仍然不能背诵励志名言。 因此,我们现在必须添加代码以显式查找#RequestQuote意图并手动生成响应。
要从MessageResponse
对象中提取检测到的意图的名称,必须调用其getIntents()
方法,该方法将返回MessageResponse.Intent
对象的列表,选择第一项,然后调用其getIntent()
方法。
if(response.getIntents().get(0).getIntent()
.endsWith("RequestQuote")) {
// More code here
}
有许多带有免费API的网站,您可以使用它们来获取鼓舞人心的报价。 Forismatic是其中之一。 它的REST API提供了纯文本引号,您可以在应用程序中直接使用引号。
要向Forismatic API的URL发出HTTP请求,您需要做的就是调用Fuel
类的get()
方法。 由于该方法异步运行,因此必须通过调用responseString()
方法并将Handler
对象传递给该方法来处理HTTP响应。
在处理程序的success()
方法内部,您可以简单地将引号附加到TextView
小部件。 以下代码向您展示了如何:
String quotesURL =
"https://api.forismatic.com/api/1.0/" +
"?method=getQuote&format=text&lang=en";
Fuel.get(quotesURL)
.responseString(new Handler<String>() {
@Override
public void success(Request request,
Response response, String quote) {
conversation.append(
Html.fromHtml("<p><b>Bot:</b> " +
quote + "</p>")
);
}
@Override
public void failure(Request request,
Response response,
FuelError fuelError) {
}
});
机器人现已完成,将能够为我们添加到工作区中的所有意图生成正确的响应。
结论
如今,对话用户界面风靡一时。 它们是如此易于使用,以至于每个人都喜欢它们。 在本教程中,您学习了使用IBM Watson Conversation服务在Android平台上创建此类接口的基础。
服务还有很多可以做的。 要了解更多信息,可以参考官方文档 。
翻译自: https://code.tutsplus.com/tutorials/create-chatbots-on-android-with-ibm-watson--cms-29387