在处理消息之前进行调用
每当客户提交输入时,预消息网络挂钩都会调用外部服务或应用程序。 外部服务可以先于助手处理信息。
如果您希望在助手处理每条新消息之前触发网络挂钩,请为助手添加一条预消息网络挂钩。
如果您使用的是自定义通道,则预发消息网络钩子仅适用于v2"/message
应用程序接口(无状态和有状态)。 有关更多信息,请参阅 API 参考。 所有内置通道集成都使用此 API。
您可以在以下用例中使用预发消息网络钩子:
-
将客户的输入翻译成助理使用的语言。
-
检查并删除任何个人身份信息,例如客户可能提交的电子邮件地址或社会保险号。
您可以将此网络挂钩与消息后网络挂钩配合使用。 例如,消息后的网络挂钩可以执行一些操作,例如将响应翻译回客户的语言,或者添加因隐私原因而被删除的信息。 有关更多信息,请参阅 在处理消息后进行调用。
对于使用专用端点的环境,请记住网络钩子会通过互联网发送流量。
要获得经典体验,如果需要在对话期间执行一次性操作,请使用对话网络钩子。 例如,当助手收集到所有必需的详细信息(如账号、用户 ID 和账户密 码)时,就满足了条件。 有关更多信息,请参阅从对话发起程序化调用。
定义 Webhook
您可以定义一个 Webhook URL,用于预处理每一条传入信息。
对外部服务的程序化调用必须满足以下需求:
-
调用必须是 POST HTTP 请求。
-
请求主体必须是 JSON 对象 (
Content-Type: application/json
)。 -
呼叫必须在 30 秒或更短时间内返回。
如果外部服务仅支持 GET 请求,或需要在运行时动态指定 URL 参数,则可考虑创建一个中间服务,接受带有 JSON 有效负载(包含任何运行时值)的 POST 请求。 然后,中间服务可以向目标服务发出请求,将这些值作为 URL 参数传递,然后将响应返回给对话框。
请勿在部署了助手并与客户进行交互的生产环境中设置和测试 Webhook。
过程
要添加 Webhook 详细信息,请完成以下步骤:
-
在助手中,转至 环境 并打开要在其中配置 Webhook 的环境。
-
单击
图标以打开环境设置。
-
在“环境设置”页面上,单击 预消息 Webhook。
要获得经典体验,请完成以下步骤:
-
对于要配置的助手,单击
图标,然后选择设置。
-
单击 Webhooks > Pre-message webhook。
-
-
将 预消息 Webhook 开关设置为 已启用。
-
在同步事件中,从以下选项中选择一个:
-
如果出现错误,则继续处理用户输入,不更新 webhook。
-
如果 webhook 调用失败,则向客户端返回错误信息。
有关更多信息,请参阅“为预处理配置 webhook 错误处理”。
-
-
在 URL 字段中,添加要向其发送 HTTP POST 请求调出的外部应用程序的 URL。
例如,您可以编写 Cloud Functions Web 操作,以检查消息是否使用非英语语言,并将其发送到 Language Translator 服务以将其转换为英语。 指定网络操作的 URL,如本例所示:
https://us-south.functions.cloud.ibm.com/api/v1/web/my_org_dev/default/translateToEnglish.json
您必须指定一个使用 SSL 协议的 URL,因此请指定一个以
https
开头的 URL。 -
要配置消息前网络钩子的身份验证,请单击编辑身份验证。 有关详细说明,请参阅 为信息前和信息后网络钩子定义身份验证方法。
- 要获得经典体验,请填写“秘密”字段。 如需了解更多信息,请参阅“为经典体验添加秘密”。
-
在“超时”字段中,指定助手在返回错误前等待网络钩子响应的时间长度(秒)。 超时持续时间不能短于 1 秒或长于 30 秒。
-
在“标头”部分,单击“添加标头 +”,一次添加一个要传递给服务的标头。
对于经典体验,服务会自动发送带有 JWT 的授权标头。 如果您想自己处理授权,请添加自己的授权标头,然后服务会使用它。
如果您调用的外部应用程序返回响应,它可能会以不同的格式发送响应。 Webhook 要求以 JSON 格式格式化响应。 下表说明了如何添加标头,以表明您希望返回 JSON 格式的结果值。
头示例 头名称 头值 Content-Type
application/json
-
保存标题值后,字符串将被替换为星号,无法再次查看。
-
这将自动保存 Webhook 详细信息。
仅为经典体验添加一个秘密
要获得经典体验,请在密文字段中添加私人密钥,以便与外部服务的身份验证请求一起传递:
-
以文本字符串形式输入密钥,如
purple unicorn
。 -
最多使用 1 024 个字符。
-
不要使用上下文变量。
外部服务负责检查和验证密文。 如果不需要标记,可指定任何字符串。 该字段不能为空。
要在输入密码时查看密码,请在输入前单击显示密码图标。 保存秘密后,星号将取代字符串,您将无法再次查看。
有关如何使用此字段的更多信息,请参阅 仅适用于经典体验的 Webhook 安全性。
为预处理配置网络钩子错误处理功能
如果 webhook 调用失败,您可以决定是否在预处理步骤中返回错误信息。 您有两个选择:
-
如果出现错误,则继续处理用户输入,不更新 webhook:助手会忽略错误,并在不更新网络钩子结果的情况下处理信息。 如果预处理有用但不是必须的,可以考虑这一选项。
-
如果 webhook 调用失败,则向客户端返回错误信息:如果在助手处理信息之前预处理至关重要,请选择此选项。
当您启用 “如果 webhook 调用失败则向客户端返回错误” 时,一切都会停止,直到预处理步骤成功完成。
定期测试外部流程,找出潜在故障。 如有必要,可调整此设置以防止信息处理中断。
测试 Webhook
在为生产环境中使用的助手启用网络钩子之前,请对其进行大量测试。
当有消息发送给您的助手进行处理时,网络挂钩就会被触发。
对 Webhook 进行故障诊断
以下错误代码可帮助您跟踪可能迂到的问题的原因。 例如,如果您具有 Web 聊天集成,那么当您提交的每条测试消息都返回一条消息 (例如 There is an error with the message you just sent, but feel free to ask me something else
) 时,您会知道您的 Webhook 存在问题。 如果显示此消息,请使用 REST API 工具(如cURL,发送测试 "/message
API 请求,以便查看错误代码和返回的完整消息。
错误代码和消息 | 描述 |
---|---|
422 Webhook 响应了无效的 JSON 主体 | 网络钩子的 HTTP 响应体无法解析为 JSON。 |
422 验证 Webhook 响应时出错 | 网络钩子的 HTTP 响应体不是有效的 /message 体。 |
422 Webhook 响应了 [500] 状态码 |
您调用的外部服务存在问题。 代码失败或外部服务器拒绝了请求。 |
500 处理器异常: [connections to all backends failing] |
在 Webhook 微服务中发生错误。 无法连接到后端服务。 |
仅限经典体验的 Webhook 安全性
对于经典体验,通过验证随请求一起发送的 JSON 网络令牌(JWT)来验证 webhook 请求。 Webhook 微服务会自动生成 JWT,并在每次 Webhook 调用时通过 Authorization
标头发送:
-
对于新的网络钩子或通过编辑身份验证更新的网络钩子,授权标头将被忽略。
-
对于已保存身份验证标头的现有网络钩子,“编辑身份验证”选项被禁用。
-
更新现有 Webhook 以使用新的身份验证配置将改变其行为。
如果需要测试 JWT 验证,可以在外部服务中添加代码。 例如,如果在秘密字段中指定 purple unicorn
,则可以使用以下代码:
const jwt = require('jsonwebtoken');
...
const token = request.headers.authentication; // grab the "Authentication" header
try {
const decoded = jwt.verify(token, 'purple unicorn');
} catch(err) {
// error thrown if token is invalid
}
请求主体
了解预消息网络钩子请求体的格式非常有用,这样您的外部代码就可以处理它。
有效内容包含 /message
(有状态或无状态) v2 API 请求的请求主体。 事件名称 "message_received
表示该请求由预消息 Webhook 生成。 有关消息请求主体的更多信息,请参阅 API 参考。
{
"payload" : { Copy of request body sent to /message }
"event": {
"name": "message_received"
}
}
跳过助理处理,只为经典体验
对于经典体验,信息前网络钩子的增强功能允许 watsonx Assistant 跳过信息处理,直接返回来自网络钩子的响应。 该功能可通过在网络钩子 HTTP 响应中设置 x-watson-assistant-webhook-returnheader
激活。
准备工作
要获得经典体验,请完成以下步骤:
- 在您的网络挂钩的 HTTP 回复中,将任何值都添加到
x-watson-assistant-webhook-returnheader
。 - 确保网络挂钩响应包含一个有效的消息响应,该响应根据 watsonx Assistant 的要求进行格式化。
该功能使网络挂钩能够动态控制对话流程,在需要时立即做出响应。
响应主体
从 Webhook 接收 POST 请求的服务必须返回 JSON 对象 (Accept: application/json
)。
回复正文必须具有以下结构:
{
"payload": {
...
}
}
payload
必须包括请求正文中的 payload
。 您的代码可以修改属性值或修改上下文变量,但返回的消息有效载荷必须遵循 message
方法模式。 更多信息,请参阅 API 参考。
示例 1
此示例显示如何检查输入文本的语言,并将语言信息附加到输入文本字符串。
在预消息 webhook 配置页面中,可指定以下值:
对于经典体验来说,“秘密”字段没有任何价值。
- URL:
https://us-south.functions.appdomain.cloud/api/v1/web/e97d2516-5ce4-4fd9-9d05-acc3dd8ennn/default/check_language
- 头名称:Content-Type
- 头值:application/json
预消息 Webhook 调用名为 "check_language
的IBM Cloud FunctionsWeb 操作。
check_language
Web 操作中的 node.js 代码如下所示。
let rp = require("request-promise");
function main(params) {
console.log(JSON.stringify(params))
if (params.payload.input.text !== '') {
// Send a request to the Watson Language Translator service to check the language of the input text.
const options = { method: 'POST',
url: 'https://api.us-south.language-translator.watson.cloud.ibm.com/instances/572b37be-09f4-4704-b693-3bc63869nnnn/v3/identify?version=2018-05-01',
auth: {
'username': 'apikey',
'password': 'nnn'
},
headers: {
"Content-Type":"text/plain"
},
body: [
params.payload.input.text
],
json: true,
};
return rp(options)
.then(res => {
params.payload.context.skills["actions skill"].user_defined["language"] = res.languages[0].language;
console.log(JSON.stringify(params))
//Append "in" plus "the language code" to the input text, surrounded by parentheses.
const response = {
body : {
payload : {
input : {
text : params.payload.input.text + ' ' + '(in ' + res.languages[0].language + ')'
},
},
},
};
return response;
})
}
return {
body : params
}
};
要测试 Webhook,请单击 预览。 提交文本 Buenos días
。 助手可能无法理解输入,并从 Anything else 节点返回响应。 但是,如果转至助手的“分析”页面并打开 对话,那么可以查看已提交的内容。 请检查最新的用户对话。 日志显示用户输入为 Buenos días (in es)
。 括号中的 es
表示西班牙语的语言代码,因此 Webhook 有效并识别提交的文本是西班牙语短语。
示例 2
此示例显示如何检查入局消息的语言,如果它不是英语,请在将其提交给助手之前将其翻译为英语。
在IBM Cloud Functions中定义一系列网络操作。 序列中的第一个操作将检查传入文本的语言。 序列中的第二个操作将文本从其原始语言转换为英语。
在预消息 webhook 配置页面中,可指定以下值:
对于经典体验来说,“秘密”字段没有任何价值。
- URL:
https://us-south.functions.appdomain.cloud/api/v1/web/e97d2516-5ce4-4fd9-9d05-acc3dd8ennn/default/translation_sequence
- 头名称:Content-Type
- 头值:application/json
序列中第一个 Web 操作的 node.js 代码如下所示:
let rp = require("request-promise");
function main(params) {
console.log(JSON.stringify(params))
if (params.payload.input.text !== '') {
const options = { method: 'POST',
url: 'https://api.us-south.language-translator.watson.cloud.ibm.com/instances/572b37be-09f4-4704-b693-3bc63869nnnn/v3/identify?version=2018-05-01',
auth: {
'username': 'apikey',
'password': 'nnn'
},
headers: {
"Content-Type":"text/plain"
},
body: [
params.payload.input.text
],
json: true,
};
return rp(options)
.then(res => {
//Set the language property of the incoming message to the language that was identified by Watson Language Translator.
params.payload.context.skills["actions skill"].user_defined["language"] = res.languages[0].language;
console.log(JSON.stringify(params))
return params;
})
}
else {
params.payload.context.skills["actions skill"].user_defined["language"] = 'none'
return params
}
};
序列中的第二个 Web 操作将文本发送到 Watson Language Translator 服务,以将输入文本从先前 Web 操作中标识的语言转换为英语。 然后,会将转换后的字符串 (而不是原始文本) 发送到助手。
序列中第二个操作的 node.js 代码如下所示:
let rp = require("request-promise");
function main(params) {
console.log(JSON.stringify(params))
//If the the incoming message is not null and is not English, translate it.
if ((params.payload.context.skills["actions skill"].user_defined.language !== 'en') && (params.payload.context.skills["actions skill"].user_defined.language !== 'none')) {
const options = { method: 'POST',
url: 'https://api.us-south.language-translator.watson.cloud.ibm.com/instances/572b37be-09f4-4704-b693-3bc63869nnnn/v3/translate?version=2018-05-01',
auth: {
'username': 'apikey',
'password': 'nnn'
},
headers: {
"Content-Type":"application/json"
},
//The body includes the parameters that are required by the Language Translator service, the text to translate and the target language to translate it into.
body: {
text: [
params.payload.input.text
],
target: 'en'
},
json: true
};
return rp(options)
.then(res => {
params.payload.context.skills["actions skill"].user_defined["original_input"] = params.payload.input.text;
const response = {
body : {
payload : {
"context" : params.payload.context,
"input" : {
"text" : res.translations[0].translation,
"options" : {
"export" : true
}
},
},
},
};
return response
})
}
return {
body : params
}
};
在预览面板中测试 Webhook 时,可以提交 Buenos días
,助手会响应,就像您说的 Good morning
是英语一样。 事实上,当您检查助手的“分析”页面并打开 对话时,日志显示用户输入为 Good morning
。
您可以添加一个信息后 webhook,在显示信息之前将信息回复翻译成客户的语言。 有关更多信息,请参阅 示例 2。
示例 3
本例展示了如何编写网络钩子响应,让 watsonx Assistant 跳过处理消息,直接返回网络钩子的响应。
Webhook 配置
在预消息网络挂钩配置页面中,指定以下值:
对于经典体验来说,“秘密”字段没有任何价值。
- URL: https://your-webhook-url/webhook_skip
- 标题名称:内容类型
- 标题值:application/json
webhook_skip网络操作中的 node.js 代码如下所示。
function main(params) {
// Your custom logic to determine the response
let responseText = "This response is directly from the pre-message webhook.";
const response = {
headers: {
"X-Watson-Assistant-Webhook-Return": "true"
},
body: {
output: {
generic: [
{
response_type: "text",
text: responseText
}
]
}
}
};
return response;
}
除去 Webhook
如果您决定不使用网络挂钩对客户输入进行预处理,请完成以下步骤:
-
在助手中,转至 环境 并打开要除去 Webhook 的环境。
-
单击
图标以打开环境设置。
-
在“环境设置”页面上,单击 预消息 Webhook。
要获得经典体验,请完成以下步骤:
-
对于要配置的助手,单击
图标,然后选择设置。
-
单击 Webhooks > Pre-message webhook。
-
-
执行下列其中一个操作:
-
要停止调用网络挂钩处理每条传入消息,请将 “消息前网络挂钩”开关设置为“禁用”。
-
要更改要调用的网络钩子,请单击删除网络钩子。