全部产品
云市场

Python开发自定义Processor

更新时间:2020-02-12 21:35:57

简介

Python是机器学习与AI领域的最主要开发语言之一。凭借 Tensorflow、numpy 和 scikit-learn 等机器学习框架和 Pandas 等数据工程师套件,Python 已经坐实了AI 领域第一编程语言的位置。一套 Python 的高性能在线预测服务框架不但能够帮助算法工程师快速进行模型迭代,也能更好的将工程同学从线上任务中释放出来。

PAI-EAS提供Python SDK,用于帮助算法同学更快的开发和部署线上模型。Python SDK支持Tensorflow、PyTorch以及scikit-learn等基于Python的开源机器学习框架,也可以集成 Pandas 等数据分析处理框架。

使用EAS Python SDK可快速将本地预测逻辑直接转换成在线服务,Python SDK中内置了EAS为AI Inference场景所订制的高性能的PRC框架,以及与EAS集群中各项高级功能交互所需要的内部接口,用户通过简单的接口实现即可将服务部署到EAS集群中,使用EAS所提供的模型监控,蓝绿发布,弹性伸缩,高速直连等功能。

接下来我们通过一个案例来说明使用步骤。

一、构建开发环境

开发环境可使用pyenv或conda等python包管理工具来构建,EAS提供的客户端工具eascmd将构建过程进行了封装,可以一条命令构建python sdk开发环境,若需求更加定制化,则也可以选择手工的方式来构建开发环境。

1.1 使用EASCMD初始化环境(仅Linux系统)

eascmd详细使用文档

eascmd是EAS提供的客户端工具,将python sdk的初始化过程进行了封装,用户下载后可直接通过一条命令来初始化python sdk环境,并生成相关的文件模板。

  1. # 安装并初始化eascmd,示例是安装Linux环境下的eascmd工具
  2. # 其他环境下的eascmd可以从上面的eascmd详细使用文档中下载
  3. $ wget http://eas-data.oss-cn-shanghai.aliyuncs.com/tools/eascmd64
  4. # 下载完成之后继续操作修改访问权限,配置您在阿里云上的AccessKey信息
  5. $ chmod +x eascmd64
  6. $ ./eascmd64 config -i <access_id> -k <access_key>
  1. # 初始化环境
  2. $ ./eascmd64 pysdk init ./pysdk_demo

输入python版本,默认为3.6,即会自动创建python环境ENV目录,预测服务代码模板app.py,服务部署模板app.json

1.2 手工初始化

如果eascmd不能满足您的需求,或在初始化过程中遇到问题,也可以尝试手工初始化,过程同样很简单,这里推荐使用conda环境来部署,在命令行执行如下命令:

  1. mkdir demo
  2. cd demo
  3. # 使用conda创建python环境,目录需指定固定名字:ENV
  4. conda create -p ENV python=2.6
  5. # 安装EAS python sdk
  6. ENV/bin/pip install http://eas-data.oss-cn-shanghai.aliyuncs.com/sdk/allspark-0.9-py2.py3-none-any.whl
  7. # 安装其它依赖包,以tensorflow1.14为例
  8. ENV/bin/pip install tensorflow==1.14

若本地未安装conda,请先安装conda环境:

  1. $ wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
  2. $ sh Miniconda3-latest-Linux-x86_64.sh

1.3 使用预构建的开发镜像(推荐)

EAS提供了预先构建好的开发镜像,预装了conda并生成了对应python版本的ENV环境,目前提供了三个镜像:

  1. # 仅安装了conda的基础镜像
  2. registry.cn-shanghai.aliyuncs.com/eas/eas-python-base-image:latest
  3. # 安装了conda及python2.7和eas allspark 0.8的python sdk
  4. registry.cn-shanghai.aliyuncs.com/eas/eas-python-base-image:py2.7-allspark-0.8
  5. # 安装了conda及python3.6和eas allspark 0.8的python sdk
  6. registry.cn-shanghai.aliyuncs.com/eas/eas-python-base-image:py3.6-allspark-0.8

