Ray Serve:可扩展且可编程的服务#

../_images/logo.svg

Ray Serve 是一个可扩展的模型服务库,用于构建在线推理 API。Serve 支持框架无关,因此您可以使用单一工具包来服务从 PyTorch、TensorFlow 和 Keras 等框架构建的深度学习模型,到 Scikit-Learn 模型,再到任意 Python 业务逻辑。它具有多项功能和性能优化,用于大型语言模型(LLM)的服务,例如响应流式传输、动态请求批处理、多节点/多 GPU 服务等。

Ray Serve 特别适合模型组合和多模型服务,使您能够使用 Python 代码构建一个由多个 ML 模型和业务逻辑组成的复杂推理服务。

Ray Serve 构建在 Ray 之上,因此可以轻松扩展到多台机器,并提供灵活的调度支持,例如分数 GPU,以便您可以共享资源并以低成本服务许多机器学习模型。

快速入门#

安装 Ray Serve 及其依赖项

pip install "ray[serve]"

定义一个简单的“hello world”应用程序,在本地运行它,并通过 HTTP 查询它。

import requests
from starlette.requests import Request
from typing import Dict

from ray import serve


# 1: Define a Ray Serve application.
@serve.deployment
class MyModelDeployment:
    def __init__(self, msg: str):
        # Initialize model state: could be very large neural net weights.
        self._msg = msg

    def __call__(self, request: Request) -> Dict:
        return {"result": self._msg}


app = MyModelDeployment.bind(msg="Hello world!")

# 2: Deploy the application locally.
serve.run(app, route_prefix="/")

# 3: Query the application and print the result.
print(requests.get("https://:8000/").json())
# {'result': 'Hello world!'}

更多示例#

使用 Serve 的模型组合 API 将多个部署组合成一个应用程序。

import requests
import starlette
from typing import Dict
from ray import serve
from ray.serve.handle import DeploymentHandle


# 1. Define the models in our composition graph and an ingress that calls them.
@serve.deployment
class Adder:
    def __init__(self, increment: int):
        self.increment = increment

    def add(self, inp: int):
        return self.increment + inp


@serve.deployment
class Combiner:
    def average(self, *inputs) -> float:
        return sum(inputs) / len(inputs)


@serve.deployment
class Ingress:
    def __init__(
        self,
        adder1: DeploymentHandle,
        adder2: DeploymentHandle,
        combiner: DeploymentHandle,
    ):
        self._adder1 = adder1
        self._adder2 = adder2
        self._combiner = combiner

    async def __call__(self, request: starlette.requests.Request) -> Dict[str, float]:
        input_json = await request.json()
        final_result = await self._combiner.average.remote(
            self._adder1.add.remote(input_json["val"]),
            self._adder2.add.remote(input_json["val"]),
        )
        return {"result": final_result}


# 2. Build the application consisting of the models and ingress.
app = Ingress.bind(Adder.bind(increment=1), Adder.bind(increment=2), Combiner.bind())
serve.run(app)

# 3: Query the application and print the result.
print(requests.post("https://:8000/", json={"val": 100.0}).json())
# {"result": 101.5}

使用 Serve 的FastAPI 集成,优雅地处理 HTTP 解析和验证。

import requests
from fastapi import FastAPI
from ray import serve

# 1: Define a FastAPI app and wrap it in a deployment with a route handler.
app = FastAPI()


@serve.deployment
@serve.ingress(app)
class FastAPIDeployment:
    # FastAPI will automatically parse the HTTP request for us.
    @app.get("/hello")
    def say_hello(self, name: str) -> str:
        return f"Hello {name}!"


# 2: Deploy the deployment.
serve.run(FastAPIDeployment.bind(), route_prefix="/")

# 3: Query the deployment and print the result.
print(requests.get("https://:8000/hello", params={"name": "Theodore"}).json())
# "Hello Theodore!"

要运行此示例,请安装以下内容:pip install transformers

使用 Ray Serve 来服务预训练的Hugging Face Transformers 模型。我们将使用的模型是一个情感分析模型:它将接收文本字符串作为输入,并返回文本是“正面”还是“负面”。

