向应用程序传递参数#
本节介绍如何使用应用程序构建器函数向应用程序传递参数。
定义应用程序构建器#
编写应用程序时,通常会有一些参数希望在开发或生产环境中能够轻松更改。例如,您可能有一个指向训练好的模型权重的路径,并想测试一个新的训练模型。在 Ray Serve 中,这些参数通常使用 .bind()
传递给部署的构造函数。这种模式允许您使用普通的 Python 代码配置部署,但每当参数需要更改时,都需要修改代码。
为了在不更改代码的情况下传递参数,请定义一个“应用程序构建器”函数,该函数接受一个参数字典(或 Pydantic 对象),并返回要运行的已构建应用程序。
from typing import Dict
from ray import serve
from ray.serve import Application
@serve.deployment
class HelloWorld:
def __init__(self, message: str):
self._message = message
print("Message:", self._message)
def __call__(self, request):
return self._message
def app_builder(args: Dict[str, str]) -> Application:
return HelloWorld.bind(args["message"])
您可以在 serve run
CLI 命令或配置文件(如下所示)中使用此应用程序构建器函数作为导入路径。为了避免编写代码来处理类型转换和缺失参数,请改用 Pydantic 对象。
通过 serve run
传递参数#
使用以下语法从 serve run
将参数传递给应用程序构建器
$ serve run hello:app_builder key1=val1 key2=val2
参数将作为字典传递给应用程序构建器,在本例中为 {"key1": "val1", "key2": "val2"}
。例如,要将新消息传递给上面定义的 HelloWorld
应用(代码保存在 hello.py
中)
% serve run hello:app_builder message="Hello from CLI"
2023-05-16 10:47:31,641 INFO scripts.py:404 -- Running import path: 'hello:app_builder'.
2023-05-16 10:47:33,344 INFO worker.py:1615 -- Started a local Ray instance. View the dashboard at http://127.0.0.1:8265
(ServeController pid=56826) INFO 2023-05-16 10:47:35,115 controller 56826 deployment_state.py:1244 - Deploying new version of deployment default_HelloWorld.
(ServeController pid=56826) INFO 2023-05-16 10:47:35,141 controller 56826 deployment_state.py:1483 - Adding 1 replica to deployment default_HelloWorld.
(ProxyActor pid=56828) INFO: Started server process [56828]
(ServeReplica:default_HelloWorld pid=56830) Message: Hello from CLI
2023-05-16 10:47:36,131 SUCC scripts.py:424 -- Deployed Serve app successfully.
请注意,“来自 CLI 的问候”消息是在部署构造函数内部打印的。
通过配置文件传递参数#
在配置文件的 args
字段中将参数传递给应用程序构建器
applications:
- name: MyApp
import_path: hello:app_builder
args:
message: "Hello from config"
例如,要将新消息传递给上面定义的 HelloWorld
应用(代码保存在 hello.py
中,配置文件保存在 config.yaml
中)
% serve run config.yaml
2023-05-16 10:49:25,247 INFO scripts.py:351 -- Running config file: 'config.yaml'.
2023-05-16 10:49:26,949 INFO worker.py:1615 -- Started a local Ray instance. View the dashboard at http://127.0.0.1:8265
2023-05-16 10:49:28,678 SUCC scripts.py:419 -- Submitted deploy config successfully.
(ServeController pid=57109) INFO 2023-05-16 10:49:28,676 controller 57109 controller.py:559 - Building application 'MyApp'.
(ProxyActor pid=57111) INFO: Started server process [57111]
(ServeController pid=57109) INFO 2023-05-16 10:49:28,940 controller 57109 application_state.py:202 - Built application 'MyApp' successfully.
(ServeController pid=57109) INFO 2023-05-16 10:49:28,942 controller 57109 deployment_state.py:1244 - Deploying new version of deployment MyApp_HelloWorld.
(ServeController pid=57109) INFO 2023-05-16 10:49:29,016 controller 57109 deployment_state.py:1483 - Adding 1 replica to deployment MyApp_HelloWorld.
(ServeReplica:MyApp_HelloWorld pid=57113) Message: Hello from config
请注意,“来自 config 的问候”消息是在部署构造函数内部打印的。
使用 Pydantic 为参数添加类型提示#
为了避免手动编写逻辑来解析和验证参数,请将 Pydantic 模型 定义为应用程序构建器函数的单个输入参数类型(该参数必须带有类型注解)。参数传递方式相同,但使用结果字典通过 model.parse_obj(args_dict)
构建 Pydantic 模型。
from pydantic import BaseModel
from ray import serve
from ray.serve import Application
class HelloWorldArgs(BaseModel):
message: str
@serve.deployment
class HelloWorld:
def __init__(self, message: str):
self._message = message
print("Message:", self._message)
def __call__(self, request):
return self._message
def typed_app_builder(args: HelloWorldArgs) -> Application:
return HelloWorld.bind(args.message)
% serve run hello:app_builder message="Hello from CLI"
2023-05-16 10:47:31,641 INFO scripts.py:404 -- Running import path: 'hello:app_builder'.
2023-05-16 10:47:33,344 INFO worker.py:1615 -- Started a local Ray instance. View the dashboard at http://127.0.0.1:8265
(ServeController pid=56826) INFO 2023-05-16 10:47:35,115 controller 56826 deployment_state.py:1244 - Deploying new version of deployment default_HelloWorld.
(ServeController pid=56826) INFO 2023-05-16 10:47:35,141 controller 56826 deployment_state.py:1483 - Adding 1 replica to deployment default_HelloWorld.
(ProxyActor pid=56828) INFO: Started server process [56828]
(ServeReplica:default_HelloWorld pid=56830) Message: Hello from CLI
2023-05-16 10:47:36,131 SUCC scripts.py:424 -- Deployed Serve app successfully.
常见模式#
使用同一个构建器构建多个参数化应用程序#
您可以使用应用程序构建器运行使用相同代码但参数不同的多个应用程序。例如,多个应用程序可能共享预处理和 HTTP 处理逻辑,但使用许多不同的训练模型权重。同一个应用程序构建器 import_path
可以接受不同的参数来定义多个应用程序,如下所示
applications:
- name: Model1
import_path: my_module:my_model_code
args:
model_uri: s3://my_bucket/model_1
- name: Model2
import_path: my_module:my_model_code
args:
model_uri: s3://my_bucket/model_2
- name: Model3
import_path: my_module:my_model_code
args:
model_uri: s3://my_bucket/model_3
配置多个组合部署#
您可以使用传递给应用程序构建器的参数在一个应用程序中配置多个部署。例如,模型组合应用程序可以接受两个不同模型的权重,如下所示
from pydantic import BaseModel
from ray.serve import Application
class ComposedArgs(BaseModel):
model1_uri: str
model2_uri: str
def composed_app_builder(args: ComposedArgs) -> Application:
return IngressDeployment.bind(
Model1.bind(args.model1_uri),
Model2.bind(args.model2_uri),
)