直接run该镜像,即可得到一个python开发环境:

  1. $sudo docker run -ti registry.cn-shanghai.aliyuncs.com/eas/eas-python-base-image:py3.6-allspark-0.8
  2. (/data/eas/ENV) [root@487a04df4b21 eas]#
  3. (/data/eas/ENV) [root@487a04df4b21 eas]# ENV/bin/python app.py
  4. [INFO] initialize new lua plugin
  5. [INFO] loading builtin config script
  6. [INFO] current meritc id:0
  7. [INFO] loading builtin lua scripts
  8. [INFO] Success load all lua scripts.
  9. [INFO] create service
  10. [INFO] rpc binds to predefined port 8080
  11. [INFO] updating rpc port to 8080
  12. [INFO] install builtin handler call to /api/builtin/call
  13. [INFO] install builtin handler eastool to /api/builtin/eastool
  14. [INFO] install builtin handler monitor to /api/builtin/monitor
  15. [INFO] install builtin handler ping to /api/builtin/ping
  16. [INFO] install builtin handler prop to /api/builtin/prop
  17. [INFO] install builtin handler realtime_metrics to /api/builtin/realtime_metrics
  18. [INFO] install builtin handler tell to /api/builtin/tell
  19. [INFO] install builtin handler term to /api/builtin/term
  20. [INFO] Service start successfully
  21. [INFO] shutting down context ... press Ctrl+C again to force quit

用户可基于该基础镜像的ENV环境继续安装自己的依赖库,再将修改过的container commit成一个数据镜像即可:

  1. ENV/bin/pip install tensorflow==1.12

用户也可以在docker外来构建ENV开发环境,构建完成后之将其拷入任意docker镜像的/data/eas/目录,使用镜像的方式来部署可以提供部署速度,避免每次部署都将整个ENV环境打包上传。

二、编写预测逻辑

在ENV同级目录下创建预测服务主文件app.py(在EAS预置的开发镜像中已经预先创建了该模板文件),EAS提供了如下SDK封装,使用eascmd初始化环境时会自动生成:

  1. # -*- coding: utf-8 -*-
  2. import allspark
  3. class MyProcessor(allspark.BaseProcessor):
  4. """ MyProcessor is a example
  5. you can send mesage like this to predict
  6. curl -v http://127.0.0.1:8080/api/predict/service_name -d '2 105'
  7. """
  8. def initialize(self):
  9. """ load module, executed once at the start of the service
  10. do service intialization and load models in this function.
  11. """
  12. self.module = {'w0': 100, 'w1': 2}
  13. def pre_process(self, data):
  14. """ data format pre process
  15. """
  16. x, y = data.split(b' ')
  17. return int(x), int(y)
  18. def post_process(self, data):
  19. """ proccess after process
  20. """
  21. return bytes(data, encoding='utf8')
  22. def process(self, data):
  23. """ process the request data
  24. """
  25. x, y = self.pre_proccess(data)
  26. w0 = self.module['w0']
  27. w1 = self.module['w1']
  28. y1 = w1 * x + w0
  29. if y1 >= y:
  30. return self.post_process("True"), 200
  31. else:
  32. return self.post_process("False"), 400
  33. if __name__ == '__main__':
  34. # paramter worker_threads indicates concurrency of processing
  35. runner = MyProcessor(worker_threads=10)
  36. runner.run()

上述代码即为python sdk的简单示例,用户需继承EAS提供的基类BaseProcessor,实现initialize()和process()两个函数,其中process()函数的输入输出均为bytes类型,输出两个参数分别为response_data和status_code,正常请求status_code可返回0或200。

函数名 功能介绍 参数列表
init(worker_threads=5, worker_processes=1,endpoint=None) processor构建函数 worker_threads worker线程数,默认值为5;worker_processes 进程数,默认为1,当worker_processes为1时,则为单进程多线程模式,当worker_processes大于1时,则worker threads只负责数据读取,请求由多进程并发处理,每个进程均会执行initialize();endpoint 服务监听的endpoint,可通过该参数指定服务监听的地址和端口,如endpoint=’0.0.0.0:8079’
initialize() processor初始化函数,服务启动时做加载模型等初始化工作 无参数
process(data) 请求处理函数,每个请求来时会将request body作为参数传递给process()进行处理,并将函数返回值返回到客户端 data 为request body,类型为bytes,返回值亦为bytes
run() 启动服务 无参数

