人工智能的兴起触发了用户界面开发领域的范式转变。 多亏了诸如Google Home,Siri和Alexa之类的智能语音激活助手的兴起,用户开始感到按下屏幕上的许多按钮或手动填写表格不仅效率低下而且缓慢,而且过时。
幸运的是,当今有许多基于云的服务可用,这使开发人员可以轻松地向其应用程序添加对话用户界面。 Google的Dialogflow标准版就是这样一种服务。 它是免费的,非常强大的,具有多种语言的版本,并带有大量精心设计的模板。
在本教程中,我将向您展示如何使用Dialogflow为Android创建一个简单的基于文本的会话用户界面。
先决条件
在继续之前,请确保您可以访问:
- 最新版本的Android Studio
- 运行Android 5.0或更高版本的设备或模拟器
1.创建一个代理
使用Dialogflow时,您将始终与代理一起工作,该代理是经过自然语言理解的系统,经过训练可以处理一组特定的用户输入。
要创建您的第一个代理,请使用Google帐户登录Dialogflow 控制台 ,然后按“ 创建代理”按钮。
在弹出的表单中,为代理指定一个合理的名称,然后按“ 创建”按钮。
几秒钟后,您将拥有一个全新的代理。
2.创建意图
用户可以按视觉界面上的按钮来表达自己的意图,而对话界面上则有意图。 这样,在设计良好的对话界面中,用户可以说的所有内容都映射到了意图。 座席的工作只是准确确定当用户说出或键入短语或句子时需要激活哪个意图。
为简单起见,让我们为代理创建一个意图:一种名为WEIGHT
的意图,它使用户可以将公斤的重量转换为磅,反之亦然。
要创建意图,请在控制台中按“ 创建意图”按钮。
在下一个屏幕上,输入意图的名称,然后按添加训练短语按钮。 现在,您将能够提供代理可以用来训练自己的多个短语。 例如,句子“ what is 32 kgs in pounds”对于WEIGHT
意图是一个很好的训练短语。
在键入句子并按Enter键之后,您将看到Dialogflow正确猜测短语“ 32公斤”是可变的。 它还将自动为其创建一个可编程访问的参数,名为unit-weight
,并将其类型设置为@sys.unit-weight
。
同样,它猜测“磅”一词也是可变的,并为其创建了一个名为unit-weight-name
,其类型为@sys.unit-weight-name
。
我建议您输入更多类似的训练短语,并始终确保将unit-weight
和unit-weight-name
参数解析为正确的值。
接下来,按添加响应按钮以键入一些常规响应。 要了解,这些内容将逐字显示给用户。
当您对所提供的训练短语和答案感到满意时,请继续并按“ 保存”按钮以保存意图并开始训练过程,该过程通常会持续不到一分钟。
正如我之前所说,良好的对话界面必须能够处理用户所说的一切。 这意味着我们的代理人还必须能够将其不理解的趣味和句子映射到有效意图上。 由于这是一个非常普遍的要求,因此Dialogflow会自动为我们生成此类意图,它们分别名为Default Welcome Intent
和Default Fallback Intent
。 后者不需要任何更改,而前者则需要任何更改。
Default Welcome Intent
没有任何训练短语,因此您必须提供一些短语。 另外,在本教程中我们将不处理事件,因此您可以删除与其关联的Welcome
事件。
进行更改后,按保存按钮。
3.启用闲聊
大多数用户不太可能将自己限制在您创建的WEIGHT
意图上。 尽管后备意图将能够处理所有无效查询,但是训练代理以使其能够进行闲聊总是一个好主意。 这样做会使它看起来更人性化。
在Dialogflow控制台中,向座席添加闲聊功能非常容易。 您需要做的就是打开“ 聊天”选项卡,然后按“ 启用”按钮。
此时,座席将能够针对许多常见问题生成默认响应。 (可选)您可以自定义这些响应,使其具有独特的个性。 现在,建议您在“ 关于代理”部分中回答一些问题,然后按“ 保存”按钮。
4.获取访问令牌
与Dialogflow代理进行通信时,您的Android应用将需要客户端访问令牌。 要获取它,请单击业务代表姓名旁边的齿轮图标,然后打开“ 常规”选项卡。 向下滚动到API密钥部分,您将能够看到令牌。 记下它,以便以后使用。
5.添加项目依赖项
在与Dialogflow的Web服务进行交互时,我们将使用Fuel网络库,因此在app
模块的build.gradle文件中添加以下implementation
依赖项 :
implementation 'com.github.kittinunf.fuel:fuel-android:1.12.1'
Dialogflow可以处理文本和音频。 但是,在本教程中,我们将仅处理文本。 因此,我们的应用程序将具有类似于聊天应用程序的用户界面。 因此,添加ChatMessageView库作为另一个依赖项。
implementation 'com.github.bassaer:chatmessageview:1.10.0'
最后,通过在AndroidManifest.xml文件中请求以下权限来确保您的应用可以连接到Internet:
<uses-permission android:name="android.permission.INTERNET"/>
6.定义布局
ChatMessageView库的ChatView
小部件提供了完整的聊天用户界面,该界面既可以显示聊天消息,也可以接受用户输入。 通过在我们的布局中使用它,我们可以节省大量时间和精力。 因此,将小部件放置在FrameLayout
小部件内,然后将其添加到布局XML文件中。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.tutsplus.dialogflowtutorial.MainActivity">
<com.github.bassaer.chatmessageview.view.ChatView
android:id="@+id/my_chat_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
如果您在项目中启用了Kotlin Android扩展,则对小部件的引用将作为活动内部的扩展属性提供。
建议您立即运行您的应用,以查看刚刚创建的布局。
7.配置燃料
通过将Fuel客户端专门配置为使用Dialogflow Web服务,可以使您的网络代码更加简洁。 但是,在执行此操作之前,请将之前获得的客户端访问令牌作为编译时常量添加到活动中。
companion object {
private const val ACCESS_TOKEN = "1234567890abcdef"
}
您对Dialogflow Web服务发出的所有HTTP请求都必须具有基于令牌的Authorization
标头。 为避免每次发出请求时都手动创建标头,请使用FuelManager
类的baseHeaders
属性。
FuelManager.instance.baseHeaders = mapOf(
"Authorization" to "Bearer $ACCESS_TOKEN"
)
接下来,将FuelManager
类的basePath
属性设置为Dialogflow Web服务的基本URL。
FuelManager.instance.basePath =
"https://api.dialogflow.com/v1/"
最后,所有HTTP请求都必须始终具有以下配置参数: v
参数指定要使用的协议版本, lang
参数指定要代理返回的语言,以及sessionId
参数,其值可以是any随机字符串。
以下代码显示了如何使用baseParams
属性设置所有参数:
FuelManager.instance.baseParams = listOf(
"v" to "20170712", // latest protocol
"sessionId" to UUID.randomUUID(), // random ID
"lang" to "en" // English language
)
8.配置聊天界面
ChatView
小部件需要两个ChatUser
对象:一个用于用户,一个用于代理。 这些对象用于存储详细信息,例如应与聊天消息一起显示的名称和个人资料图片。 此外,每个ChatUser
对象必须具有与其关联的唯一ID。
以下代码显示了如何创建对象:
val human = ChatUser(
1,
"You",
BitmapFactory.decodeResource(resources,
R.drawable.ic_account_circle)
)
val agent = ChatUser(
2,
"Agent",
BitmapFactory.decodeResource(resources,
R.drawable.ic_account_circle)
)
请注意,该代码使用名为ic_account_circle
的内置资源作为两个对象的化身。 如果需要,可以随意使用任何其他可绘制资源。
9.发送和接收消息
每当用户按下ChatView
小部件的“发送”按钮时,都必须根据他们键入的文本创建Message
对象。为此,可以使用Message.Builder
类。 创建对象时,必须通过调用setUser()
方法来确保它属于人类用户。
一旦准备好Message
对象,就可以将其传递到ChatView
小部件的send()
方法以进行呈现。 下面的代码向您展示如何在ChatView
小部件的setOnClickSendButtonListener()
方法内进行ChatView
。
my_chat_view.setOnClickSendButtonListener(
View.OnClickListener {
my_chat_view.send(Message.Builder()
.setUser(human)
.setText(my_chat_view.inputText)
.build()
)
// More code here
}
)
要将用户的消息实际发送到您的代理,您现在必须向Dialogflow Web服务的/query
端点发出HTTP GET请求。 作为输入,它需要一个query
参数,其值可以是用户键入的任何短语或句子。
作为HTTP响应,您将获得一个JSON文档,其result/fulfillment/speech
值包含代理的回复。
Fuel.get("/query",
listOf("query" to my_chat_view.inputText))
.responseJson { _, _, result ->
val reply = result.get().obj()
.getJSONObject("result")
.getJSONObject("fulfillment")
.getString("speech")
// More code here
}
要在ChatView
小部件内呈现答复,您必须再次构建另一个Message
对象。 但是,这一次,它的所有者必须是代理。 此外,要在右侧显示消息,必须将true
传递给它的setRight()
方法。
my_chat_view.send(Message.Builder()
.setRight(true)
.setUser(agent)
.setText(reply)
.build()
)
如果您现在运行该应用程序,则应该可以与该代理聊天。
但是,如果您要求该应用将公斤重量转换为磅,则只会给出一般性答复。 为了能够实际执行转换,必须首先确定是否触发了WEIGHT
意图。 为此,您可以检查result/metadata/intentName
键的值。
val intent:String? = result.get().obj()
.getJSONObject("result")
.optJSONObject("metadata")
.optString("intentName")
if(intent!! == "WEIGHT") {
// More code here
}
一旦确定触发了WEIGHT
意图,就可以确定unit-weight-name
和unit-weight
参数的值,它们将出现在result/parameters
对象中。
// Convert to what
val unitWeightName = result.get().obj()
.getJSONObject("result")
.getJSONObject("parameters")
.getString("unit-weight-name")
// The weight that needs to be converted
val unitWeight = result.get().obj()
.getJSONObject("result")
.getJSONObject("parameters")
.getJSONObject("unit-weight")
.getDouble("amount")
使用上述值,只需执行简单的数学运算和一条if-else
语句即可执行转换。 要呈现结果,您将需要另一个Message
对象。 它的所有者也必须是代理。
// Perform conversion
val result = if(unitWeightName == "lb") {
unitWeight * 2.20462
} else {
unitWeight / 2.20462
}
// Render result
my_chat_view.send(Message.Builder()
.setRight(true)
.setUser(agent)
.setText("That's ${"%.2f".format(result)} $unitWeightName")
.build()
)
我们的应用程序已准备就绪。 您现在应该可以运行它,以查看它正确执行了所有转换。
结论
现在,您知道如何使用Google Dialogflow创建友好而有用的代理。 在本教程中,您还学习了如何创建一个吸引人的界面,人们在与代理进行通信时可以使用该界面。
要了解有关Dialogflow的更多信息,请参阅其官方文档 。