kotti_ai:AI+互联网企业级应用,打通飞桨部署最后一公里!

结合Pyramid Kotti web框架和飞桨Paddle Serving框架,通过构建kotti_ai软件项目,打通AI部署最后一公里!

kotti_ai是AI+互联网企业级应用软件包,通过web技术,将基于飞桨Paddle Serving框架的AI应用更好的呈现出来,解决AI实际部署落地难、AI技术提供商与最终用户互通难的问题,实现AI训练、部署以及上线一条龙服务!
项目AIStudio手册:https://aistudio.baidu.com/aistudio/projectdetail/252773
项目demo展示:http://airoot.org:5000/
项目代码仓库:https://git.openi.org.cn/skywalk163/kotti_ai

kotti_ai的特点:

  • 易部署
  • 易上线
  • 易使用

当前AI行业的痛点

  • AI项目部署落地难
  • 每个项目单打独斗,没有合力
  • AI服务商与最终用户隔绝

如何解决这些问题呢?
学习互联网行业经验,使用互联网模式为AI行业助力!

使用互联网模式解决当前AI痛点

  • 使用成熟互联网技术,解决AI部署落地难的问题
  • 复制互联网模式,AI项目流水线化
  • AI项目互联网化,互联互通,服务与用户

下面我们就通过实践来学习和展示如何用kotti_ai构建企业级AI+互联网应用!

一、构建企业级AI+互联网应用的功能分解

企业级级AI+互联网应用服务由三部分组成,其中前两部分业内有成熟解决方案,即部署和web服务,增加的工作是通过第三部分 kotti_ai软件包,将前两部分联通在一起,组成整体解决方案。

1、飞桨Paddle Serving企业级部署

Paddle Serving 依托深度学习框架 PaddlePaddle 旨在帮助深度学习开发者和企业提供高性能、灵活易用的工业级在线推理服务。Paddle Serving 支持 RESTful、gRPC、bRPC 等多种协议,提供多种异构硬件和多种操作系统环境下推理解决方案,和多种经典预训练模型示例。
https://github.com/PaddlePaddle/Serving/

2、企业级WEB服务

采用Pyramid和Kotti提供企业级web服务。

Pyramid 是基于Python的企业级web框架,Kotti是基于Pyramid的企业级CMS web框架。

Pyramid:The Start Small, Finish Big
Stay Finished Framework
https://www.trypyramid.com/

Kotti is a high-level, Pythonic web application framework based on Pyramid and SQLAlchemy. It includes an extensible Content Management System called the Kotti CMS (see below).
https://github.com/Kotti/Kotti

3、kotti_ai 企业级AI+互联网应用组件

kotti_ai是本项目的主角,刚刚面市不久,还在功能完善中…https://git.openi.org.cn/skywalk163/kotti_ai

kotti_ai基于Kotti框架,将飞桨Paddle Serving提供的推理服务,使用web技术呈现给最终用户。

我们这样简单理解:

  • 飞桨Paddle Serving提供企业级推理服务,但不提供终端用户界面。
  • PaddleHub提供推理服务,提供终端用户界面,但只适合个人用户使用,无法提供企业级服务。
  • kotti_ai既有终端用户界面,又通过飞桨Paddle Serving提供企业级推理服务。

二、AI+互联网应用项目展示

本项目以pp-shitu模型为例,已经在移动云测试主机:http://airoot.org:5000/ 进行部署展示,预计展示时间到2022.11月停止。
在此感谢移动云苏州区的大力支持!

大家可以点击上面的网址,使用账户admin密码qwerty登录。登录之后可以选择菜单:add-AImage上传图片,图片上传后就会进行分类识别,打印出类似这样的识别结果:[{'bbox': [345, 95, 524, 585], 'rec_docs': '红牛-强化型', 'rec_scores': 0.8073724}]

在这里插入图片描述

ps,该网站为kotti_ai展示和学习所用,请各路大神小心呵护,太使劲了小网站承受不起哈。

三、AI+互联网应用项目实践

以下步骤仅为参考展示,因为Paddle Serving本身安装就会碰到很多坑,尤其是在AIStudio下一般不会太顺利,更要命的是c++ serving更加困难(我都忘记自己是否安装成功过了)。 索性Paddle Serving是服务器版,不需要安装很多遍,另外其负载能力强大,值得我们花费的时间。

安装并启动Paddle Serving c++之后,就可以安装kotti_ai了。kotti_ai源代码写死了会跟本机9400端口通信,所以不启动c++ serving 是无法正常启动kotti_ai的。

