技能后处理


技能后处理帮助开发者实现自定义功能,可直接与万维网通信。

业务逻辑

对外 - 图1

能力

  1. 实现多轮对话。
  2. 获取语义结果后,直接与万维网通信,缩短链路时间。
  3. 开发者无需拥有服务器。
每次请求都会触发技能后处理,开发者拿到语义结果(request:JSON),处理后返回(response:JSON),引擎解析 response 来决定最终下发到客户端的数据。

调用方式

技能后处理支持云函数webhook ### 云函数 云函数可以在线编辑,调用信源,处理业务逻辑,填写技能的回复 answer,通过 HTTP 请求通信。 云函数的是 FaaS (Function as a Service)服务,运行在讯飞服务器。

对外 - 图2

运行环境

云端NodeJS 环境为v9.10.1。除 nodejs 携带的标准模块(http crypto https url dgram net stream string_decoder timers buffer)外,还提供以下第三方模块:
  1. promise asap async bson caseless concat-stream
  2. data-format double-ended-queue fibers http-basic
  3. http-response-object inherits ioredis isarray
  4. json5 minimist ms node-zookeeper-client qs
  5. readable-stream resolve-from safe-buffer semver
  6. streamroller string_decoder request-promise
  7. then-request typedarray util-deprecate
云函数有全局变量 AIUI,用于打印日志的 console。点击查看更多云函数接口:v2.0v2.1 #### 示例 云函数通过 dialogState判断填槽对话是否完成,未完成时,开发者不做操作。完成填槽对话后, 回复answer到客户端 。 示例代码:
  1. AIUI.create("v2", function(aiui, err){
  2. //打印 request 结构体
  3. requestObject = aiui.getRequest().getObject();
  4. console.log(requestObject);
  5. //获取 response 对象
  6. var response = aiui.getResponse();
  7. // 获取填槽对话状态
  8. dialogState= requestObject.request.dialogState;
  9. if(dialogState!=null&&dialogState!="COMPLETED"){
  10. // 填槽对话未完成时,托管给系统管理
  11. response.addDelegateDirective();
  12. }else{
  13. // 填槽对话完成时,回复用户一句 answer
  14. updatedIntent = aiui.getUpdatedIntent();
  15. companyValue = updatedIntent.getSlotValue("company");
  16. numberValue = updatedIntent.getSlotValue("number");
  17. answer="你的"+companyValue+"快递,快递单号是是:"+numberValue+",已经达到合肥市"
  18. esponse.setOutputSpeech(answer);
  19. }
  20. // 提交
  21. aiui.commit();
  22. })
Copy

对外 - 图3

如果您不会编写代码,但是想为您的技能增加回复,只需要把以下代码复制进入代码编辑框,修改第12行之后,保存并构建即可。
  1. AIUI.create("v2", function(aiui, err){
  2. requestObject = aiui.getRequest().getObject();
  3. var response = aiui.getResponse();
  4. // 获取当前意图名
  5. intentName = requestObject.request.intents[0].name;
  6. console.log("本次意图来自:"+intentName);
  7. // 获取填槽对话状态
  8. dialogState= requestObject.request.dialogState;
  9. if(dialogState!=null&&dialogState!="COMPLETED"){
  10. response.addDelegateDirective();
  11. }else{
  12. response.setOutputSpeech("这里修改成您想要的回复");
  13. }
  14. aiui.commit();
  15. })
Copy 如果您想根据 intent 回复不同的 answer,可以使用以下代码。
  1. AIUI.create("v2", function(aiui, err){
  2. requestObject = aiui.getRequest().getObject();
  3. var response = aiui.getResponse();
  4. // 获取当前意图名
  5. intentName = requestObject.request.intents[0].name;
  6. console.log("本次意图来自:"+intentName);
  7. // 获取填槽对话状态
  8. dialogState= requestObject.request.dialogState;
  9. if(dialogState!=null&&dialogState!="COMPLETED"){
  10. response.addDelegateDirective();
  11. }else if(intentName==="这里填写intent A 的名称"){
  12. response.setOutputSpeech("这里是是 intent A的回复");
  13. }else if(intentName==="这里填写intent B 的名称"){
  14. response.setOutputSpeech("这里是是 intent B的回复");
  15. }else if(intentName==="这里填写intent C 的名称"){
  16. response.setOutputSpeech("这里是是 intent C的回复");
  17. }else{
  18. response.setOutputSpeech("这里是一个默认回复");
  19. };
  20. aiui.commit();
  21. })
Copy

安全

云端进行了资源隔离以及监测,危险代码并不会影响服务器运行,但系统检测到代码异常时,将下线该技能。 NodeJS 标准不建议的代码请勿编写,如:阻止事件循环。NodeJS 为单线程环境运行,如果存在死循环,技能将不能接收用户消息,技能会被下线。默认每次请求交互800毫秒超时,开发者技能应该在该超时时间内调用 api 的 response 接口,否则云端返回超时错误,此类情况可能出现在:
  • 上述事件循环阻塞。
  • 开发者在异步操作(如 http 调用)回调中调用返回接口,该异步操作可能返回时间较长,此类情况应该对该异步操作设置超时,不要让云端触发超时。
注意
event(Deprecated)、response(Deprecated)、context(Deprecated)、eventName(Deprecated)为四个过时的全局变量点击阅读接口参数。建议尽快迁移到最新的接口,以使用填槽对话等新特性。

Webhook

Webhook的本质是一个web调用,若通过公网部署,技能耗时会增加。

对外 - 图4

使用Webhook流程
  • 在平台填写技能部署地址(URL地址)
  • 技能需要验证发送的请求,验证步骤请参考技能请求校验
注意:Webhook只支持v2.1协议