import requests
from starlette.requests import Request
from typing import Dict

from transformers import pipeline

from ray import serve


# 1: Wrap the pretrained sentiment analysis model in a Serve deployment.
@serve.deployment
class SentimentAnalysisDeployment:
    def __init__(self):
        self._model = pipeline("sentiment-analysis")

    def __call__(self, request: Request) -> Dict:
        return self._model(request.query_params["text"])[0]


# 2: Deploy the deployment.
serve.run(SentimentAnalysisDeployment.bind(), route_prefix="/")

# 3: Query the deployment and print the result.
print(
    requests.get(
        "https://:8000/", params={"text": "Ray Serve is great!"}
    ).json()
)
# {'label': 'POSITIVE', 'score': 0.9998476505279541}

为什么选择 Serve?#

构建端到端 ML 驱动的应用程序

许多 ML 服务解决方案都专注于“输入张量,输出张量”的服务:也就是说,它们将 ML 模型包装在一个预定义的、结构化的端点后面。然而,机器学习本身并没有用。将机器学习与业务逻辑和传统 Web 服务逻辑(如数据库查询)相结合通常很重要。

Ray Serve 的独特之处在于,它允许您在一个框架中构建和部署端到端的分布式服务应用程序。您可以使用 Serve 的 FastAPI 集成(参见FastAPI HTTP 部署)组合多个 ML 模型、业务逻辑和表达性 HTTP 处理,将整个应用程序构建成一个 Python 程序。

使用可编程 API 组合多个模型

解决一个问题通常需要一个以上的机器学习模型。例如,图像处理应用程序通常需要一个多阶段的管道,包括预处理、分割和过滤等步骤来实现最终目标。在许多情况下,每个模型可能使用不同的架构或框架,并需要不同的资源(如 CPU vs GPU)。

许多其他解决方案支持在 YAML 或其他配置语言中定义静态图。这可能会受到限制且难以处理。另一方面,Ray Serve 支持使用可编程 API 进行多模型组合,其中对不同模型的调用就像函数调用一样。模型可以使用不同的资源并在群集中的不同机器上运行,但您可以像编写常规程序一样编写它。有关更多详细信息,请参阅部署模型组合

灵活地扩展和分配资源

机器学习模型是计算密集型的,因此运营成本可能很高。任何 ML 服务系统的关键要求是能够动态地扩展和缩减,并为每个模型分配正确的资源来处理请求负载,同时节省成本。

Serve 提供了一系列内置原语,以帮助提高 ML 服务应用程序的效率。它支持通过调整副本数量来动态扩展或缩减模型的资源,通过批处理请求来利用高效的矢量化操作(在 GPU 上尤其重要),以及一个灵活的资源分配模型,使您能够在有限的硬件资源上服务许多模型。

避免框架或供应商锁定

机器学习发展迅速,新库和模型架构层出不穷,重要的是要避免将自己锁定在与特定框架绑定的解决方案中。这在服务中尤其重要,因为更改基础架构可能耗时、昂贵且有风险。此外,许多托管解决方案仅限于单个云提供商,这在当今的多云世界中可能是一个问题。

Ray Serve 不绑定到任何特定的机器学习库或框架,而是提供一个通用的可扩展服务层。因为它构建在 Ray 之上,所以您可以在 Ray 的任何地方运行它:在您的笔记本电脑、Kubernetes、任何主要的云提供商,甚至本地环境中。

Serve 如何为我这样的… 提供帮助?#

数据科学家

Serve 使您能够轻松地从笔记本电脑迁移到群集。您可以在本地计算机上测试模型(以及整个部署图),然后再将其部署到群集生产环境。您无需了解重量级的 Kubernetes 概念或云配置即可使用 Serve。

ML 工程师

Serve 帮助您扩展部署,并可靠高效地运行它们以节省成本。借助 Serve 的一流模型组合 API,您可以将模型与业务逻辑结合起来,构建端到端的面向用户的应用程序。此外,Serve 原生运行在 Kubernetes 上,具有最小的运维开销。

ML 平台工程师

