才权的博客


  • 首页

  • 归档

  • 标签

  • 关于

基于Python Hyper实现Http2的multipart/form-data数据上传

发表于 2017-07-21

Http/2虽然推出已经不短了,但目前整体的使用率并不高,对应的支持库也并不理想,目前主要的支持库可以参考:https://github.com/http2/http2-spec/wiki/Implementations

针对也Python,目前可选的库好像只有Hyper(http://hyper.readthedocs.io/en/latest/)。Hyper在官网当中声称对Requests有很好的支持,可以将Hyper集成到Request中,完成Requests对Http/2的支持,

requests集成hyper

但在实际开发中并不理想。比如,默认Request的请求超时时间是无限的,但通过集成Hyper来使用Requests进行get请求时,还是会出现超时的情况,所以,对于Http/2的开发,不建议使用这种方式。

开发背景

在开发“才权的AI小助手”过程中,进行了DuerOS云端接口的接入,DuerOS的云端接口是基于Http/2的,而且,需要使用multipart/form-data进行当前状态和语音数据流的上传。

DuerOS语音状态和数据上传格式

http://open.duer.baidu.com/doc/dueros-conversational-service/device-interface/voice-input_markdown

面临问题和解决方案

Hyper中并没有专门的接口用来实现multipart/form-data类型数据的上传,而是直接接收已经序列化后的body数据。

Hyper数据上传

针对这种情况,我们可以Http协议的报文定义,来定制body的内容,最终实现Hyper对multipart/form-data类型数据上传的支持。

数据报文格式

示例代码

对于DuerOS的语音请求,需要讲语音状态(Json串)和语音数据(PCM音频流)以multipart/form-data的形式进行上传。这里我们通过get_multipart_formed_data()方法来定制body内容,

'''
    msg_id:消息ID(messageId字段)
    dialog_req_id:对话ID(dialogRequestId字段)
    format:语音数据格式(format字段)
    data:语音raw data(pcm数据流)
'''
def get_multipart_formed_data(self, msg_id, dialog_req_id, format, data):

    event={'clientContext':['ai.dueros.device_interface.alerts.AlertsState','ai.dueros.device_interface.audio_player.PlaybackState','ai.dueros.device_interface.speaker_controller.VolumeState','ai.dueros.device_interface.voice_output.SpeechState'], \
   'event':{'header':{'namespace':'ai.dueros.device_interface.voice_input', \
                      'name':'ListenStarted', \
                      'messageId':msg_id, \
                      'dialogRequestId':dialog_req_id}, \
            'payload':{'format':format}}}

    event=json.dumps(event)

    post_data1=[]

    # ListenStarted事件
    post_data1.append('--'+boundary)
    post_data1.append('Content-Disposition: form-data; name="metadata"')
    post_data1.append('Content-Type: text/plain; charset=utf-8')
    post_data1.append('')
    post_data1.append(event)
#     post_data1.append('--'+boundary+'--')# test
    post_data1.append('')

#     return crlf.join(post_data1).encode('utf-8')# test

#     # Audio data
    post_data1.append('--'+boundary)
    post_data1.append('Content-Disposition: form-data; name="audio"')
    post_data1.append('Content-Type: application/octet-stream')
    post_data1.append('')

    body1=crlf.join(post_data1).encode('utf-8')

    body2=data

    post_data3=[]
    post_data3.append('--'+boundary+'--')
    post_data3.append('')
    body3=crlf.join(post_data3).encode('utf-8')

    upload_data=body1+b'{0}'.format(crlf)+body2+b'{0}'.format(crlf)+body3

    return upload_data

语音状态和数据上传,

'''
    msg_id:消息ID(messageId字段)
    dialog_req_id:对话ID(dialogRequestId字段)
    format:语音数据格式(format字段)
    data:语音raw data(pcm数据流)
'''
def voice_raw_data_upload(self, msg_id, dialog_req_id, format, data):
    post_body=self.get_multipart_formed_data(msg_id, dialog_req_id, format, data)
    self.conn.request('POST', path_upload_voice_data, headers=self.headers, body=post_body)
    resp = self.conn.get_response()

    return resp.read()

完整代码参考

完整的代码可以参考
《Eddy的AI小助手-百度DuerOS模块接入(23)》

Eddy的AI小助手-百度DuerOS模块接入(23)

发表于 2017-07-21

目前开放语音能力的平台已经不少,但能够完整的端到端的解决方案,百度的DuerOS应该是最完善的一个。先前的DuerOS能力通过SDK的形式来提供,当前最新的DuerOS完全兼容亚马逊的AVS协议,并基于Http/2的网络请求对外提供能力。

DuerOS开放平台地址

http://open.duer.baidu.com/openduer/main/index

DuerOS能力接入

AI小助手以模块的形式接入了DuerOS的能力,主要完成的工作包括:

  • 基于OAuth协议的Token获取;
  • 基于Http/2 get的长链接建立;
  • 基于Http/2 multipart-form-data语音状态和音频流的上传;

其中,
Token的获取因为涉及到OAuth协议中对页面的交互,所以Token通过修改并运行DuerOS Java SDK,通过过程中打Log的方式直接过去Token,然后填写到AI小助手中进行测试使用;

Python的Http/2是基于Hyper的,基于multipart-form-data的数据上传操作可以参考:

《基于Python Hyper实现Http2的multipart/form-data数据上传》

模块工程目录

模块工程目录

其中,

duerosdev:DuerOS模块
moduletests/dueros.py:测试代码

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git

Python代码:https://github.com/CaiquanLiu/MyTuringService

Eddy的AI小助手-百度UNIT模块(22)

发表于 2017-07-15

目前市面上的AI接口大多都只能满足固定场景的问答,比如,

  • “今天深圳天气怎么样?”

  • “今天百度的股票怎么样?”

但我们只能被动的接收并展示对方处理的结果。

很多时候我们希望我们自己能够具备语义理解的能力,并自己来控制处理的过程和结果。比如,

  • “我媳妇的生日是哪天呀?”

我们希望语义理解能够识别,

  • 询问的类别:“生日询问”
  • 生日对象:“我媳妇”

有了这些关键信息,我们就可以做自己的定制处理了,比如,将我预先保存在数据库中关于我媳妇生日的信息返回给自己的客户端。具备这种能力我们就可以做各种定制性的需求,但自己来通过语义识别来进行语义分类,和关键信息提取还是挺有难度的(简单的正则匹配灵活性太差)。如果想尽快的满足这样的需求,百度的UNIT接口是不错的选择。

百度UNIT接口地址

http://ai.baidu.com/tech/unit

模块项目地址

MyTuringService中集成了UNIT接口,

UNIT模块

其中,

  • baiduunit:UNIT模块;
  • moduletests/unit.py:测试模块;

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git

Python代码:https://github.com/CaiquanLiu/MyTuringService

Eddy的AI小助手-Keras模块(21)

发表于 2017-07-12

Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow或Theano。Keras 为支持快速实验而生,能够把你的idea迅速转换为结果。

Keras在MyTuringService中的应用

项目中通过Keras构建了一个4输入、3输出、单隐藏层(16单元)的简单神经网络分类器。
代码参考:https://github.com/fastforwardlabs/keras-hello-world/blob/master/kerashelloworld.ipynb

模块工程位置

Keras模块

其中,

  • kerasdev:基于Keras的单层神经网络分类器模块;
  • moduletests/keras_helloworld.py:模块测试程序;

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git
Python代码:https://github.com/CaiquanLiu/MyTuringService

Eddy的AI小助手-Scikit-learn模块(20)

发表于 2017-07-12

MyTuringService集成了基于Scikit-learn的机器学习模块,涵盖逻辑回归、朴素贝叶斯、K临近、决策树、支持向量机的算法。

模块工程位置

机器学习模块

其中,

  • machine_learning:机器学习方法模块;
  • moduletests、scikit_learn.py:模块测试程序;

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git
Python代码:https://github.com/CaiquanLiu/MyTuringService

Eddy的AI小助手-finalseg分词模块(19)

发表于 2017-07-12

Finalseg算法是基于HMM模型,采用了Viterbi算法的分词Python工具包,简单易用,分词效果也不错。

Finalseg项目地址

https://github.com/fxsjy/finalseg

模块工程位置

Finalseg模块

其中,

  • utils/word_seg_finalseg.py:Finalseg封装;
  • moduletests/finalseg.py:Finalseg测试程序;
  • webpage_server.py:Finalseg网页版测试程序(已部署在阿里云,可以通过http://120.25.220.14:8000/)访问);

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git
Python代码:https://github.com/CaiquanLiu/MyTuringService

Eddy的AI小助手-百度TTS合成模块(18)

发表于 2017-07-12

发声是AI机器人必备的基本技能,其中一个关键的技术模块就是TTS(Text To Speech),将文本内容转化为声音(如pcm流)。

AI小助手中使用的TTS模块来自百度语音: http://yuyin.baidu.com/。

模块在工程中的位置

Paste_Image.png

其中,

  • utils/tts.py:百度TTS模块封装;
  • moduletests/tts.py:TTS模块测试程序;

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git
Python代码:https://github.com/CaiquanLiu/MyTuringService

Eddy的AI小助手-MongoDB模块(17)

发表于 2017-07-12

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

MyTuringService中引入了MongoDB作为数据持久化的数据库。

工程中MongoDB模块位置

MongoDB模块

其中,

  • mongodb:MongoDB封装模块;
  • moduletests/mongodb.py:MongoDB模块的测试代码;

MongoDB项目地址:

https://www.mongodb.com/

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git
Python代码:https://github.com/CaiquanLiu/MyTuringService

Eddy的AI小助手-Turing机器人模块(16)

发表于 2017-07-12

图灵机器接口是一个基于Http请求的智能问答接口,只要在其官网注册并申请AppID和AppKey即可使用该服务。

图灵机器人网址: http://www.tuling123.com/

模块工程位置

模块位置

其中,

  • turing:图灵机器人模块;
  • moduletests/turing.py:模块测试程序;

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git
Python代码:https://github.com/CaiquanLiu/MyTuringService

Eddy的AI小助手-请求处理框架模块(15)

发表于 2017-07-12

基于Python的MyTuringService主要用于进行数据处理,并响应来自Java微信服务器(MyWeChatService)的请求,数据流框图如下所示,

数据流框图

其中,

  • 微信客户端:才权的AI小助手微信公众号客户端;
  • 微信服务器:腾讯针对有微信的后台服务器;
  • MyWeChatService:基于Tomcat的Java WebServer,用于与微信公众号进行绑定;
  • MyTuringServcie:基于Tornado的Python WebServer,用于进行离线数据处理和响应MyWeChatService的请求;

MyTuringService WebServer入口,

MyTuringService WebServer入口

其中,

  • wechat_server.py:MyTuringService WebServer入口;
  • http_client.py:模拟MyWeChatService的Http请求(用于测试);

项目地址

Java代码:http://github.com/CaiquanLiu/MyWeChatService.git
Python代码:https://github.com/CaiquanLiu/MyTuringService

1…456…8
Liu Caiquan

Liu Caiquan

71 日志
11 标签
© 2019 Liu Caiquan
由 Hexo 强力驱动
主题 - NexT.Mist
本站总访问量次