专栏首页喔家ArchiSelf用JavaScript打造AI应用-从Nodejs SDK 看DuerOS的技能开发

用JavaScript打造AI应用-从Nodejs SDK 看DuerOS的技能开发

为什么要掌握JavaScript呢? 使用JavaScript能能否开发AI应用么?

答案是肯定的。

全栈语言JavaScript

就全栈编程语言而言,与python 并驾齐驱的要算是JavaScript了:

基于JavaScript的前端框架百花齐放,Vue、React、Angular都有广泛的应用;

桌面应用有NW.js(Node +webkit),以及现在的Electron;

嵌入式系统中,也有着Espruino(被称为微控制器的 JavaScript),Tessel (一个集成了Wi-Fi的JavaScript 微处理器)以及国内的ruff.io,详见拙文《探索嵌入式应用框架(EAF)》;

后台服务基本上就是Nodejs的世界,有着丰富的工具集;

在人工智能领域,就机器学习而言,Javascript也有着诸多的开源框架,TensorFlow.js, Brain.js , Synaptic.js等

......

关于JavaScript 的一些编程基础,可以参见《全栈必备JavaScript基础》。

那对于JavaScript的开发者如何开发人工智能相关的应用呢?

这还是需要明确具体的应用场景,但是人工智能操作系统(可参见《感知人工智能操作系统》一文)的产生扩大了AI应用的领域。就对话式AI系统(例如DuerOS)而言,平台化更是Javascript开发者的福音。基于AI操作系统和开发平台,Javascript开发者可以更加高效地开发AI应用。

DuerOS 的 Nodejs 应用示例

关于DuerOS的详细介绍,可以参见《面向接口/协议?看DuerOS的技能开发》,当然对NLP的更多理解(可以参见《感知自然语言理解(NLU)》一文),对于开发对话式AI系统上的技能应用,是大有裨益的。DuerOS提供的Javascript支持是开发技能服务(Skill Bot)的SDK,采用npm加载 , 支持node.js 6.10及以上版本。

构建一个DuerOS的技能服务,一般如下步骤:

1)在DBP(DuerOS Bot Platform)创建并配置技能服务

2)构建基于Nodejs的开发环境

3)创建web服务及调用入口

4)编辑具体的业务逻辑

5)调试后发布技能服务

关于在DBP平台创建和配置技能,以及调试和发布技能,可以具体参见官网说明dueros.baidu.com/dbp。

环境构建

基于DuerOS的技能服务开发,基本上只需要安装Node,Javascript bot SDK,以及相应的httpserver模块例如express,koa等,就可以完成开发环境的搭建:

cd /myworkspace
mkdir js-bot-test
cd js-bot-test
npm init
npm install express --save
npm install bot-sdk --save

Web 服务入口

和Java 开发技能服务类似(参见《从Java SDK看DuerOS的技能开发》),需要创建一个服务启动的入口,在这里是index.js:

const express = require('express');

const Bot = require('./Bot');
let myapp = express();

myapp.post('/', (req, res) => {
    req.rawBody = '';

    req.setEncoding('utf8');
    req.on('data', chunk => {
        req.rawBody += chunk;
    });

    req.on('end', () => {
        let mybot = new Bot(JSON.parse(req.rawBody));

        mybot.run().then(result => {
            res.send(result);
        });
    });
}).listen(8888);

使用express 构建了一个监听8888端口的web服务,完成与DuerOS平台之间的通信,在生产环境中,要增加证书的验证。

编写Bot的业务逻辑

最重要的,需要创建具体的技能服务,实现具体的业务逻辑,示例的Bot.js 文件组织结构如下:

const BaseBot = require('bot-sdk');
class Bot extends BaseBot {

