设置 Web 终结点
重要
自定义命令将于 2026 年 4 月 30 日停用。 自 2023 年 10 月 30 日起,无法在 Speech Studio 中创建新的自定义命令应用程序。 与此更改相关的是,LUIS 将于 2025 年 10 月 1 日停用。 自 2023 年 4 月 1 日起,无法创建新的 LUIS 资源。
本文介绍了如何在自定义命令应用程序中设置相应 Web 终结点,以便从客户端应用程序发出 HTTP 请求。 你将完成以下任务:
- 在自定义命令应用程序中设置 Web 终结点
- 在自定义命令应用程序中调用 Web 终结点
- 接收 Web 终结点响应
- 将 Web 终结点响应集成到自定义 JSON 有效负载,从 C# UWP SPEECH SDK 客户端应用程序中发送和直观呈现该响应
先决条件
- Visual Studio 2019
- Azure AI 语音资源密钥和区域:在 Azure 门户上创建语音资源。 有关详细信息,请参阅创建多服务资源。
- 自定义命令应用(请参阅使用自定义命令创建语音助理)
- 启用了语音 SDK 的客户端应用(请参阅与使用语音 SDK 的客户端应用程序集成)
使用 Azure 函数应用部署外部 Web 终结点
对于本教程,需要一个 HTTP 终结点,用于维护在自定义命令应用程序的 TurnOnOff 命令中设置的所有设备的状态。
如果已具有要调用的 Web 终结点,请跳到下一部分。 或者,如果要跳过此部分,下一部分提供了有关可以使用的默认托管 Web 终结点的详细信息。
Azure 函数的输入格式
接下来,你会使用 Azure Functions 部署终结点。 下面是传递给 Azure 函数的自定义命令事件的格式。 编写 Azure 函数应用时,请使用此信息。
{
"conversationId": "string",
"currentCommand": {
"name": "string",
"parameters": {
"SomeParameterName": "string",
"SomeOtherParameterName": "string"
}
},
"currentGlobalParameters": {
"SomeGlobalParameterName": "string",
"SomeOtherGlobalParameterName": "string"
}
}
下表介绍了此输入的关键属性:
属性 | 说明 |
---|---|
conversationId | 对话的唯一标识符。 请注意,此 ID 可以由客户端应用生成。 |
currentCommand | 对话中当前启用的命令。 |
name | 命令的名称。 parameters 属性是一个包含参数当前值的映射。 |
currentGlobalParameters | 类似于 parameters 的映射,但用于全局参数。 |
对于 DeviceState Azure 函数,示例自定义命令事件如下所示。 这会作为函数应用的输入。
{
"conversationId": "someConversationId",
"currentCommand": {
"name": "TurnOnOff",
"parameters": {
"item": "tv",
"value": "on"
}
}
}
自定义命令应用的 Azure 函数输出
如果 Azure 函数的输出由自定义命令应用使用,则它应显示为以下格式。 有关详细信息,请参阅从 Web 终结点更新命令。
{
"updatedCommand": {
"name": "SomeCommandName",
"updatedParameters": {
"SomeParameterName": "SomeParameterValue"
},
"cancel": false
},
"updatedGlobalParameters": {
"SomeGlobalParameterName": "SomeGlobalParameterValue"
}
}
客户端应用程序的 Azure 函数输出
如果 Azure 函数的输出由客户端应用程序使用,则输出可采用客户端应用程序所需的任何形式。
对于我们的 DeviceState 终结点,Azure 函数的输出由客户端应用程序(而不是自定义命令应用程序)使用。 Azure 函数的示例输出应如下所示:
{
"TV": "on",
"Fan": "off"
}
此输出应写入到外部存储,以便可以维护设备的状态。 外部存储状态会在下面的与客户端应用程序集成部分中使用。
部署 Azure 函数
我们提供了一个示例,可以将它配置和部署为 Azure Functions 应用。 若要为我们的示例创建存储帐户,请执行以下步骤。
- 创建表存储以保存设备状态。 在 Azure 门户中,按名称 devicestate 创建“存储帐户”类型的新资源 。
- 从“devicestate -> 访问密钥”复制“连接字符串”值。 你需要将此字符串机密添加到下载的示例函数应用代码中。
- 下载示例函数应用代码。
- 在 Visual Studio 2019 中打开下载的解决方案。 在 Connections.json 中,将 STORAGE_ACCOUNT_SECRET_CONNECTION_STRING 替换为步骤 2 中的机密 。
- 下载 DeviceStateAzureFunction 代码。
若要将示例应用部署到 Azure Functions,请执行以下步骤。
- 部署 Azure Functions 应用。
- 等待部署成功,然后将部署的资源置于 Azure 门户上。
- 在左窗格中选择“函数”,然后选择“DeviceState” 。
- 在新窗口中,选择“代码 + 测试”,然后选择“获取函数 URL” 。
在自定义命令中设置 Web 终结点
让我们将 Azure 函数与现有的自定义命令应用程序关联起来。
在此部分中,你将使用现有的默认 DeviceState 终结点。 如果使用 Azure 函数或其他方式创建了自己的 Web 终结点,请使用该终结点,而不是默认的 https://webendpointexample.chinacloudsites.cn/api/DeviceState
。
打开之前创建的自定义命令应用程序。
转到“Web 终结点”,选择“新建 Web 终结点”。
设置 建议值 说明 名称 UpdateDeviceState Web 终结点的名称。 URL https://webendpointexample.chinacloudsites.cn/api/DeviceState
你希望自定义命令应用与之通信的终结点的 URL。 方法 POST 允许的与终结点之间的交互(如 GET、POST)。 头文件 键:app,值:取 applicationId 的前 8 位 要包含在请求头中的标头参数。 注意
- 使用 Azure Functions 创建的示例 Web 终结点,该终结点与保存电视和风扇设备状态的数据库挂钩。
- 建议的标头只是示例终结点需要而已。
- 若要确保标头值在示例终结点中具有唯一性,请使用 applicationId 的前 8 位。
- 在实际中,Web 终结点可以是管理设备的 IOT 中心的终结点。
选择“保存” 。
调用 Web 终结点
转到“TurnOnOff”命令,选择完成规则下的“ConfirmationResponse”,然后选择“添加操作” 。
在“新建操作类型”下,选择“调用 Web 终结点”
在“编辑操作 - 终结点”中,选择“UpdateDeviceState”,这是我们创建的 Web 终结点 。
在“配置”中,使用以下值:
设置 建议值 说明 终结点 UpdateDeviceState 要在此操作中调用的 Web 终结点。 查询参数 item={SubjectDevice}&&value={OnOff} 要追加到 Web 终结点 URL 的查询参数。 正文内容 不可用 请求的正文内容。 注意
- 建议的查询参数只是示例终结点需要而已
在“成功时 - 要执行的操作”中,选择“发送语音响应” 。
在“简单编辑器”中,输入
{SubjectDevice} is {OnOff}
。设置 建议值 说明 要执行的操作 发送语音响应 对 Web 终结点的请求成功时要执行的操作 注意
- 还可以使用
{YourWebEndpointName.FieldName}
直接访问 http 响应中的字段。 例如:{UpdateDeviceState.TV}
- 还可以使用
在“失败时 - 要执行的操作”中,选择“发送语音响应”
在“简单编辑器”中,输入
Sorry, {WebEndpointErrorMessage}
。设置 建议值 说明 要执行的操作 发送语音响应 对 Web 终结点的请求失败时要执行的操作 注意
{WebEndpointErrorMessage}
是可选项。 如果不希望公开任何错误消息,则可以随意将其删除。- 在示例终结点中,我们发送了带有详细错误消息的 http 响应,以返回常见错误(例如缺少标头参数)的错误消息。
在测试门户中试用
- 响应成功后,进行保存,训练并测试。
- 响应失败后,删除其中一个查询参数,保存,重新训练并测试。
与客户端应用程序集成
在向客户端应用程序发送自定义命令活动中,你添加了“向客户端发送活动”操作。 无论“调用 Web 终结点”操作是否成功,都会向客户端应用程序发送活动。 但是,通常只有当调用 Web 终结点成功时才希望将活动发送到客户端应用程序。 本例中,这即为设备状态成功更新的时候。
- 删除之前添加的“向客户端发送活动”操作。
- 编辑调用 Web 终结点:
- 在“配置”中,确保“查询参数”是
item={SubjectDevice}&&value={OnOff}
- 在“成功时”中,更改“要执行的操作”,以向客户端发送活动
- 将下面的 JSON 复制到“活动内容”
{ "type": "event", "name": "UpdateDeviceState", "value": { "state": "{OnOff}", "device": "{SubjectDevice}" } }
- 在“配置”中,确保“查询参数”是
现在,只有当对 Web 终结点的请求成功时才向客户端发送活动。
创建同步设备状态的视觉对象
将以下 XML 添加到 MainPage.xaml
中 EnableMicrophoneButton 块的上方。
<Button x:Name="SyncDeviceStateButton" Content="Sync Device State"
Margin="0,10,10,0" Click="SyncDeviceState_ButtonClicked"
Height="35"/>
<Button x:Name="EnableMicrophoneButton" ......
.........../>
同步设备状态
在 MainPage.xaml.cs
中,添加引用 using Windows.Web.Http;
。 将以下代码添加到 MainPage
类。 此方法会向示例终结点发送 GET 请求,并提取应用的当前设备状态。 请务必将 <your_app_name>
更改为自定义命令 Web 终结点的标头中所使用的内容。
private async void SyncDeviceState_ButtonClicked(object sender, RoutedEventArgs e)
{
//Create an HTTP client object
var httpClient = new HttpClient();
//Add a user-agent header to the GET request.
var your_app_name = "<your-app-name>";
Uri endpoint = new Uri("https://webendpointexample.chinacloudsites.cn/api/DeviceState");
var requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint);
requestMessage.Headers.Add("app", $"{your_app_name}");
try
{
//Send the GET request
var httpResponse = await httpClient.SendRequestAsync(requestMessage);
httpResponse.EnsureSuccessStatusCode();
var httpResponseBody = await httpResponse.Content.ReadAsStringAsync();
dynamic deviceState = JsonConvert.DeserializeObject(httpResponseBody);
var TVState = deviceState.TV.ToString();
var FanState = deviceState.Fan.ToString();
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() =>
{
State_TV.Text = TVState;
State_Fan.Text = FanState;
});
}
catch (Exception ex)
{
NotifyUser(
$"Unable to sync device status: {ex.Message}");
}
}
试试看
- 启动应用程序。
- 选择“同步设备状态”。
如果你在上一部分中使用turn on tv
测试了应用,便会发现电视显示为“开”。 - 选择“启用麦克风”。
- 选择“对话”按钮。
- 说出
turn on the fan
。 风扇的可视状态应更改为“开”。