三、本地测试服务

  1. ./ENV/bin/python app.py
  2. curl http://127.0.0.1:8080/test -d '10 20'

四、发布线上服务

4.1 打包完整环境

完成 Python代码开发后,可以进行打包部署,分两个步骤,一个是打包上传,一个是部署eascmd提供了打包命令,对打包进行了简单的封装:

  1. $ ./eascmd64 pysdk pack ./demo
  2. [PYSDK] Creating package: /home/xingke.lwp/code/test/demo.tar.gz

用户也可选择自行打包(支持zip包和tar.gz包),注意:ENV目录需要在打包的根目录中。将打出来的tar.gz包上传至oss,获取地址:oss://eas-model-beijing/1955570263925790/demo.tar.gz可使用如下服务配置文件来部署服务:

  1. {
  2. "name": "pysdk_demo",
  3. "processor_entry": "./app.py",
  4. "processor_type": "python",
  5. "processor_path": "oss://eas-model-beijing/1955570263925790/pack.tar.gz",
  6. "metadata": {
  7. "instance": 1,
  8. "memory": 2000,
  9. "cpu": 1
  10. }
  11. }

4.2 通过镜像来上传环境(推荐)

由于用户使用conda生成的python ENV环境通常会比较大,且在开发过程中,ENV环境的修改频率很低,在开发部署的过程中每次都打包上传会浪费用户时间和存储资源,EAS提供了data_image的部署方式,用户基于EAS提供的预构建的镜像来构建ENV环境,在ENV中安装自己所需依赖的python包,安装完成后可将container commit成一个自己的数据镜像来并上传到镜像仓库中,比如:

  1. sudo docker commit 487a04df4b21 registry.cn-shanghai.aliyuncs.com/eas-service/develop:latest
  2. sudo docker push registry.cn-shanghai.aliyuncs.com/eas-service/develop:latest

用户每次只需将app.py相关的文件打包上传至oss即可,可使用下面的服务描述文件来部署服务:

  1. {
  2. "name": "pysdk_demo",
  3. "processor_entry": "./service.py",
  4. "processor_type": "python",
  5. "processor_path": "http://eas-data.oss-cn-shanghai.aliyuncs.com/demo/service.py",
  6. "data_image": "registry.cn-shanghai.aliyuncs.com/eas-service/develop:latest",
  7. "metadata": {
  8. "instance": 1,
  9. "memory": 2000,
  10. "cpu": 1
  11. }
  12. }

4.3 服务部署

  1. $ ./eascmd64 create app.json
  2. [RequestId]: 1202D427-8187-4BCB-8D32-D7096E95B5CA
  3. +-------------------+-------------------------------------------------------------------+
  4. | Intranet Endpoint | http://1828488879222746.vpc.cn-beijing.pai-eas.aliyuncs.com/api/predict/pysdk_demo |
  5. | Token | ZTBhZTY3ZjgwMmMyMTQ5OTgyMTQ5YmM0NjdiMmNiNmJkY2M5ODI0Zg== |
  6. +-------------------+-------------------------------------------------------------------+
  7. [OK] Waiting task server to be ready
  8. [OK] Fetching processor from [oss://eas-model-beijing/1955570263925790/pack.tar.gz]
  9. [OK] Building image [registry-vpc.cn-beijing.aliyuncs.com/eas/pysdk_demo_cn-beijing:v0.0.1-20190806082810]
  10. [OK] Pushing image [registry-vpc.cn-beijing.aliyuncs.com/eas/pysdk_demo_cn-beijing:v0.0.1-20190806082810]
  11. [OK] Waiting [Total: 1, Pending: 1, Running: 0]
  12. [OK] Service is running
  13. # 测试服务
  14. $ curl http://1828488879222746.vpc.cn-beijing.pai-eas.aliyuncs.com/api/predict/pysdk_demo -H 'Authorization: ZTBhZTY3ZjgwMmMyMTQ5OTgyMTQ5YmM0NjdiMmNiNmJkY2M5ODI0Zg==' -d 'hello eas'