Deploy inference services

更新时间:
复制 MD 格式

Deploy models to PAI and create inference services using high-level APIs from the PAI Python SDK.

How it works

The PAI Python SDK provides two high-level classes — pai.model.Model and pai.predictor.Predictor — to deploy models to Elastic Algorithm Service (EAS) and send inference requests.

All deployments follow the same four-step pattern:

  1. Define the inference runtime in an InferenceSpec object (choose a built-in processor or a custom runtime image).

  2. Create a Model object from the InferenceSpec and the path to your model artifacts.

  3. Call model.deploy() to create an inference service in PAI. Specify the instance type, service name, and any other options.

  4. deploy() returns a Predictor object. Call .predict() to send inference requests to the running service.

from pai.model import InferenceSpec, Model, container_serving_spec
from pai.image import retrieve, ImageScope

# Step 1: Retrieve a PAI-provided PyTorch inference runtime image.
torch_image = retrieve("PyTorch", framework_version="latest",
    image_scope=ImageScope.INFERENCE)

# Step 2: Define the inference runtime using InferenceSpec.
inference_spec = container_serving_spec(
    command="python app.py",
    source_dir="./src/",
    image_uri=torch_image.image_uri,
)

# Step 3: Create a Model object.
model = Model(
    model_data="oss://<your-bucket>/path-to-model-artifacts",
    inference_spec=inference_spec,
)

# Step 4: Deploy to PAI-EAS and get a Predictor.
predictor = model.deploy(
    service_name="example_torch_service",
    instance_type="ecs.c6.xlarge",
)

# Send an inference request.
result = predictor.predict(data=data)

Prerequisites

Before you begin, make sure you have:

  • The PAI Python SDK installed

  • An OSS bucket containing your model artifacts, or a local model directory

  • An ECS instance type for the inference service (for example, ecs.c6.xlarge)

  • (Optional) A custom Docker image pushed to an Alibaba Cloud Container Registry (ACR) repository, if deploying with a custom runtime image

Configure InferenceSpec

pai.model.InferenceSpec defines how PAI runs your inference service. Choose between a built-in processor (simpler) or a custom runtime image (more flexible).

Use a built-in processor

A processor is a PAI abstraction that builds an inference service directly from your model artifacts, without writing any serving code. PAI provides built-in processors for common model formats including TensorFlow SavedModel, PyTorch TorchScript, XGBoost, LightGBM, and PMML. For the full list, see Built-in processors.

Pass the processor name as a string to InferenceSpec:

# TensorFlow processor.
tf_infer_spec = InferenceSpec(processor="tensorflow_cpu_2.3")

# PyTorch processor.
torch_infer_spec = InferenceSpec(processor="pytorch_cpu_1.10")

# XGBoost processor.
xgb_infer_spec = InferenceSpec(processor="xgboost")

Configure additional service options — such as warm-up data or RPC settings — directly on the InferenceSpec instance:

# Path to warm-up data stored in OSS.
tf_infer_spec.warm_up_data_path = "oss://<your-oss-bucket>/path/to/warmup-data"

# Keep-alive duration (in milliseconds) for request connections.
tf_infer_spec.metadata.rpc.keepalive = 1000

For all available service parameters, see JSON-based deployment.

Use a runtime image

For models or services with complex dependencies — or when you need full control over the serving environment — deploy using a custom Docker image instead of a processor.

Deploy from a pre-built image

Package your inference code and dependencies into a Docker image, push it to an ACR repository, then build an InferenceSpec from the image URI:

from pai.model import InferenceSpec, Model, container_serving_spec

container_infer_spec = container_serving_spec(
    # URI of your custom Docker image.
    image_uri="<your-custom-image-uri>",
    # Port the service listens on inside the container. PAI routes prediction requests to this port.
    port=8000,
    environment_variables=environment_variables,
    # Command to start the inference service.
    command=command,
    # Additional Python packages to install at startup.
    requirements=[
        "scikit-learn",
        "fastapi==0.87.0",
    ],
)

m = Model(
    model_data="oss://<your-oss-bucket>/path-to-tensorflow-saved-model",
    inference_spec=container_infer_spec,
)
p = m.deploy(instance_type="ecs.c6.xlarge")

Deploy from local code without building an image

The SDK can package and upload a local code directory automatically — no manual image build required. Specify source_dir in container_serving_spec(). The SDK uploads that directory to an OSS bucket and mounts it to /ml/usercode/ in the running container. The start command runs with /ml/usercode as the working directory.

from pai.model import InferenceSpec, container_serving_spec

inference_spec = container_serving_spec(
    # Local directory containing your inference code.
    # The SDK uploads it to OSS and mounts it at /ml/usercode/ in the container.
    source_dir="./src",
    # Runs with /ml/usercode as the working directory.
    command="python run.py",
    image_uri="<serving-image-uri>",
    requirements=[
        "fastapi",
        "uvicorn",
    ],
)

