处理依赖#

添加运行时环境#

导入路径(例如,text_ml:app)必须能在运行时被 Serve 导入。在本地运行时,此路径可能位于您当前的目录中。然而,在集群上运行时,您还需要确保此路径可被导入。将代码构建到集群的容器镜像中(有关更多详细信息,请参阅 集群配置)或者使用一个带有 远程 URIruntime_env,该 URI 托管了远程存储中的代码。

有关示例,请参阅 GitHub 上的 Text ML Models 应用程序。您可以即使在本地没有代码的情况下,使用此配置文件将文本摘要和翻译应用程序部署到您自己的 Ray 集群。

import_path: text_ml:app

runtime_env:
    working_dir: "https://github.com/ray-project/serve_config_examples/archive/HEAD.zip"
    pip:
      - torch
      - transformers

注意

您还可以将部署图打包成一个独立的 Python 包,然后使用 PYTHONPATH 来导入,以在本地机器上提供位置无关性。然而,最佳实践是使用 runtime_env,以确保集群中所有机器之间的一致性。

每个部署的依赖项#

Ray Serve 还支持服务具有不同(甚至可能冲突)的 Python 依赖项的部署。例如,您可以同时服务一个使用旧版 Tensorflow 1 的部署和一个使用 Tensorflow 2 的部署。

这在 Mac OS 和 Linux 上通过 Ray 的 运行时环境 功能得到支持。与所有其他 Ray Actor 选项一样,通过部署中的 ray_actor_options 传入运行时环境。请务必先运行 pip install "ray[default]" 以确保 Runtime Environments 功能已安装。

示例

import requests
from starlette.requests import Request

from ray import serve
from ray.serve.handle import DeploymentHandle


@serve.deployment
class Ingress:
    def __init__(
        self, ver_25_handle: DeploymentHandle, ver_26_handle: DeploymentHandle
    ):
        self.ver_25_handle = ver_25_handle
        self.ver_26_handle = ver_26_handle

    async def __call__(self, request: Request):
        if request.query_params["version"] == "25":
            return await self.ver_25_handle.remote()
        else:
            return await self.ver_26_handle.remote()


@serve.deployment
def requests_version():
    return requests.__version__


ver_25 = requests_version.options(
    name="25",
    ray_actor_options={"runtime_env": {"pip": ["requests==2.25.1"]}},
).bind()
ver_26 = requests_version.options(
    name="26",
    ray_actor_options={"runtime_env": {"pip": ["requests==2.26.0"]}},
).bind()

app = Ingress.bind(ver_25, ver_26)
serve.run(app)

assert requests.get("http://127.0.0.1:8000/?version=25").text == "2.25.1"
assert requests.get("http://127.0.0.1:8000/?version=26").text == "2.26.0"

提示

避免动态安装从源代码安装的包:这些包可能安装缓慢,并在安装过程中耗尽所有资源,导致 Ray 集群出现问题。请考虑在私有存储库或 Docker 镜像中预编译此类包。

部署所需的依赖项可能与驱动程序(运行 Serve API 调用的程序)中安装的依赖项不同。在这种情况下,您应该在类中使用延迟导入,以避免在驱动程序中导入不可用的包。即使不使用运行时环境,也适用此规则。

示例

from ray import serve


@serve.deployment
class MyDeployment:
    def __call__(self, model_path):
        from my_module import my_model

        self.model = my_model.load(model_path)