最简的一些执行命令留档,具体目录可能根据实际情况改动:

# 到PaddleServing 目录并启动9400端口的PaddleServing 服务
cd 
cd ~/PaddleClas/deploy/paddleserving/recognition
bash run_cpp_serving.sh

# 进入kotti_ai目录并启动5000和5001两个端口的web服务
cd ~/work/kotti_ai
nohup pserve app.ini?http_port=5000 --reload &
nohup pserve app.ini?http_port=5001 --reload &

1、安装飞桨Paddle Serving

安装Paddle Serving c++服务器,服务端口号是9400

具体请参照官方文档:https://github.com/PaddlePaddle/PaddleClas/blob/release/2.5/docs/zh_CN/inference_deployment/recognition_serving_deploy.md

下面按照文档把步骤简单展示一下

首先安装 Serving 相关的 python 包。

!pip3 install paddle-serving-client
!pip3 install paddle-serving-app
!pip3 install faiss-cpu


#若为CPU部署环境:
# !pip3 install paddle-serving-server==0.7.0 # CPU
# !pip3 install paddlepaddle==2.2.0          # CPU

#若为GPU部署环境
!pip3 install paddle-serving-server-gpu # GPU with CUDA10.2 + TensorRT6
# !pip3 install paddlepaddle-gpu     # GPU with CUDA10.2

#其他GPU环境需要确认环境再选择执行哪一条
# !pip3 install paddle-serving-server-gpu==0.7.0.post101 # GPU with CUDA10.1 + TensorRT6
# !pip3 install paddle-serving-server-gpu==0.7.0.post112 # GPU with CUDA11.2 + TensorRT8

下载Paddle Serving代码

将PaddleClas套件里的deploy目录单独拷贝出来即可。这里为了效率,就不用git下载了,直接使用下载好的deploy目录。

# 将Paddle Serving代码从work目录拷贝到根目录
# !cp -rf ~/work/deploy ~/
!cd ~/ && tar -xzf ~/work/deploy.tar.gz

模型转换

进入deploy目录,并进行模型转换

%cd ~/deploy
# 创建并进入models文件夹
!mkdir models
%cd ~/deploy/models
# 下载并解压通用识别模型
!wget https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/inference/PP-ShiTuV2/general_PPLCNetV2_base_pretrained_v1.0_infer.tar
!tar -xf general_PPLCNetV2_base_pretrained_v1.0_infer.tar
# 下载并解压通用检测模型
!wget https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/inference/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer.tar
!tar -xf picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer.tar

转换通用识别 inference 模型为 Serving 模型:

# 转换通用识别模型
%cd ~/deploy/models
!python3.7 -m paddle_serving_client.convert \
--dirname ./general_PPLCNetV2_base_pretrained_v1.0_infer/ \
--model_filename inference.pdmodel  \
--params_filename inference.pdiparams \
--serving_server ./general_PPLCNetV2_base_pretrained_v1.0_serving/ \
--serving_client ./general_PPLCNetV2_base_pretrained_v1.0_client/

接下来分别修改 general_PPLCNetV2_base_pretrained_v1.0_serving/ 和 general_PPLCNetV2_base_pretrained_v1.0_client/ 目录下的 serving_server_conf.prototxt 中的 alias 名字: 将 fetch_var 中的 alias_name 改为 features。修改后的 serving_server_conf.prototxt 内容如下

feed_var {
name: "x"
alias_name: "x"
is_lod_tensor: false
feed_type: 1
shape: 3
shape: 224
shape: 224
}
fetch_var {
  name: "batch_norm_25.tmp_2"
  alias_name: "features"
  is_lod_tensor: false
  fetch_type: 1
  shape: 512
}

转换通用检测 inference 模型为 Serving 模型:

# 转换通用检测模型
%cd ~/deploy/models
!python3.7 -m paddle_serving_client.convert --dirname ./picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer/ \
--model_filename inference.pdmodel  \
--params_filename inference.pdiparams \
--serving_server ./picodet_PPLCNet_x2_5_mainbody_lite_v1.0_serving/ \
--serving_client ./picodet_PPLCNet_x2_5_mainbody_lite_v1.0_client/

下载并解压已经构建后完成的检索库 index

# 回到deploy目录
%cd ~/deploy
# 下载构建完成的检索库 index
!wget https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/data/drink_dataset_v2.0.tar
# 解压构建完成的检索库 index
!tar -xf drink_dataset_v2.0.tar