Mount additional data to the container

To load tokenizers, lookup tables, or other artifacts into the container at runtime, call InferenceSpec.mount():

# Upload a local directory to OSS and mount it at /ml/tokenizers/.
inference_spec.mount("./bert_tokenizers/", "/ml/tokenizers/")

# Mount data already stored in OSS to /ml/data/.
inference_spec.mount("oss://<your-oss-bucket>/path/to/data/", "/ml/data/")

Retrieve PAI-provided runtime images

PAI publishes inference runtime images for TensorFlow, PyTorch, and XGBoost. Pass image_scope=ImageScope.INFERENCE to list_images() or retrieve() to get them:

from pai.image import retrieve, ImageScope, list_images

# List all PAI PyTorch inference images.
for image_info in list_images(framework_name="PyTorch", image_scope=ImageScope.INFERENCE):
    print(image_info)

# Get a specific version (CPU).
retrieve(framework_name="PyTorch", framework_version="1.12", image_scope=ImageScope.INFERENCE)

# Get a GPU-accelerated image.
retrieve(framework_name="PyTorch", framework_version="1.12",
    accelerator_type="GPU", image_scope=ImageScope.INFERENCE)

# Get the latest GPU image.
retrieve(framework_name="PyTorch", framework_version="latest",
    accelerator_type="GPU", image_scope=ImageScope.INFERENCE)

Deploy an inference service

Build a Model object from an InferenceSpec and the path to your model artifacts, then call .deploy(). The model_data parameter accepts an OSS URI or a local path — for a local path, the SDK uploads the artifacts to an OSS bucket automatically.

from pai.model import Model, InferenceSpec
from pai.predictor import Predictor

model = Model(
    # OSS URI or local path to your model artifacts.
    model_data="oss://<your-bucket>/path-to-model-artifacts",
    inference_spec=inference_spec,
)

predictor = model.deploy(
    # Name of the inference service.
    service_name="example_xgb_service",
    # ECS instance type for each service instance.
    instance_type="ecs.c6.xlarge",
    # Number of service instances.
    instance_count=2,
    # (Optional) Dedicated resource group. Defaults to the public resource group.
    # resource_id="<your-eas-resource-group-id>",
    options={
        "metadata.rpc.batching": True,
        "metadata.rpc.keepalive": 50000,
        "metadata.rpc.max_batch_size": 16,
        "warm_up_data_path": "oss://<your-oss-bucket>/path-to-warmup-data",
    },
)

For advanced deployment parameters, see JSON-based deployment.

model.deploy() parameters

ParameterTypeDescription
service_namestringName of the inference service
instance_typestringECS instance type (e.g., ecs.c6.xlarge). Use "local" for local testing mode
instance_countintNumber of service instances
resource_idstring(Optional) Dedicated resource group ID. Defaults to the public resource group
optionsdictAdvanced service options (RPC batching, keep-alive, warm-up data path, and others)
serializerobjectSerializer for prediction data. Defaults to the processor's built-in serializer
resource_configResourceConfigCPU and memory allocation per instance. Use instead of instance_type for fine-grained control

Allocate resources by CPU and memory

To control CPU and memory per instance instead of using a predefined instance type, pass a ResourceConfig object:

from pai.model import ResourceConfig

predictor = model.deploy(
    service_name="dedicated_rg_service",
    # Each instance gets 2 CPU cores and 4,000 MB of memory.
    resource_config=ResourceConfig(
        cpu=2,
        memory=4000,
    ),
)

Invoke an inference service

model.deploy() returns a Predictor pointing to the newly created service. To connect to an existing service, construct a Predictor directly using the service name.

from pai.predictor import Predictor, EndpointType

# Connect to a service returned by deploy().
predictor = model.deploy(
    instance_type="ecs.c6.xlarge",
    service_name="example_xgb_service",
)

# Connect to an existing service by name.
predictor = Predictor(
    service_name="example_xgb_service",
    # By default, the service is accessed over the Internet.
    # To access over a VPC network (client must run inside the VPC):
    # endpoint_type=EndpointType.INTRANET,
)

Send prediction requests

Use predict() for standard requests or raw_predict() for full HTTP control:

# Send a prediction request. Input and output are processed by the Serializer.
result = predictor.predict(data_in_nested_list)

# Send a raw HTTP request. Input and output are NOT processed by the Serializer.
response = predictor.raw_predict(
    data=data_in_nested_list,
    # path="predict",     # Custom HTTP path. Defaults to "/".
    # headers=dict(),     # Custom request headers.
    # method="POST",      # HTTP method. Defaults to POST.
    # timeout=30,         # Request timeout in seconds.
)

