开源algorithm-base框架v3.0

简介: 随着机器学习火遍全球,越来越多的算法服务被开发出来。在算法服务化的过程中,我们经常会遇到如下的问题和需求- 算法工程师希望独立高效的开发出具有一定鲁棒性的服务- 算法工程师与软件工程师的工作边界难以划分- 运维工程师希望将算法服务快速,标准化的部署到生产环境- 政企客户对交付有加密,许可证的需求[Algorithm-Base框架](https://github.com/aliyu

随着机器学习火遍全球,越来越多的算法服务被开发出来。在算法服务化的过程中,我们经常会遇到如下的问题和需求

  • 算法工程师希望独立高效的开发出具有一定鲁棒性的服务
  • 算法工程师与软件工程师的工作边界难以划分
  • 运维工程师希望将算法服务快速,标准化的部署到生产环境
  • 政企客户对交付有加密,许可证的需求

Algorithm-Base框架,就是在这种场景下应运而生了。

方流在这篇文章中已经详细描述了algorithm-base框架v2.0(简称AB框架)的使用场景。鉴于在机器学习领域,各种为训练,实验而生的框架已经数不胜数了,我们觉得不应该重复制造轮子,我们希望提供一套类似Java领域的Spring Boot的框架,让算法工程师开箱即用。因此,Algorithm-Base框架v3.0整合了大量工具,从用户的角度进行重构,开源到阿里云github账号中。下面简述一下3.x版本的主要特性和实践情况。

特性

restful服务

如果你用过flask,一定知道flask通过@route装饰器指定http服务的路由。类似,Algorithm-Base框架使用@algorithm装饰器,以达到类似的目的,同时,可以更方便实现自定义的功能。比如,实现一个路由是/api/algorithm/add的接口,该接口两个输入参数,返回两个入参之和。可以实现如下

# 会自动暴露为/api/algorithm/add接口
@algorithm()
def add(a: int, b: int) -> int:
    """
    一个简单的加法算法示例
    :param a: 第一个参数
    :param b: 第二个参数
    :return:
    """
    logger.info("enter algorithm {}, {} ".format(a, b))
    return a + b

在”家庭医生“这款产品中,全部算法服务接入了AB框架,所有算法API托管于框架的@algorithm装饰器,该装饰器为所有API提供了统一的请求压缩,文档抓取等特性。在”医疗市场“中,算法工程师一次性编写文档,AB框架配合”医疗市场“实现API调试,在线文档,导出文档等功能,把算法工程师从管理文档版本,重复书写文档的琐碎工作中解放出来。

多环境配置

在产品开发的过程中,通常需要区分开发环境,预发环境和生产环境,甚至,在不同的客户部署时,只有些许配置不同。框架支持通过不同的配置启动服务,配置之间保持”继承“关系,比如

  • 使用默认的配置启动服务

pyab

  • 使用test环境的配置启动服务,即使用test环境的配置继承默认配置

pyab test

  • 使用daily环境的配置继承默认配置启动服务,并设置workers的数量为4

workers=4 pyab daily

  • 使用local和daily的配置启动服务,local(靠左侧)的优先级更高,同时继承默认配置

pyab local daily

在“家庭医生”这个产品中,该特性得到了充分体现。同样是“家庭医生”产品,有些客户使用云平台,有些客户使用自建虚拟机,有些客户使用k8s,每个客户的资源各不相同,要求的QPS也不同。如果我们把“配置”固化在算法镜像中,每部署一个环境,都需要构建一个特定的镜像。实际上,利用该特性,算法工程师只需要提交一次镜像,后续配置修改,完全由运维工程师,按照文档进行配置。

数据穿透

有的时候,你的服务需要以接口的形式,把数据库的某些数据局部透出给第三方。当然,你可以手动开发这样的接口,但这会导致不小的工作量,算法工程师一般也不愿意做这样的开发。Alogorithm-Base框架通过简单的配置,帮你搞定这样的需求。在山东医保等项目中,该功能有效的提升了算法同学的工作效率。

DBM = [
    {'table_name': 'template',   # 想要暴露的表名
     'json_columns': 'data',     # 哪些字段是json格式,需要自动dump/load
     'list_columns': 'id,name,gmt_create,gmt_modified,gmt_run'  # 哪些字段需要在列表中显示。有些字段比如data或者二进制列比较大,不想在列表中返回
     'detail_columns': 'id,remark,pk_name', # 哪些字段需要在根据id查询详情的时候返回。有些字段如二进制数据是无法显示在json中的,可以用此字段控制。默认为'*'
     # 更多配置见config.py里说明,此处从略
     },
]

GET /api/table/template?page=1&size=10&name=test
等价于执行 SELECT * from template where name='test' limit 0, 10

支持云原生监控

无需任何配置,访问/metrics 即可看到各个被@algorithm装饰器装饰的算法耗时分布,方法调用耗时分布等,数据格式原生支持了Prometheus,非常方便接入到各类监控服务中。生成的监控数据如下

# HELP general_duration_seconds Multiprocess metric
# TYPE general_duration_seconds histogram
general_duration_seconds_sum{app="simple",name="eureka"} 0.0002838499999999744
general_duration_seconds_sum{app="simple",name="spark"} 0.00013202300000014766
general_duration_seconds_sum{app="simple",name="dbm"} 5.45200000012791e-06
general_duration_seconds_bucket{app="simple",le="0.005",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="0.01",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="0.025",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="0.05",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="0.075",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="0.1",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="0.25",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="0.5",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="0.75",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="1.0",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="2.5",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="5.0",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="7.5",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="10.0",name="eureka"} 1.0
general_duration_seconds_bucket{app="simple",le="+Inf",name="eureka"} 1.0
general_duration_seconds_count{app="simple",name="eureka"} 1.0
# HELP cache_hits_total Multiprocess metric
# TYPE cache_hits_total counter
cache_hits_total 0.0
# HELP cache_wait_timeout_count_total Multiprocess metric
# TYPE cache_wait_timeout_count_total counter
cache_wait_timeout_count_total 0.0
# HELP http_requests_total Multiprocess metric
# TYPE http_requests_total counter
http_requests_total{app="simple",code="200",method="GET",url="/metrics"} 1.0

在”家庭医生“产品中,如果部署基于K8S或ADP,无需任何配置,我们便可以监控到服务的基本情况。通过简单配置,也可以监控到业务逻辑。在实践中,基础监控,是我们进行压力测试,服务资源分配的必不可少的基本依据。

python文件加密

框架内使用Cython对python源码进行”加密“,虽然这不是真正意义的加密,但也足以应对一般的代码泄露问题。我们选择Cython,是因为这几乎是性价比最高的一种方案,无需开发,且易于调试,很少存在兼容性问题。使用框架内置的abt命令,可以让你更高效的使用Cython”加密“,下面的例子是加密项目目录下所有python文件,并排除掉文件路径包含正则表达式"config.*”的文件。

abt encrypt -i ".*" -e "config.*"

数据文件加密

除了对python文件加密,我们也经常遇到数据文件,模型文件加密的需求。命令如下,使用方法同样简单。

abt crypto -i ".*" -e "somedata.*"

值得一提的是,开发时,一般我们使用明文数据。交付打包后,使用密文数据。Algorithm-Base框架为你准备好了一切,只需简单的配置,使用框架提供的打包脚本,自动将明文替换为密文,你也无需修改“读取”方法,当明文存在时,框架读取明文,不存在明文,框架会自动搜索密文读取。

上述两种不同目的的加密方法,分别保护了源代码和资源文件,已经应用到了医疗,监管行的算法服务中。不少接入了AB框架的工程师不知道自己使用过源代码加密功能,那是因为源代码加密是默认开启的,一切都是无感的。AB框架中的加密工具,当然也可以当做独立的工具脱离算法服务使用,

授权许可

在政企交付过程中,为了保护算法镜像不被泄露,我们开发了许可证功能,许可证可以将服务限制在用户的特定一台或多台硬件上,并限制使用的期限。

在调研这个功能时,我本想集成现有的“轮子”,但发现市面上并没有一款适合容器化部署许可的方案,于是这个轮子只能自己来造。我们的目标有以下几点

  • 授权许可功能对算法工程师而言,需要透明,不应让开发者在开发,打包过程中投入过多的时间
  • 对docker的有限保护。从理论上讲,会有多种办法破解许可证,但我们的目的只是增加破解难度,防君子不防小人。

除此之外,框架也支持限制对特定API的细粒度调用次数限制。

支持spring cloud

在“大项目”中,单个算法服务是无法满足需求的,往往需要负载均衡,oauth等功能的配合。Algorithm-Base框架已经集成了eureka,nacos,oauth等客户端,仅需一行配置,就可以把算法服务注册到服务注册中心,并提供oauth的保护。

在”家庭医生“的测试环境中,我们将接入AB框架的算法服务 和开源的若依框架整合到了一起,以极小的代价实现了用户管理等功能。后者,在未来也计划接入税务,监管等其他行业的用户管理系统中。

支持spark和python双计算引擎

这是个很有意思的特性,有些“算法”需要处理大量的数据,大数据是无法在python内完成计算的,这是必须借用计算引擎(如spark)的能力。你只需要在algorithm装饰器上,声明使用spark引擎,即可使用pyspark的api,将spark任务提交出去。

@algorithm(engine="saprk")
def add(data: SparkDataFrame) -> int:
    return data.rdd.getNumPartitions()

容器支持

docker的优势就不用在这里多说了,框架解决的主要问题是,让不那么”懂“docker的开发者,可以快速构建出属于自己的镜像。在项目中,算法工程师通常只需要安装不同的python module,便可以进行开发,而不需要关注操作系统层面。因此,基于框架模板创建的项目,只需要在requirements.txt中添加你需要用到的python module即可,然后使用abt build命令,一键构建出镜像,无需任何其他修改。

阿里云serverless与持续集成

如果你的基础设施搭建在阿里云上,那就更方便了。Algorithm-Base框架提供的abt命令,可以将你的镜像一键上传到镜像容器服务,同时部署到阿里云的serverless应用中。abt也支持一键把提交较大的数据,模型文件同步到阿里云OSS上,实现大文件和代码的分离,abt命令在构建镜像时,会自动聚合OSS上的大文件和git上的代码,从而实现持续集成。

在网络互通的情况下,你只需要提交代码,持续集成引擎可以利用Algorithm-Basev3.0提供的abt命令,将算法代码进行编译,打包,部署到serverless。在“家庭医生”产品中,因为参与产品开发的工程师众多,为了避免代码误提交与误发布,我们添加了“卡点”,实现一键手动发布。事实上,所有接入AB框架的服务,都支持在云端打包,如果不想让自己的笔记本变成电暖气,快来试试Jenkins上的打包功能吧

展望

除了上述功能外,框架中也包含了许多工具类,比如对redis,hive,maxcompute的支持等等。伴随着越来越多的 产品交付给客户,Algorithm-Base框架已经迭代到了v3版本,上面描述的只是Algorithm-Basev3.x的部分特性,这里可以看到更多的特性,欢迎感兴趣的小伙伴来github一起出谋划策!

相关文章
|
2月前
|
机器学习/深度学习 算法 程序员
C++ Algorithm 库 算法秘境探索(Algorithm Wonderland Exploration)
C++ Algorithm 库 算法秘境探索(Algorithm Wonderland Exploration)
77 1
|
3月前
|
机器学习/深度学习 安全 搜索推荐
【现代密码学】笔记3.4-3.7--构造安全加密方案、CPA安全、CCA安全 《introduction to modern cryphtography》
【现代密码学】笔记3.4-3.7--构造安全加密方案、CPA安全、CCA安全 《introduction to modern cryphtography》
67 0
|
4月前
|
存储 算法 安全
C/C++学习 -- Base64算法
C/C++学习 -- Base64算法
25 0
|
7月前
关于 sap.ui.base.Object 的简要介绍
关于 sap.ui.base.Object 的简要介绍
23 0
|
JSON Linux 数据格式
Base64是什么、应用场景、开源库(libb64)使用
Base64是什么、应用场景、开源库(libb64)使用
467 0
|
算法 搜索推荐 Go
AES加密算法简介及Go库介绍|Go主题月
AES(Advanced Encryption Standard)的中文名叫高级加密标准,又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于 2001 年 11 月 26 日发布于 FIPS PUB 197,并在 2002 年 5 月 26 日成为有效的标准。现在,高级加密标准已然成为对称密钥加密中最流行的算法之一。
189 1
|
存储 算法 安全
分布式服务器框架之Servers.Core库实现 DES对称加密算法;SHA1信息摘要算法;MD5信息摘要算法
通信双方(通信主体)同时掌握一个钥匙,加解密都由这一个钥匙完成。通信双方通信前共同拟定一个密钥,不向第三方公开,发送前加密和接受后解密都由此密钥完成。即钥匙如果泄露,将暴露自己的全部信息。
|
算法 数据安全/隐私保护
Qt中base64基础的应用
Qt中base64基础的应用
229 0
Qt中base64基础的应用
|
机器学习/深度学习 自然语言处理 算法
《algorithm-note》算法笔记中文版正式发布!
《algorithm-note》算法笔记中文版正式发布!
220 0
《algorithm-note》算法笔记中文版正式发布!
Basic introduction about SAP SPS (Support Package Stack)
You can get the detailed definition here https://websmp207.sap-ag.de/~sapidb/011000358700003734172003E/
114 0
Basic introduction about SAP SPS (Support Package Stack)