服务部署和请求

本身我们这个企业级应用项目使用的是c++部署,不过c++部署在AIStudio可能有些波折,这里先展示下python部署。

python部署

下面的命令需要到控制台使用。

注意: 识别服务涉及到多个模型,出于性能考虑采用 PipeLine 部署方式。Pipeline 部署方式当前不支持 windows 平台。

# 进入到工作目录
cd ~/deploy/paddleserving/recognition

# 启动服务,运行日志保存在 log.txt
python3.7 recognition_web_service.py &>log.txt &

然后进行测试:
发送请求:

python3.7 pipeline_http_client.py

目前在AIStudio下没有测试成功

# 使用客户端测试
!cd ~/deploy/paddleserving/recognition && python3.7 pipeline_http_client.py

C++ Serving部署

与Python Serving不同,C++ Serving客户端调用 C++ OP来预测,因此在启动服务之前,需要编译并安装 serving server包,并设置 SERVING_BIN。

编译并安装Serving server包

以下步骤就不能在notebook下执行了,需要到命令行执行,否则项目会卡死,别问我怎么知道的。

# 进入工作目录
cd ~/deploy/paddleserving

# 一键编译安装Serving server、设置 SERVING_BIN
source ./build_server.sh python3.7

注: build_server.sh 所设定的路径可能需要根据实际机器上的环境如CUDA、python版本等作一定修改,然后再编译;如果执行 build_server.sh 过程中遇到非网络原因的报错,则可以手动将脚本中的命令逐条复制到终端执行。

另外编译安装可能非常慢,主要是因为要git 下载一些源代码进行编译,好在只需要编译一次即可,所以多等等也没啥大问题。编译用到go语言,后来就没在AIStudio下尝试了,等以后有时间再整。(换句话说,当前c++ serving版本我在AIStudio下没有装成功)。

C++ Serving使用的输入输出格式与Python不同,因此需要执行以下命令,将4个文件复制到下的文件覆盖掉3.1得到文件夹中的对应4个prototxt文件。

# 回到deploy目录
cd ../

