前言
PART.1
AI 的快速发展,尤其是以ChatGPT为代表的大模型带来的新一轮AI技术浪潮,极大地助推了AI模型的推理决策能力在企业业务场景的落地,帮助企业最大化业务效益。模型推理作为模型生命周期中最关键的一环,是对业务数据进行预处理,输入给预训练好的模型,产生预测结果的过程。
在实际生产实践中,模型推理涉及到模型部署、依赖服务集成(如特征数据服务、模型服务)、主流框架支持,以及模型指标监控等。模型推理平台就是在工程上解决这些问题,缩短模型在业务上的落地时间。
eBay AI平台部门在内部私有云上构建了模型推理平台,目前广泛应用在各个业务团队,包括搜索、推荐、广告、营销、风控、买家卖家体验等。在构建推理平台过程中,我们总结了一些实践心得,将以系列文章的方式和大家分享,包括以下几个方面:
模型推理平台核心功能和整体架构,及主流框架支持
模型生命周期管理
模型端到端服务优化
模型资源优化
模型特征监控
大模型落地实践
本篇作为整个系列的开端,将围绕模型推理在eBay 内部的挑战,介绍推理平台提供的核心功能,以及构建这些核心功能的平台架构实践。
模型推理场景对平台的挑战
PART.2
模型生命周期和模型推理简介
一个典型的机器学习模型生命周期包含四个步骤:
数据(训练集)准备,从业务数据中通过特征工程提取模型需要的训练集。
模型训练:包含模型实验,训练流水线和超参调优。
模型管理:对训练的不同版本的模型进行统一管理。
模型部署和推理:将训练好的模型部署到线上,应用在业务场景里。
模型推理属于模型生命周期里最为关键的一个环节,负责将训练好的模型部署起来,对外接受大规模线上请求,提供预测服务能力。
模型推理挑战
eBay 模型推理平台服务几乎覆盖所有内部的业务团队。目前生产环境服役的模型实例有几百个,这些模型每天给平台带来数十亿次的推理请求流量。
推理平台支持这些业务场景,主要存在以下几个挑战:
模型研发效率
随着AI技术的发展,模型迭代速度越来越快,如何降低模型生产落地时间(Time-to-market),就需要平台提供快速落地的能力,主要体现在几个方面:
自助式服务(self-service)。对于绝大部分模型来说,不需要额外的代码或者少量的代码,加上简易的UI步骤即可以完成模型的部署上线、模型验证和模型特征观测能力。
持续集成和持续部署(CI/CD)。需要面向模型更新的场景(镜像依赖、代码及模型版本升级)提供自动化的持续集成和部署方案。
端到端自动化。模型推理涉及需要的预训练的模型以及模型需要的特征信息,预训练模型产自于模型训练平台,而特征数据来自特征平台,平台层面需要端到端做无缝集成,尽量做到对用户透明。
不同维度的可靠性保证
主要包含:
高可用性。在推理平台部署的很多模型直接被主链路业务使用,对于这类场景平台要保证模型服务达到5个9以上的高可用保证。
性能可靠性。平台要要针对两种典型的推理场景提供不同的性能保障策略:实时场景的低延迟推理和近实时场景的高吞吐推理。
可伸缩性。一些业务场景具有典型的峰值流量特性,要针对这种场景优化资源分配的同时,保证能及时按需获取需要的资源。
隔离性。推理平台面向不同业务部门,不同业务部门内部有不同场景的模型推理需求,需要合理定义资源隔离粒度,在业务扩展性和平台维护易用性之间做权衡。
可观测性
在机器学习领域,可观测性除了传统意义上平台系统层面的可观测性指标外,还有模型指标的可观测。这是因为模型推理有两个典型的特征:
1) 所用的模型是在特定样本数据上训练出来的
2) 推理所输入的数据是未见过的
因此我们需要及时发现模型真实预测下的特征输入,相比训练数据中的特征,有没有统计分布的偏移。这是模型特征监控的目的,在模型反馈回路「Feedback loop」中至关重要,可以帮助用户做模型迭代决策参考。
异构资源调度和优化
在eBay 内部,越来越多的推理场景使用深度学习模型或大语言模型,这些模型需要GPU进行加速计算。如何调度GPU 资源以及最大化GPU的利用率,尤其随着模型架构的演化,给平台带来越来越大的挑战。
多环境管理
从用户视角,模型通常先部署在演练环境做功能测试,然后部署到预发环境做性能测试,最后部署到生产环境。推理平台需要支持用户在统一入口实现多环境部署。
统一推理平台架构实践
PART.3
整体架构
基于模型推理的核心需求,及内部推理应用场景的挑战,我们在设计上核心考虑几个架构原则:
基于统一元数据和配置驱动,从而实现轻量级的模型迭代
统一模型生命周期管理及API实现,为平台Portal 及业务部门系统提供统一集成能力
支持异构计算资源调度部署, 支持主流机器学习框架
无缝集成上游特征平台和模型训练平台,实现机器学习平台端到端自动化
业务隔离,不同业务场景的模型推理及迭代相互不影响
基于这些原则,我们统一推理平台的架构如下:
整个推理平台服务于内部的不同团队,通过多租户的方式提供服务,在物理资源上做租户间隔离。
模型推理构建在内部K8S云原生平台上,对下通过Model Deployment Service 统一对底层资源进行管控,对上通过Model Management Service 提供模型生命周期管理API。
服务层面,我们采取了两层服务架构的模式:网关服务 + 模型服务。采用这样的领域模型有几个原因:
集成标准化 + 模型异构化的支持。一方面,模型的预测依赖来自其它系统的数据,例如特征存储,平台需要提供标准集成能力,这个可以通过在网关服务层实现这些数据源的集成,减轻用户部署集成成本;另一方面,不同模型可能由不同的框架训练出来的,部署时需要不同的硬件资源,所以需要提供可扩展的模型服务能力,所以通过把模型本身解耦到单独的服务来实现。
多模型(或模型版本)切换能力。在实际业务场景中,模型有两种迭代方式 1) 利用更强大的模型 2)利用最新数据更新已有模型。直接做部署更新往往在生产里有一定的风险,所以往往用户会部署一个单独的模型实例,做充分验证后切换应用需要的实例。我们在网关服务层做了一层服务内路由,实现配置驱动的多模型切换,而无需客户端做任何修改。
服务调用编排。完成一次推理请求,往往涉及多个步骤,包括特征预取和处理,模型调用以及模型后处理等。平台侧也有一些内置的能力做推理的集成,例如模型特征监控需要的日志(model logging)功能,这些功能往往需要在推理调用时同时调用,但为了不影响线上,处理流程是异步的。这些需求都需要在模型调用之上,需要一个可扩展的调用编排组件。
在端到端集成上,推理平台打通了特征工程平台和模型训练平台,正向上用户可以通过简单的模型规范定义(model specification)完成模型的推理部署上线,反向上通过内置的模型日志(model logging) 能力,提供线上特征快照能力,方便线下基于新的特征生成训练集,基于新的训练集训练和迭代线上模型。
核心功能
推理平台面向业务场景提供一些核心功能,下面选择其中几个最常用的功能做介绍。
推理平台的两层服务架构里,网关服务是随着租户(内部称做resource pool)创建而创建的,各个模型实例的部署是用户按需(on-demand) 自助部署,我们利用云原生Tekton实现了一套部署流水线完成:
跨数据中心部署,高可用保证,线上模型服务对下游服务本地访问友好以及数据中心瘫痪容灾。
自动构建模型服务,实现网关服务对接自动化。
部署流水线任务中,平台根据不同模型需要的硬件标准套餐(flavor SKU), 实现异构资源部署。目前大部分MLApp 需要的推理资源是CPU,但是越来越多的推理资源需求GPU,平台提供了几类主要的GPU规格。
V100
A100 1g10Gb MIG
A100 3g40Gb MIG
A100
2A100
为了最大化GPU 资源利用率,上一代推理平台架构支持模型混合部署,即将不同模型部署在一起,通过软件层实现GPU共享。这种方式对模型流量模式有比较高的要求,理想情况是模型流量完全分时错开,但实际情况下,服务型部署相对于任务型部署,GPU 工作负载不可控,均匀分时显然很难做到,因为单个模型的流量变化容易影响其它模型响时间。
我们在新一代的架构中,摒弃了这种架构,取而代之的,是通过新的GPU架构在硬件层实现的虚拟化来实现,即A100 MIG (multi-instance GPU)。在部署原则上:
尽可能将小的模型或者整体流量小的模型,通过最小规格的A100 MIG 部署
对于有特殊硬件需求,例如训练发生在V100 且模型输出对精度要求也高,保持训练推理一致性,部署在和训练使用的同质GPU上。
对于其它大多数深度学习模型,采用中型规格的A100 MIG 部署,我们在GPU 利用率和处理吞吐能力之间作权衡,选了这种规格。因为在目前架构下,为了解决机器硬件碎片化问题,每一个GPU MIG 按照物理节点配比,分配固定比例CPU,CPU 往往负责做一些预处理计算,划分MIG 太小,会导致CPU太少造成的计算瓶颈。平台目前也在探索通过CPU/GPU 分离的方式(例如引入开源社区Ray)来实现更好的GPU利用率。
模型迭代是机器学习平台要解决的场景。对于一个业务场景来说,开始可能是用模型A部署的实例来服务业务请求,但运行一段时间后,可能因为有了新的数据,模型A更新了自己的版本到A’; 也有可能是业务方训练了一个更好的模型B而部署了实例。这两种场景都需要切换客户端使用的模型实例。在推理平台,我们通过引入模型执行类型的概念来解决这个问题。
每一个模型版本部署的可服务实例,我们称做模型应用(MLapp),MLApp 是用来解决一个特定的业务,一个或者多个解决同一个业务场景的模型实例,我们在逻辑上组织在一个推理服务(Inference Service)下。
每一个MLApp 有一个属性: 模型执行类型,包含两种类型:Champion和Challenger。同一个Inference Service下只有一个MLApp 是Champion(有一种情况特殊,下面模型分割部分介绍),其它都是Challenger。在推理请求发生时,也只有Champion 才会真正处理请求。
通过这种建模,我们对外提供的服务默认是在Inference Service 粒度(也提供显式基于MLApp 粒度的),当请求发生时,我们通过模型执行类型选择Champion MLApp 处理请求。
非Champion模型默认会被异步调用,结果通过模型日志功能转存到线下,方便做离线模型评估。
在eBay 内部的场景里,模型分割指的是用同质模型,解决不同站点的同一业务场景。特点是部署实例里使用的模型架构是一样的,但是训练所用的模型数据是不一样的,但是业务处理流程是一样的,所以这个就要求在模型推理侧,根据推理上下文选择合适的模型服务实例。
在推理平台,模型分割是通过在MLApp 层增加selector 实现。
具体地说:对于一个Segmentation场景,部署的MLApp 具有selector 属性,它是一个表达式,将请求上下文应用到表达式后可以判断出当前MLApp 是否是需要处理请求的MLApp,从而完成模型请求路由。
所以在一个Segmentation的场景里,Champion 和 Selector 一起决定了需要服务当前请求的模型,一个inference service 下有一个或者多个Champion MLApp,服务不同的selector。
在一些场景里,一次模型推理需要多个模型配合完成,上一个模型的输出是下一个模型的输入,这种场景成为Model Chain。
Model Chain 根据实际情况,有两种支持实现:
在MLApp 部署实例内。物理视角多个子模型部署在同一个K8S Pod里,适合低延迟需求且模型的物理资源有同构需求,例如需要同一类GPU。
不同的MLApp 部署实例。在模型服务编排里,我们支持申明式模型特征,即model as feature,在网关服务层实现预取和调用编排。这种拓扑适合模型资源异构,或依赖模型在不同MLApp 之间共享(从而实现资源优化)。
机器学习模型是不停地迭代的,核心原因是因为模型是通过历史数据训练出来的,而模型预测是在新的数据上。所以这个就带来两个典型的需求:
要定期用最新的生产产生的数据来更新模型参数
要实时查看生产特征数据,通过定量分析判别模型是否产生漂移(drift)
平台通过提供模型日志(Model logging)能力来解决这两个需求。
Model Logging 是通过配置或者编程的方式,将线上推理过程中的模型输入(特征)和模型结果,通过异步的方式写入离线存储(HDFS),进而方便离线分析。
Model Logging 发生在线上,要尽量做到线上请求性能无损或几乎无损,我们在架构和实现层面做了权衡和优化:
网关服务层针对Logging I/O 场景的优化,并且网关服务层通过side car container 实现logging client 代理
离线转存采用内部Kafka 集群 + Flink Job 实现。因为Model logging 提供给不同租户,不同租户的网关服务规模不同,防止同时大量Pod 连接同一个Kafka Broker 会产生不稳定的问题,我们在架构上通过加一层logging service 做一层聚合。
在这样统一的Logging 架构下,我们可以非常方便地实现基于线上数据的新训练集的生成,以及模型指标监控。
下图演示了基于logging 的新训练集生成过程。推理请求的输入通过logging 记录到离线Hive 表中,特征ETL Job 会定时(每日)去分析离线表的数据,然后将输入特征打平存在特征表中。当用户有需要时,可以根据准备好的request ID 以及label 信息,和feature 表做join 生成新的训练集合。
同样的,模型指标监控也是基于model logging。我们和内部的监控平台(Sherlock) 合作,通过在model logging service 采集特征实时数据,从而方便地通过监控平台针对不同特征定义监控面板。甚至可以通过集成监控平台,基于采集的特征数据,做一些统计分析,例如(PSI计算)。
关于模型监控的细节,系列后续章节会详细介绍。
机器学习框架支持
推理平台的模型来自不同的训练框架,或者被不同的框架加以优化,因此在模型推理服务层,我们考虑异构资源部署外,还要考虑模型的异构性。
目前推理平台支持典型的三种类型的推理场景,并提供对应的框架支持:
主流深度学习框架训练的模型例如Tensorflow,Pytorch及ONNX。这些模型通常是深度学习模型,并且有规范化的格式。这类模型的特点是在部署的时候,除了预处理外,模型本身不需要提供额外的代码,我们推理运行时框架会自动加载运行模型。
自定义Python 推理逻辑。这类模型通常都是一些传统机器学习模型,并且模型有一些特定的依赖库,因为模型相关,这些依赖库往往被打包在模型运行需要的docker 镜像里,所以我们称为container based model。针对这种类型的模型,我们开发了一套自研的GRPC 服务协议实现模型的加载运行。
LLM 模型。LLM 推理有它自身的特性,例如它是token generation的,这个带来对框架支持及优化的需求。我们推理平台也是针对LLM 做了服务层优化处理(如Streaming API & Early Termination),并集成了业界流行的LLM 框架VLLM 在模型服务层。
在架构上,我们在接口层,通过统一的类型系统统一模型规范,在模型服务层则根据部署时选择的不同服务框架,映射到底层服务框架的GRPC handler,完成一次推理调用。
因历史原因,不同框架平台选择了不同的服务实现策略。随着架构的演化,我们在保证向后兼容的同时,也在整合服务实现框架统一到基于Nvidia的Triton的实现。我们会在后续的文章有更多关于Triton服务集成的介绍。
总结
PART.4
本文介绍了eBay 机器学习平台团队在模型推理上的一些架构实践,重点分析了推理平台要处理的业务场景及其带来的挑战,在此基础上介绍了我们架构上的考量和设计,以及推理平台提供的核心功能包括机器学习框架的支持。
这是推理系列的开篇,后续文章会针对一些特定的主题,展开分享我们在模型生命周期管理、服务和资源优化,模型特征监控和大模型落地方面的实践。