Seldon 使用 (五): engine & graph
在上文https://xie.infoq.cn/article/6aa2eceb59f3f3a7988d272ac,我们提到每个 SeldonDeployment(简称 sdep)的 pod 中都包含一个 engine 容器。这个 engine 容器,是由 seldon-manager 服务为每个 sdep 插入的,用于满足复杂推理场景的需求,如合并(Combine)多个模型推理结果,推理请求处理(Transform-Input),推理结果转换(Transform-Output),以及推理请求路由等对模型推理的请求和结果进行编排
1 示例一(Route):多臂赌博机模型服务
该示例是由 seldon 官方提供的,详细可见https://github.com/SeldonIO/seldon-core/tree/master/components/routers/epsilon-greedy。创建 sdep 定义文件 egreedy.yaml,如下:
说明如下:
graph 定义中模型推理的入口是 name 指定的 eg-router 容器,该容器使用多臂赌博机算法,从三个 childen 容器中选择一个模型服务,然后将推理请求发送给该 childen 容器模型服务处理
graph 中定义的 eg-router 容器和三个 children 容器,分别和 ComponentSpec 中定义了四个容器一一对应
eg-router 容器的多臂赌博机算法,是使用 1-epislon 的概率选择使用历史最佳模型,或者 epislon 概率选择其他模型服务
当 pod 启动后,使用 kubectl describe pod 可以看到,该 pod 内有五个容器(container)。除了上述 4 个容器外,还有一个 seldon-container-engine 容器。engine 容器负责编排上述四个容器,根据 graph 指定的类型(type)为 ROUTER,将先请求发送给 eg-router 获取 childern 容器的 index,然后根据这个 index 获取该容器的端口,完成最后的推理请求
可使用如下脚本,测试推理服务。其中 sys.argv[1]参数,使用 podIP+engine 端口(可通过 kubectl get pod -owide |grep seldon),或者 serviceIP+engine 端口(可通过命令 kubectl get svc -owide |grep seldon 获得)都可以。注:engine 端口号是 8000。
返回结果如下所示。注,本次请求使用的是 classifier-3 模型服务的推理结果。
2 示例二(Transform):输入输出转换
该示例是 seldon 官方提供的,详细可查看https://docs.seldon.io/projects/seldon-core/en/latest/graph/inference-graph.html。创建 seldon-model.yaml,如下所示:
说明:
graph 定义的模型推理入口是 step_one 容器,该容器负载完成 transformer-input(即输入特征转换,例如过滤,默认值,标准化等)
然后模型推理服务由 step_one 容器的 children,即 step_two 容器完成
最后,step_two 容器的推理结果,再由它的 children,即 step_three 容器完成
graph 所定义的三个容器,分别对应到 componentSpec 中定义的三个容器
上述,step_one, step_two, step_three 三个容器的处理过程,同样是由 engine 容器编排完成的。
3 engine 服务如何实现
上面描述的两个推理服务编排(graph),它们都是由 engine 容器服务实现的。那么 engine 容器是如何实现的呢。
engine 容器实现的服务是一个 http 服务,我们这里只看它的主要接口 predictions。实现如下,详细可查看 executor/api/rest/server.go 源码文件
说明:
对于每个请求,创建一个 PredictorProcess。然后将反序列化后的请求,以及 Graph,做为参数,调用 PredictorProcess.Predict()方法,得到推理结果
Predict()方法处理过程如下,详细可查看 executor/predictor/predictor_process.go 源码:
说明:
transformInput():如果 node 的 type 是 MODEL,则调用该节点的 Predict()方法处理。如果是 TRANSFORMER,则调用该节点的 TransformInput()方法处理。
predictChildren(): 如果该节点包含 children,且 type 是 ROUTER,则调用其 route()方法获得 index(即后续请求发给哪个 children 节点)
transformOutput(): 如果 node 的 type 是 TRANFORMER,则调用该节点的 TransformOutput()方法转换推理结果
总体,逻辑是比较清晰易懂的。这里只做简单介绍,可大致了解,如需要则可自行阅读源码。
4 总结
seldon 通过提供 engine 容器及其所定义的 type 和相应的逻辑,一定程度上满足了模型服务编排的需要。
通常编排服务,都会涉及到底层资源的信息,包括服务地址,如何寻址,通信方式等,这些细节,对于不同的底层资源,实现方式会有所不同。但是这些细节,却又不是模型服务所关心的。而 engine 容器,正好可以满足这种需求,即屏蔽了底层资源细节,同时又满足了模型服务编排(graph)的需求。
版权声明: 本文为 InfoQ 作者【托内多】的原创文章。
原文链接:【http://xie.infoq.cn/article/b9173f4266af59b4ecf4e163c】。文章转载请联系作者。
评论