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

../_images/logo.svg

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

Ray Serve 特别适合模型组合和许多模型服务场景,使您能够构建一个由多个 ML 模型和业务逻辑组成的复杂推理服务,所有这些都用 Python 代码实现。

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("http://localhost: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("http://localhost: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("http://localhost:8000/hello", params={"name": "Theodore"}).json())
# "Hello Theodore!"

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

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

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(
        "http://localhost:8000/", params={"text": "Ray Serve is great!"}
    ).json()
)
# {'label': 'POSITIVE', 'score': 0.9998476505279541}

为什么选择 Serve?#

构建端到端的 ML 驱动应用

许多 ML 服务解决方案专注于“张量进,张量出”的服务:也就是说,它们将 ML 模型封装在预定义、结构化的端点背后。然而,机器学习并非孤立有用。通常将机器学习与业务逻辑和传统 Web 服务逻辑(如数据库查询)结合起来非常重要。

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

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

通常解决问题不仅仅需要一个机器学习模型。例如,图像处理应用通常需要一个多阶段流水线,包括预处理、分割和过滤等步骤,以实现其最终目标。在许多情况下,每个模型可能使用不同的架构或框架,并需要不同的资源(如 CPU 与 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 集群时,Ray Serve 很容易上手。需要部署时,您可以使用我们的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 的博客文章