# 覆盖prototxt文件
\cp ./paddleserving/recognition/preprocess/general_PPLCNetV2_base_pretrained_v1.0_serving/*.prototxt ./models/general_PPLCNetV2_base_pretrained_v1.0_serving/
\cp ./paddleserving/recognition/preprocess/general_PPLCNetV2_base_pretrained_v1.0_client/*.prototxt ./models/general_PPLCNetV2_base_pretrained_v1.0_client/
\cp ./paddleserving/recognition/preprocess/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_client/*.prototxt ./models/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_client/
\cp ./paddleserving/recognition/preprocess/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_serving/*.prototxt ./models/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_serving/

启动服务

# 进入工作目录
cd ./paddleserving/recognition

# 端口号默认为9400;运行日志默认保存在 log_PPShiTu.txt 中
# CPU部署
bash run_cpp_serving.sh
# GPU部署,并指定第0号卡
bash run_cpp_serving.sh 0

2、安装Kotti软件包

直接使用pip安装即可。Kotti包含了PYramid web框架的软件包。

!pip install kotti

3、安装kotti_ai

首先需要https://git.openi.org.cn/skywalk163/kotti_ai下载kotti_ai源代码,然后需要安装相关库,安装相关库需要较长时间。主要是opencv等安装起来较慢。

大家直接在kotti_ai目录可以查阅源代码,也欢迎志同道合的朋友一起来建设这个项目。

# 下载kotti_ai源代码
%cd ~/
!git clone https://git.openi.org.cn/skywalk163/kotti_ai
# 安装kotti_ai,需要提前安装一些三方库,否则安装时编译安装太慢!
!pip install opencv-python faiss-cpu numpy paddle_serving_client # kotti_ai中pp-shitu需要的库
!pip install kotti_image kotti_tinymce pyramid_debugtoolbar plone # kotti_ai需要的库
!cd ~/kotti_ai && python setup.py develop # 安装kotti_ai库

以上就安装好了kotti_ai库。kotti_ai核心代码就是ppshitu.py和views/edit.py两个文件。

ppshitu.py核心代码:

import numpy as np
from paddle_serving_client import Client
import cv2
import faiss

def ppshitu(im=None):
    client = Client()
    client.load_client_config([        "/home/pyramid/PaddleClas/deploy/paddleserving/recognition/../../models/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_client",        "/home/pyramid/PaddleClas/deploy/paddleserving/recognition/../../models/general_PPLCNet_x2_5_lite_v1.0_client"
    ])
    client.connect(['127.0.0.1:9400'])

    if im is None :
        return None
    im_shape = np.array(im.shape[:2]).reshape(-1)
    fetch_map = client.predict(
        feed={"image": im,
              "im_shape": im_shape},
        fetch=["features", "boxes"],
        batch=False)

    #add retrieval procedure
    det_boxes = fetch_map["boxes"]
    searcher, id_map = init_index(index_dir)
    results = postprocess(fetch_map, feature_normalize, det_boxes, searcher,
                          id_map, return_k, rec_score_thres, rec_nms_thresold)

    return str(results)

views/edit.py中核心代码

@view_config(
    name="my-custom-submenu", permission="edit",
    renderer="kotti_ai:templates/my-custom-submenu.pt")
def my_custom_submenu(context, request):
    from kotti_ai.ppshitu  import ppshitu

    if not isinstance(context, AImage) :
        print("====context.__class__ != AImage.__class__ :", False)
        return {}
    # if context.description == None or context.description[:2] != "[{":
    if  context.description[:1] != "[":
        im = None
        if "data" in dir(context) :
            # from plone.scale.scale import scaleImage
            import numpy as np
            
            tmpdata = context.data.file.read() # 从上下文(当前或数据库中)中读到图片文件
            image = cv2.imdecode(np.fromstring(tmpdata, np.uint8), 1) # 使用cv2读取图片文件
            im = image
            
            out = ppshitu(im=im)
            context.description = str(out)
    return {}

4、启动web服务

kotti_ai是基于Kotti框架,Kotti基于Pyramid框架,但是使用起来并不会感到层级关系,直接在kotti_ai目录启动web服务即可。

在控制台进入kotti_ai目录,执行pserve developmnet.ini --reload
实际使用中,为了无人值守,会加上nohup命令:nohup pserve development.ini --reload &

kotti_ai需要本地启动Paddle Serving c++服务,也就是需要启动9400端口才行。所以目前我们在AIStudio下无法正常运行。

ps:大家也可以学习下Kotti和Pyramid框架,他们都相当优秀。

5、浏览器测试

打开浏览器,默认是5000端口
http://127.0.0.1:5000

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hmRCMNZ8-1664269547451)(https://ai-studio-static-online.cdn.bcebos.com/26fda8be7279459095364f73cf4dab1ee7913670989d49c593fdb259c9fbfc98)]

点击菜单Add-AImage,上传图片,就可以看到图片识别效果了。

在work目录放了几张图片,大家可以在测试网站http://airoot.org:5000/ 上传图片看看效果。

四、调试

因为PaddleClas刚刚升级版本,手册和配置文件有些地方版本还有问题,要稍后解决

config.yaml文件配置大约不对

            #uci模型路径
            # model_config: ../../models/general_PPLCNet_x2_5_lite_v1.0_serving general_PPLCNetV2_base_pretrained_v1.0_serving deploy/models/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_serving
            model_config: ../../models/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_serving

pipeline_http_client.py调用的还是以前的数据集

# imgpath = "../../drink_dataset_v1.0/test_images/001.jpeg"
imgpath = "../../drink_dataset_v2.0/test_images/001.jpeg"

Kotti、kotti_ai的坑

  • 库fanstatic 需要python3.8以上版本。
  • 若有相关库报错,写上这句: from sqlalchemy import Integer, UnicodeText, String
  • 若有报错,title=(u’Document’)改为 = TranslationStringFactory(‘kotti_addon’)

麒麟芯片碰到的问题

如果设备不支持mkldnn,请把配置里的enable_mkldnn设置成False enable_mkldnn: False

nginx代理的问题

多机代理的时候,若有问题,则加上这句proxy_set_header Host $host:$server_port;

结束语

让我们荡起双桨,在AI的海洋乘风破浪!

飞桨官网:https://www.paddlepaddle.org.cn

因为水平有限,难免有不足之处,还请大家多多帮助。

作者:段春华, 网名skywalk 或 天马行空,济宁市极快软件科技有限公司的AI架构师,百度飞桨PPDE。

我在AI Studio上获得至尊等级,点亮10个徽章,来互关呀~ https://aistudio.baidu.com/aistudio/personalcenter/thirdview/141218

此文章为搬运
原项目链接

Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