执行方式定义了用于获取用户输入的对话界面,以及用于处理输入并最终执行 Action 的逻辑。
定义对话
现在,您已定义 Action,可以为这些 Action 构建相应的对话。为此,您可以创建 Dialogflow intent,用于定义语法或用户在触发 intent 时需要说的内容,以及相应的执行方式以在 intent 被触发时对其进行处理。
您可以创建任意数量的意图来定义整个对话的语法。
创建意图
点击 Dialogflow 左侧导航菜单中意图菜单项旁边的 + 号。系统会显示 Intent Editor,您可以在其中输入以下信息:
- intent 名称是 IDE 中显示的 intent 的名称。
- 借助上下文,您可以将 intent 的触发范围限定为特定情况。如需了解详情,请参阅关于上下文的 Dialogflow 文档。
- 事件会触发 intent,无需用户说出任何内容。
GOOGLE_ASSISTANT_WELCOME
事件就是一个示例事件,它允许 Google 助理调用您的 Action。此事件用于您的 Action 的默认 Action。如需详细了解内置帮助程序 intent,请参阅我们的文档。 - 训练短语定义用户需要说出什么内容(语法)才能触发 intent。请在此处输入几个短语(5-10 个),说明用户可以说什么来触发 intent。Dialogflow 会自动处理您提供的示例短语的自然变体。
操作和参数定义了要传递给 fulfillment 的数据(如果为此 intent 启用了 fulfillment)。这包括从用户输入解析的数据,以及您可以在执行方式中使用的用于检测触发了哪个 intent 的名称。稍后您将使用此名称将 intent 映射到其对应的执行方式逻辑。如需详细了解如何定义操作,请参阅 Dialogflow 文档中的操作和参数。
Responses 是 Dialogflow Response Builder。利用以下构建器,您可以直接在 Dialogflow 中定义对此意图的响应,而无需调用 fulfillment。此功能对于不需要执行方式的静态响应非常有用。您可以使用它来提供简单的欢迎或道别消息。不过,您可能需要使用执行方式来响应用户的大多数 intent。
Fulfillment 指定是否要在此 intent 触发时调用您的执行方式。您很可能会在 Dialogflow 代理中为大多数意图启用此功能。如需在 intent 中查看此项,您必须在 Fulfillment 菜单中为代理启用 fulfillment。
在 Dialogflow 中构建响应
对于某些 intent,您可能不需要让执行方式返回响应。在这些情况下,您可以使用 Dialogflow 中的响应构建器来创建响应。
在响应区域中,提供要返回给用户的文本回复。默认文本响应是简单的 TTS 文本响应,可以跨多个 Dialogflow 集成工作。响应页面上介绍了 Google 助理的响应。
构建执行方式响应
您的执行方式代码托管在 Action 的网络钩子执行方式逻辑中。例如,在 Silly Name Maker 示例中,可在 Cloud Functions for Firebase 的 index.js
中找到此逻辑。
当使用 fulfillment 的意图被触发时,您会收到来自 Dialogflow 的请求,其中包含有关该意图的信息。然后,您可以通过处理 intent 并返回响应来响应请求。此请求和响应由 Dialogflow 网络钩子定义。
强烈建议您使用 Node.js 客户端库来处理请求并返回响应。以下是使用客户端库的一般流程:
- 初始化 Dialogflow 对象。此对象会自动处理请求并解析请求,以便您可以在执行方式中处理这些请求。
- 创建用于处理请求的函数。这些函数会处理用户输入以及 intent 的其他组件,并构建要返回给 Dialogflow 的响应。
初始化 Dialogflow
对象
以下代码会实例化 Dialogflow
并为 Google Cloud Functions 函数对 Node.js 进行一些样板设置:
'use strict'; const {dialogflow} = require('actions-on-google'); const functions = require('firebase-functions'); const app = dialogflow({debug: true}); app.intent('Default Welcome Intent', (conv) => { // Do things }); exports.yourAction = functions.https.onRequest(app);
public class DfFulfillment extends DialogflowApp { private static final Logger LOGGER = LoggerFactory.getLogger(DfFulfillment.class); @ForIntent("Default Welcome Intent") public ActionResponse welcome(ActionRequest request) { // Do things // ... }
创建用于处理请求的函数
当用户说出触发意图的短语时,您会收到来自 Dialogflow 的请求,您可以使用执行方式中的函数来处理该请求。在此函数中,您通常需要执行以下操作:
- 执行处理用户输入所需的任何逻辑。
- 构建响应以响应触发的 intent。请考虑用户使用的途径来构建适当的响应。如需详细了解如何满足不同 surface 的响应,请参阅surface 功能。
- 通过您的响应调用
ask()
函数。
以下代码展示了如何构建两个 TTS 响应,用于处理一个调用 intent (input.welcome
) 和一个对话框 intent (input.number
),欢迎用户访问您的 Action,并回显用户针对某个 Dialogflow intent 说出的数字,并带有名称:
const app = dialogflow(); app.intent('Default Welcome Intent', (conv) => { conv.ask('Welcome to number echo! Say a number.'); }); app.intent('Input Number', (conv, {num}) => { // extract the num parameter as a local string variable conv.close(`You said ${num}`); });
@ForIntent("Default Welcome Intent") public ActionResponse defaultWelcome(ActionRequest request) { ResponseBuilder rb = getResponseBuilder(request); rb.add("Welcome to number echo! Say a number."); return rb.build(); } @ForIntent("Input Number") public ActionResponse inputNumber(ActionRequest request) { ResponseBuilder rb = getResponseBuilder(request); Integer number = (Integer) request.getParameter("num"); rb.add("You said " + number.toString()); return rb.endConversation().build(); }
上述代码附带的自定义 intent“输入数字”使用 @sys.number
实体从用户话语中提取数字。然后,intent 会向执行方式中的函数发送包含用户号码的 num
参数。
您可以添加一个回退函数,而不是为每个 intent 使用单独的处理程序。在回退函数内,检查哪个 intent 触发了它,并相应地执行适当的操作。
const WELCOME_INTENT = 'Default Welcome Intent'; const NUMBER_INTENT = 'Input Number'; const NUMBER_PARAMETER = 'num'; // you can add a fallback function instead of a function for individual intents app.fallback((conv) => { // intent contains the name of the intent // you defined in the Intents area of Dialogflow const intent = conv.intent; switch (intent) { case WELCOME_INTENT: conv.ask('Welcome! Say a number.'); break; case NUMBER_INTENT: const num = conv.parameters[NUMBER_PARAMETER]; conv.close(`You said ${num}`); break; } });
// you can add a fallback function instead of a function for individual intents @ForIntent("Default Fallback Intent") public ActionResponse fallback(ActionRequest request) { final String WELCOME_INTENT = "Default Welcome Intent"; final String NUMBER_INTENT = "Input Number"; final String NUMBER_ARGUMENT = "num"; // intent contains the name of the intent // you defined in the Intents area of Dialogflow ResponseBuilder rb = getResponseBuilder(request); String intent = request.getIntent(); switch (intent) { case WELCOME_INTENT: rb.add("Welcome! Say a number."); break; case NUMBER_INTENT: Integer num = (Integer) request.getParameter(NUMBER_ARGUMENT); rb.add("You said " + num).endConversation(); break; } return rb.build(); }
无匹配项重新提示
当 Dialogflow 无法匹配意图的训练短语中定义的任何输入语法时,它会触发回退 intent。回退 intent 通常会重新提示用户为您的 Action 提供必要的输入。您可以提供重新提示短语,方法是在回退 intent 的响应 (Response) 区域中指定这些短语,也可以使用网络钩子提供响应。
当用户的响应与您的 Action 的训练短语不匹配时,Google 助理会尝试处理输入。此行为有助于用户在对话过程中更改操作。例如,用户询问“这周放映哪些电影?”,然后在对话过程中改变上下文:“明天的天气怎么样?”在此示例中,由于“明天的天气怎么样?”不是对初始提示触发的对话的有效响应,因此 Google 助理会自动尝试处理匹配并将用户移至适当的对话。
如果 Google 助理找不到与用户输入匹配的适当 Action,就会将用户返回到该 Action 的上下文中。
由于 Google 助理可能会中断您的 Action 来响应有效的非匹配场景,因此请勿使用回退 intent 来执行用户查询。您应仅使用后备 intent 重新提示用户输入有效的内容。
如需创建回退 intent,请执行以下操作:
- 点击 Dialogflow 导航菜单中的意图 (Intents)。
- 点击创建 intent 旁边的 ⋮,然后选择创建后备 intent。(或者,点击 Default Fallback intent 进行修改。)
指定重新提示短语,以回复用户。这些短语应该具有对话性,并且对用户当前的上下文尽可能有用。
在不使用 fulfillment 的情况下执行此操作:在 intent 的 Response 区域指定短语。Dialogflow 会从此列表中随机选择短语并向用户传达,直到触发更具体的意图。
如需使用 fulfillment 执行此操作,请执行以下操作:
- 在 intent 的 Fulfillment 部分中,切换为此 intent 启用 webhook 调用。
- 在您的执行方式逻辑中,应像处理任何其他 intent 一样处理回退 intent,如创建用于处理请求的函数部分中所述。
例如,以下函数使用 Node.js 客户端库中的
conv.data
对象(可用于维护状态的任意数据载荷)存储计数器,用于跟踪回退 intent 的触发次数。如果多次触发,则 Action 会退出。虽然它未在代码中显示,但当非回退 intent 被触发时,您应使其他 intent 将此计数器重置为 0。(如需详细了解如何实现,请参阅 Number Genie 示例。)Node.js app.intent('Default Fallback Intent', (conv) => { conv.data.fallbackCount++; // Provide two prompts before ending game if (conv.data.fallbackCount === 1) { conv.contexts.set(DONE_YES_NO_CONTEXT, 5); conv.ask('Are you done playing Number Genie?'); } else { conv.close(`Since I'm still having trouble, so I'll stop here. ` + `Let's play again soon.`); } });
Java @ForIntent("Default Fallback Intent") public ActionResponse defaultFallback(ActionRequest request) { final String DONE_YES_NO_CONTEXT = "done_yes_no_context"; ResponseBuilder rb = getResponseBuilder(request); int fallbackCount = request.getConversationData().get("fallbackCount") == null ? 0 : (Integer) request.getConversationData().get("fallbackCount"); fallbackCount++; request.getConversationData().put("fallbackCount", fallbackCount); if (fallbackCount == 1) { rb.add(new ActionContext(DONE_YES_NO_CONTEXT, 5)); rb.add("Are you done playing Number Genie?"); } else { rb.add("Since I'm still having trouble, so I'll stop here. Let's play again soon") .endConversation(); } return rb.build(); }
使用上下文
如果您希望 Dialogflow 仅在特定情况下触发回退 intent,请使用上下文。如果您希望针对不同的非匹配场景使用不同的后备 intent,这会非常有用。
- 如果您没有为回退 intent 设置上下文,则会被认为是 Dialogflow 在没有匹配其他意图时触发的全局回退 intent。如果您选择使用其中一个属性,则仅应定义其中一个属性。
如果您为回退 intent 设置输入上下文,则 Dialogflow 会在满足以下条件时触发此回退 intent:
- 用户的当前上下文是 intent 中定义的上下文的超集。
- 没有其他 intent 匹配。
这样,您就可以使用具有不同输入上下文的多个回退 intent,从而针对特定场景自定义非匹配重新提示。
如果您为回退 intent 设置输出上下文,则会在触发和处理回退 intent 后使用户处于同一上下文中。
如需了解详情,请参阅 Dialogflow 上下文。
无输入重新提示
请参阅重新提示页面,详细了解如何应对用户未在 Google Home 等需要持续互动的语音设备上提供进一步输入的情况。