    constructor(postData) {
        super(postData);
        //服务入口请求的处理
            this.addLaunchHandler(() => {
                return {
                    outputSpeech: '欢迎使用!'
                };
            });
        //相关意图处理
            this.addIntentHandler('myintent1', () => {
                let targetSlot1 = this.getSlot('slot1');
        // 意图1 的逻辑处理以及槽位填充,return 相应的 directives 和 outspeech等
                }); 
            this.addIntentHandler('myintent1', () => {
                let targetSlot2 = this.getSlot('slot2');
                });
        //事件处理
            this.addEventListener(‘event1’,() => {
            //对于于事件1的相关处理,return 相应的 directives 和 outspeech等
            });
        //......         // 退出会话
        this.addSessionEndedHandler(function({
            // clear status
            // 清空状态,结束会话。 
            return null; 
        });
    }
    //其他业务逻辑的相关方法

主要的框架还是对话的开启和关闭,以及对意图和事件的处理。所有的逻辑处理函数的返回结果可以是json Object 也可以是Promise包裹的json Object。

至此,就可以运行服务来调试技能了,一旦验证完成,即可在DBP 发布自己的技能了。

DuerOS Javascript Bot SDK 代码浅析

“磨刀不误砍柴功”,理解JS Bot SDK的源代码,对基于Nodejs开发DuerOS的技能服务大有裨益。

在github上bot-sdk-node.js/lib/ 的目录下,是JS bot sdk 的核心代码,主要是6个文件:

  • Bot.js
  • Certificate.js
  • NLU.js
  • Request.js
  • Response.js
  • session.js

NLU 模块

NLU 模块主要完成槽位的设置\获取\确认,以及通过ask()方法完成槽位填充。同时,可以获取意图的名称并确认意图及确认意图状态。需要注意的是setDelegate()方法的使用,只有在DBP平台完成了意图配置,setDelegate()才有效,该方法只是将明确的意图判断交给了DuerOS代为处理。

Session 模块

正像《面向接口/协议?看DuerOS的技能开发》一文中指出的,Session 和浏览器中的cookie 非常类似,用于在客户端和服务器之间传递持久化数据。Javascript bot sdk 中的Session 模块主要提供了getData()和setData()两个方法,用于存储/读取key/value形式的数据。

Certificate 模块

安全性一直是DuerOS 平台所关注的一个重要方面,在DuerOS 与技能服务bot之间是安全通信,尽管在技能调试的时候可以关闭证书的验证。Certificate 模块通过enableVerifyRequestSign()方法开启验证请求参数签名,阻止非法请求, disableVerifyRequestSign()关闭验证请求参数签名,verifyRequest()验证发送请求者是否合法。 关于DBP 平台的安全性,可以以后专门研究讨论。

Request 模块

Request 模块完成了对DBP协议request 请求的封装,主要功能包括:

  • 获取数据对象:getData(),getSession(),getNlu()
  • 根据上下文获取终端状态信息和事件信息:getAudioPlayerContext(),getVideoPlayerContext(), getScreenContext() 和getEventData()
  • 获取用户信息: getUserId(),getQuery(),getLocation()
  • 获取应用信息: getBotId(),getApiAccessToken() ,getApiEndPoint() ,getExternalAccessTokens()
  • 判断对话状态:isLaunchRequest() ,isSessionEndedRequest() ,isDialogStateCompleted()

Response 模块

Response 模块完成了对DBP协议Response响应的封装,主要功能包括:

  • 返回结果封装:buildResult(data),buildResult(data),defaultResult()是默认结果
  • 对话相关:setShouldEndSession(),
  • 异常处理:illegalRequest(),setFallBack() 是兜底话术
  • 麦克风控制: setExpectSpeech(expectSpeech)
  • 设置指令次序:setAutoDirectivesArrangement(),setStrictDirectivesArrangement()
  • 设置expectResponse:addExpectTextResponse(text), addExpectSlotResponse(slot)

expectResponse用于推测用户可能的回复,开发者的技能Bot在响应DuerOS请求时,可以添加expectResponse 信息,告诉DuerOS用户在下次交互时可能话术的某些关键词,DuerOS将在下一轮对话中提高语音识别能力,进而提高了意图的准确性,从而提高了用户使用该技能的用户体验。

还有一个语音播报相关的方法formatSpeech(mix) ,该方法自动识别SSML和纯文体,另外在extension 目录下还有还TTS相关的模块,以后可以对TTS和SSML做更多的探讨。

Bot模块

Bot 模块是所有技能bot的基类,实现了一个典型技能服务的基础功能和逻辑框架。Bot 类的构造函数如下:

constructor(postData) {
        this.request = new Request(postData);

        this.session = this.request.getSession();

        this.nlu = this.request.getNlu();
        this.response = new Response(this.request, this.session, this.nlu);

        this._eventHandler = new Map();
        this._intentHandler = new Map();

        this.botMonitor = new BotMonitor(postData);
    }

Bot的构造以request为参数,完成对request,NLU和Session的获取,生成Response对象,创建意图和事件的处理映射,并且构建了技能服务的监控器。

Bot 类中的主要方法分类如下:

  • 对话相关:addLaunchHandler(handler) ,addSessionEndedHandler(handler) ,waitAnswer() ,endDialog()
  • 意图相关:addIntentHandler(intent, handler),getIntentName(),getSlot(field, index = 0), setSlot(field, value, index = 0)
  • 事件相关:addDefaultEventListener(handler)
  • 安全相关:initCertificate(headers, body),setPrivateKey(filename)
  • 会话相关:endSession() ,getSessionAttribute(field = null, defaultValue = null),setSessionAttribute(field, value, defaultValue = null)和setSessionAttribute(field, value, defaultValue = null),
  • 设备属性判断:isSupportDisplay(),isSupportAudioPlayer(),isSupportVideoPlayer()
  • 对Response中expectResponse的封装:addExpectSlotResponse(slot)
  • 应用相关,对request中的方法封装: getApiAccessToken(),getApiEndPoint() ,sendMateappNotification(data)
  • 用户相关:getUserProfile(),getRecordSpeech(audioToken),getDeviceLocation()

Run()方法是Bot 执行的主体,流程如下:

为了简洁起见,流程图中忽略了botMonitor的相关操作。

另外, Bot类中还实现了对音视频播放器指令,以及展示卡片和模版的处理。

Directive 指令实现

DuerOS JS Bot SDK 对DBP协议中的Directive指令实现了较为完整的封装。所有的指令都派生自BaseDirective类,指令的种类包括:

  • 启动app指令
  • 录音指令
  • 支付指令
  • 授权指令
  • 音频播放器指令
  • 视频播放器指令
  • 显示指令及相关模版

指令相关源代码位于https://github.com/dueros/bot-sdk-node.js/tree/master/lib/directive。

展示模版和卡片

针对有屏设备,DuerOS Bot SDK 提供了较为丰富的展现模版和展示卡片。

展现模板分body template和list template两种类型。其中body template由图片和文字组成,list template由一系列list item组成,每个list item由图片和文字组成。不同的展现模板适合不同的场景,开发者可以根据技能展现的需求选择合适的模板。模版指令示意如下:

{
    "directives": [
        {
            "type": "Display.RenderTemplate",
            "template": {
                "type": "{{STRING}}",
                "token": "{{STRING}}", 
                "backgroundImage": {{ImageStructure}},
                "title": "{{STRING}}",
                "textContent": {
                    "position": "{{ENUM}}",
                    "text": {{TextStructure}}
                }
            }
        }
    ]
}

当技能服务回复用户的时候,可以通过使用卡片形式来展现更生动、丰富的内容。常用的展现卡片类型有文本卡片、标准卡片、标准列表卡片、图片卡片。展现卡片随Response消息一起发送给DuerOS。卡片在response中的json格式如下:

"card": {
    "type":"txt",
    "token":"{{STRING}}",
    "content":"{{STRING}}",
    "url":"{{STRING}}",
    "anchorText": "{{STRING}}",
    "cueWords":[
        "{{STRING}}",
        "{{STRING}}",
        "{{STRING}}",
        ...
    ]
}

针对展现模版和展示卡片,github上给出了比较详细的示例,在DuerOS官网上则给出了具体的布局示意例子。

示例代码

作为一个Javascript开发者,如果开发基于DuerOS的技能服务的话, 从示例代码开始往往是个不错的选择。在github上(https://github.com/dueros/bot-sdk-node.js/tree/master/samples),给出了10多个示例代码,有音乐播放的技能服务,个税计算器,历史上的今天等等。

其中的多个示例代码就是DBP官网上的技能模版,猜一猜是哪几个呢?

参考资料:
  • https://www.robinwieruch.de/machine-learning-javascript-web-developers/
  • https://github.com/dueros/bot-sdk-node.js
  • https://dueros.baidu.com/dbp

本文分享自微信公众号 - 喔家ArchiSelf(wireless_com),作者:老曹

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-04-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • AI开发者大会中的公开课摘要解读——如何在DuerOS技能中实现用户支付购买

    在百度2019AI开发者大会上有很多相对精彩的公开课,DuerOS相关的公开课有4场,分别是:

    半吊子全栈工匠
  • AI开发者大会中的公开课摘要解读——DuerOS技能开发与CFC编程

    在百度2019AI开发者大会上有很多相对精彩的公开课,DuerOS相关的公开课有4场,分别是:

    半吊子全栈工匠
  • 放心用吧!浅谈DuerOS的安全性

    “我们每个人都是安全工作者”(参见关于软件开发,都应该知道的10个常识), 这绝不是一句戏言。在人工智能智能领域,安全同样是一个重要的话题。AI操作系统要保证系...

    半吊子全栈工匠
  • 华为正在与微软洽谈合作,或将在中国微软数据中心使用其AI芯片

    根据The Information中的一份新报告,华为和微软正在洽谈在中国的微软数据中心使用华为的新AI芯片。

    AiTechYun
  • 学习前端开发,至少有50%是无用功,现在你到%几了?

    我记得有一个广告行业的牛人说过,“至少有一半的广告费都是白费的,但我不知道是哪一半”。他叫什么名字我忘记了,只记得这句话。 后来我发现这句话也适合于前端学习,至...

    web前端教室
  • MLP中实现dropout,批标准化MLP中实现dropout,批标准化

    MLP中实现dropout,批标准化 基本网络代码 三层MLP 使用MNIST数据集 import torch as pt import torchvision...

    月见樽
  • excel导出使用get请求参数过长问题

    excel导出功能时,使用的是window.location.href=url也就是get请求。当传入参数过长的时候就报了414,地址过长的错误。

    用户1518699
  • Mac OSX 开发入门基础系列之NSTask

    关于OSX的沙盒机制,推荐学习这篇文档[Cocoa开发之沙盒机制及访问Sandbox之外的文件

    代码行者
  • wordpress添加post_type自定义文章类型

      wordpress很强大,能当博客也能进行二次开发出很完善的内容管理系统满足企业运营需求,比如可以添加products产品模型、汽车模型等,如何实现呢?添加...

    ytkah
  • 高通LCD的pwm背光驱动

    msm8953 lcd在快速亮灭的情况下背光概率性休眠不灭;测量高通pwm,发现正常的时候pwm的管脚LCM_BL_PWM为低电平,失败的时候为高电平;

    233333

扫码关注云+社区

领取腾讯云代金券