# Access the response body and headers.
print(response.content, response.headers)
# Deserialize the response body from JSON.
print(response.json())

Manage the service lifecycle

predictor.stop_service()
predictor.start_service()
predictor.delete_service()

Serialize prediction data

When calling predictor.predict(), the SDK uses a Serializer to convert Python objects to bytes before sending the request, and to convert the HTTP response body back into a Python object.

predict(data=...) → serializer.serialize(data) → bytes → HTTP request body
HTTP response body → serializer.deserialize() → Python object

PAI provides built-in serializers for common use cases. Each built-in processor uses a matching serializer by default.

SerializerDefault forInput/output format
JsonSerializerXGBoost, PMML processorsJSON
TensorFlowSerializerTensorFlow processorProtocol Buffers
PyTorchSerializerPyTorch processorProtocol Buffers
Custom (SerializerBase)Any serviceAny

JsonSerializer

JsonSerializer serializes a numpy.ndarray or list to a JSON string and deserializes the response back to a Python object. XGBoost and PMML processors use JsonSerializer by default.

from pai.serializers import JsonSerializer

# Deploy with an explicit serializer (optional for XGBoost — it's the default).
p = Model(
    inference_spec=InferenceSpec(processor="xgboost"),
    model_data="oss://<your-oss-bucket>/path-to-xgboost-model"
).deploy(
    instance_type="ecs.c6.xlarge",
    serializer=JsonSerializer(),
)

# Or attach a serializer to an existing Predictor.
p = Predictor(
    service_name="example_xgb_service",
    serializer=JsonSerializer(),
)

result = p.predict([[2, 3, 4], [4, 5, 6]])

TensorFlowSerializer

Use the PAI TensorFlow processor to deploy a TensorFlow SavedModel. The service exchanges data using Protocol Buffers. TensorFlowSerializer converts numpy.ndarray inputs to Protocol Buffers messages and deserializes responses back to numpy.ndarray. See tf_predict.proto for the message format.

The TensorFlow processor uses TensorFlowSerializer by default.

tf_predictor = Model(
    inference_spec=InferenceSpec(processor="tensorflow_cpu_2.7"),
    model_data="oss://<your-oss-bucket>/path-to-tensorflow-saved-model"
).deploy(
    instance_type="ecs.c6.xlarge",
)

# Inspect the model's input/output signature.
print(tf_predictor.inspect_signature_def())

# Input: a dict where each key is an input signature name and each value is a numpy.ndarray.
tf_result = tf_predictor.predict(data={
    "flatten_input": numpy.zeros(28 * 28 * 2).reshape((-1, 28, 28))
})

assert tf_result["dense_1"].shape == (2, 10)

PyTorchSerializer

Use the PAI PyTorch processor to deploy a model in TorchScript format. The service uses Protocol Buffers for data exchange. PyTorchSerializer converts numpy.ndarray inputs to Protocol Buffers messages and deserializes responses back to numpy.ndarray. See pytorch_predict_proto for the message format.

The PyTorch processor uses PyTorchSerializer by default.

torch_predictor = Model(
    inference_spec=InferenceSpec(processor="pytorch_cpu_1.10"),
    model_data="oss://<your-oss-bucket>/path-to-torchscript-model"
).deploy(
    instance_type="ecs.c6.xlarge",
)

# For multiple inputs, pass a list or tuple of numpy.ndarray objects.
torch_result = torch_predictor.predict(
    data=numpy.zeros(28 * 28 * 2).reshape((-1, 28, 28))
)
assert torch_result.shape == (2, 10)

Custom serializer

For services with non-standard data formats, implement a custom Serializer by inheriting from pai.serializers.SerializerBase and implementing serialize and deserialize.

The following example shows a NumpySerializer that exchanges data in NumPy's .npy binary format:

  1. predict() receives a numpy.ndarray or pandas.DataFrame. NumpySerializer.serialize() converts it to .npy format and sends it in the request body.

  2. The server deserializes the .npy data, runs inference, and returns the result in .npy format.

  3. NumpySerializer.deserialize() converts the response back to a numpy.ndarray.

Test locally before deploying

For custom image deployments, run the inference service locally using Docker before deploying to PAI-EAS. Pass instance_type="local" to model.deploy(). The SDK starts a local container, downloads model artifacts from OSS, and mounts them automatically.

Local mode is only available for custom image deployments. Services deployed using a built-in processor do not support local mode.
from pai.predictor import LocalPredictor

local_predictor: LocalPredictor = model.deploy(
    instance_type="local",
    serializer=JsonSerializer(),
)

local_predictor.predict(data)

# Stop and remove the local Docker container.
local_predictor.delete_service()

What's next

For sample Notebooks demonstrating the deployment process, see Sample code.

References