Serve 专注于可扩展且可靠的 ML 模型服务。因此,它可以成为您的 ML 平台堆栈中的重要即插即用组件。Serve 支持任意 Python 代码,因此可以很好地与 MLOps 生态系统集成。您可以将其与模型优化器(ONNX、TVM)、模型监控系统(Seldon Alibi、Arize)、模型注册表(MLFlow、Weights and Biases)、机器学习框架(XGBoost、Scikit-learn)、数据应用 UI(Gradio、Streamlit)和 Web API 框架(FastAPI、gRPC)结合使用。

LLM 开发人员

Serve 使您能够快速原型化、开发和部署可扩展的 LLM 应用程序到生产环境。许多大型语言模型(LLM)应用程序结合了提示预处理、向量数据库查找、LLM API 调用和响应验证。由于 Serve 支持任何任意 Python 代码,因此您可以将所有这些步骤编写成单个 Python 模块,从而实现快速开发和轻松测试。然后,您可以快速将您的 Ray Serve LLM 应用程序部署到生产环境,并且每个应用程序步骤都可以独立自动扩展,以有效地适应用户流量,而不会浪费资源。为了提高 LLM 应用程序的性能,Ray Serve 具有批处理功能,并且可以与任何模型优化技术集成。Ray Serve 还支持流式响应,这是聊天机器人类应用程序的关键功能。

Serve 与… 相比如何?#

TFServing、TorchServe、ONNXRuntime

Ray Serve 是*框架无关*的,因此您可以将其与任何其他 Python 框架或库一起使用。我们认为数据科学家不应受限于特定的机器学习框架。他们应该能够使用最适合该工作的工具。

与这些特定于框架的解决方案相比,Ray Serve 不执行任何特定于模型的优化来使您的 ML 模型运行得更快。但是,您仍然可以自行优化模型并在 Ray Serve 中运行它们。例如,您可以运行由PyTorch JITONNXRuntime编译的模型。

AWS SageMaker、Azure ML、Google Vertex AI

作为一个开源项目,Ray Serve 将这些托管产品在您自己基础架构上的可扩展性和可靠性带给您。您可以使用 Ray 的群集启动器将 Ray Serve 部署到所有主要的公共云、K8s,以及裸金属、本地机器。

Ray Serve 不是一个功能齐全的 ML 平台。与这些其他产品相比,Ray Serve 缺少管理模型生命周期、可视化其性能等的​​功能。Ray Serve 主要专注于模型服务,并提供原语供您在之上构建自己的 ML 平台。

Seldon、KServe、Cortex

您可以在笔记本电脑上开发 Ray Serve,将其部署在开发机器上,并将其扩展到多台机器或 Kubernetes 群集,所有这些都只需少量或无需代码更改。当您无需预配和管理 K8s 群集时,上手会容易得多。在部署时,您可以使用我们的Kubernetes Operator透明地将您的 Ray Serve 应用程序部署到 K8s。

BentoML、Comet.ml、MLflow

其中许多工具专注于独立地服务和扩展模型。相比之下,Ray Serve 是框架无关的,并专注于模型组合。因此,Ray Serve 可以与任何模型打包和注册表格式一起使用。Ray Serve 还提供了构建生产级机器学习应用程序的关键功能,包括一流的自动扩展以及与业务逻辑的自然集成。

我们坚信 Serve 是独一无二的,因为它使您能够完全控制您的 ML 应用程序,同时提供可扩展性和高性能。要通过其他工具实现 Serve 的功能,您需要将 Tensorflow Serving 和 SageMaker 等多个框架结合起来,甚至需要自己编写微批处理组件来提高吞吐量。

了解更多#

请查看入门关键概念,或者前往示例开始构建您的 Ray Serve 应用程序。

入门

从我们的快速入门教程开始,了解在本地部署单个模型以及如何将现有模型转换为 Ray Serve 部署

关键概念

了解 Ray Serve 背后的关键概念。了解部署如何查询它们,以及使用DeploymentHandles来组合多个模型和业务逻辑。

示例

遵循教程,学习如何将 Ray Serve 与TensorFlowScikit-Learn集成。

API 参考

获取有关 Ray Serve API 的更深入信息。

有关更多信息,请参阅以下有关 Ray Serve 的博客文章