MLSQL深度学习入门(四)-Serving
本文所有代码示例都基于MLSQL Engine最新版本 2.1.0-SNAPSHOT
本文将使用MLSQL Console的notebook演示。
环境要求,请参考第一篇: MLSQL深度学习入门【一】。
系列文章列表:
- MLSQL 机器学习最简教程(无需Python!)
- MLSQL深度学习入门【一】
- MLSQL深度学习入门【二】-分布式模型训练
- MLSQL深度学习入门【三】-特征工程
- MLSQL深度学习入门【四】-Serving
内置算法 end-2-end http based 服务
内置算法非常简单,当你训练好算法模型,包括各种特征工程得到的模型,你可以一键把他们转化成UDF函数部署到线上提供服务。 具体操作如下:
我们通过 deployModel 注解,然后通过register语法,把模型部署到指定的服务上。
然后可以通过调用http接口进行预测验证:
上面的语句相当于发起了一个POST请求。
深度学习 end-2-end http based 服务
深度学习部署成HTTP 服务有两步。
第一步是部署模型
部署的方式也是很简单的,如下:
首先看注解:
--%deployModel
--%url=http://127.0.0.1:9003
--%access_token=mlsql
这里其实是把指定的模型部署到指定的url的服务上。那具体怎么部署呢?用户只需要设置三个变量即可:
set model="ai_model.minist_model";
set localPath="/tmp/minist_model";
set pythonEnv = "source /Users/allwefantasy/opt/anaconda3/bin/activate ray1.3.0";
第一个指定模型所在的表名。第二个指定模型要放到预测服务的本地目录。设置好这几个值后,系统会自动将模型部署到指定的服务指定的目录下。
第二步是部署预测脚本
代码如下:
先看注解部分:
--%deployScript
--%url=http://127.0.0.1:9003
--%access_token=mlsql
--%codeName=testScript
我们会把脚本部署到指定的Url的服务上。并且给该脚本取了名字,叫testScript。现在看看脚本代码部分:
首先通过下面的方式获取http接口的参数。这个是固定写法。
params = dict([(row["key"],row["value"]) for row in context.fetch_once_as_rows()])
模型的位置是固定的,因为我们在发布模型的时候已经确定了。所以可以直接加载:
localPath="/tmp/minist_model"
model = models.load_model(localPath)
输出结果的话,用如下方式:
context.build_result([{"value":value}])
输出的结果必须是上面的格式,其中value是一个json字符串。 注册成功后,系统会返回预测地址。
测试下接口
我们可以测试下接口,这里采用crawler_http
函数去访问接口:
系统成功加载了模型,所以可以顺利返回结果。校验成功。
最后,模型serving的服务是开源的么?
是的。MLSQL Engine 同时也是Model Serving Engine。当MLSQL Engine单机部署时他和标准的Java程序是一致的。我们通过通过开发了内置的插件,使得其支持python代码的预测和执行。譬如上面的示例代码,执行时间在10ms以内。
最最后,如何避免每次加载模型
上面的代码其实每次执行都会加载模型,这显然是不符合实际生产的。我们可以少做改动即可确保只加载一次。
#%deployScript
#%url=http://127.0.0.1:9003
#%access_token=mlsql
#%codeName=testScript
import json
from pyjava.api.mlsql import RayContext,PythonContext
from tensorflow.keras import models,layers
from tensorflow.keras import utils as np_utils
params = dict([(row["key"],row["value"]) for row in context.fetch_once_as_rows()])
localPath="/tmp/minist_model"
codeName = params["codeName"]
if "models" not in PythonContext.cache:
PythonContext.cache["models"]={}
if codeName not in PythonContext.cache["models"]:
PythonContext.cache["models"][codeName]=models.load_model(localPath)
model= PythonContext.cache["models"][codeName]
data=params["data"]
value=json.dumps({"hello":data})
context.build_result([{"value":value}])