Amazon Alexa 服务端搭建

来源:互联网 发布:ds数据精灵激活码 编辑:程序博客网 时间:2024/06/05 16:49

  • Skill
  • 交互方式
  • 语音格式
    • intent sample utterances
    • slot value
    • 处理那些奇怪的话
  • 请求处理
    • JSON格式
    • 签名校验

Alexa是amazon自家的语音助手服务。用户需要购买一个echo音箱,然后就可以对着音箱说出各种各样的指令来指挥它。

Skill

在alexa开发过程,每一个开发者开发的程序被称为skill。在注册成为amazon developer后,便可以开发skill,这个skill在没有发布前,是只有开发者团队自己可见的。如果需要发布到amazon网站上供所有用户使用,则需要走发布流程,经过一系列的审核后,方可被普通用户搜索到。

目前虽然alexa上的skill很多,但其实最常用的也就只有天气、设置闹钟这几个。而当初amazon大力推广的语音叫车服务,美国人民并不买账。

交互方式

用户在对着音箱说话以后,语音识别的结果以POST请求的形式传到开发者的服务器上,服务器需要对这个请求在指定的时间内作出回应(以测试经验来看是7秒左右)。
amazon目前只提供java语言的服务端框架,其他语言需要自行编写。

语音格式

用户的语音识别结果并不是以原文的形式直接发送给服务端的。服务端需要在后台去设置好几种固定的格式,alexa会按照这几种格式去尝试匹配,并返回匹配度最高的结果。

intent & sample utterances

intent英文意为意图,在这里指代用户的某种动作。
假设现在我们的skill去控制一个智能灯泡,灯泡有开灯和关灯两种操作。那么这里开就是一种intent。我们可以定义这个intent叫onIntent. 一个skill有多少个intent,是配置在后台的intent schema里面的。
至于用户怎么表达出这个onIntent,就需要开发者设置在sample utterances里。比如最常用的表达是turn on,甚至可以用中式英语,把open也映射到这个onIntent上。

amazon本身也提供一些现成的intent,比如AMAZON.CancelIntent,它就已经预先配置好了sample utterances,当用户说出shut up,enough,done等词语时会映射到AMAZON.CancelIntent上。当然,你在sample utterances里可以再定义额外的词语也映射到AMAZON.CancelIntent上。

slot value

动词分及物和不及物,intent就好比动词,有的intent在触发以后已经明确了要执行的动作,比如上文的AMAZON.CancelIntent。有的则不行,比如onIntent,服务端只知道用户要打开东西,并不知道打开什么。

这时候就可以给intent这个动词添加一个谓语,这个宾语就叫做slot。至于一句话里,哪些部分解析为intent,哪些部分解析为slot value,直接在sample utterances中指定即可。

如上文中的开灯,我们可以定义一个名叫objects的slot type,里面有light,radio之类的可以打开的东西。然后,sample utterances里这样写:

onIntent turn on {objects}

第一个单词代表了要映射到的intent的名字,随后是语句模板。被大括号括起来的部分就是slot部分。

处理那些奇怪的话

仍然以上面的东西举例,假设我的skill只能帮用户开灯关灯,用户说了一句go flying,这时候会出现什么情况呢?

令人遗憾的是,在未作处理的情况下,alexa会随机选一个intent并作强行匹配,所以,很有可能用户调戏alexa说了句go flying,然后发现灯开了。

邮件咨询amazon之后,得到了一个解决方案:再加一个intent,比如叫CatchAll,然后在sample utterances里写几个奇怪的话映射到这个CatchAll。比如下面的:

CatchAll go on holidayCatchAll start cooking

不用写多,几句话就可以了。用户再调戏alexa的时候,会很大概率匹配到这个CatchAll,服务端代码中做相应处理即可。

请求处理

JSON格式

紧接着上文,在用户说出了turn on the light这样一段话之后,amazon发送给服务端的JSON里面就包含类似以下格式的识别结果。

{    "request": {        "type": "IntentRequest",        "requestId": "EdwRequestId.72965756-xxxx-xxxx-xxxx-439e4daa56e3",        "intent": {            "name": "onIntent",            "slots": {            "objects": {                "name": "objects",                "value": "light"            }        }    },}

其中的IntentRequest代表这是一个动作请求。除此之外,还有两种特殊的请求:
* LaunchRequest: 用户唤醒了skill,但未指明具体动作。直接说出skill名字或者open + skill名字都可以唤醒。此时服务端应该返回欢迎语。
* SessionEndedRequest: 用户说出了exit。这时候skill应该关闭用户的session。

签名校验

在成功的解析出amazon发过来的json数据以后,我们回过头来看看,是不是忘了做什么事情?如果这个请求不是amazon发来的,而是一个伪造的请求,该如何鉴别?
Amazon在每次发送post请求的header里会带上body的SHA1摘要,存放在signature字段里,并且这个摘要是用私钥加密过的。
同时还会带上一个signaturecertchainurl字段,这个字段里标注了加密使用的证书的存放地址。
服务端在接收到每个post请求后,首先要校验request body中的时间戳是否过期(150秒)以防止replay攻击;再校验URL格式是否合法(主机名、协议等都是有要求的)。
然后需要根据URL拿到证书链,验证证书链的有效性,并且用证书中的公钥,去解密signature字段,得到携带的SHA1摘要,将其与收到的request body的SHA1摘要作比较,如果一致,则认为请求合法。
详细的描述可以看官方文档.

如果是自己用用的Skill无所谓,对于要正式发布的Skill,amazon的test case是会全面覆盖这些东西的,不要抱有侥幸心理。

这里有个问题,就是拿URL去下载证书太耗费时间了,如果每个请求都去下载证书,验证完了再去处理请求,很可能已经超时了。
这个问题官方文档里没有提过,不过在Alexa的论坛上有个官方回复,大意就是,服务端可以对证书进行缓存,Amazon确保不同的证书的路径不一样。也就是说,只要两个证书的路径一致,它们的内容必定一致。因此,对于一个新的证书,只要下载一次,后续的请求都是直接从缓存里去拿公钥解密,大大减少了等待时间。Amazon更换证书的频率大约是几个月一次。

原创粉丝点击