Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Bentoml BentoML IO Descriptor Multipart

From Leeroopedia
Knowledge Sources
Domains IO Descriptors, Multipart Encoding, API Specification
Last Updated 2026-02-13 15:00 GMT

Overview

The Multipart IO descriptor defines API specification for BentoML services that accept or return multipart form data, composing multiple child IO descriptors into a single request/response.

Description

The Multipart class is an IO descriptor that handles multipart/form-data inputs and outputs for BentoML services. It extends IODescriptor[Dict[str, Any]] and composes multiple child IO descriptors (such as NumpyNdarray, JSON, Image, Text, File) into named fields of a multipart request. Key features include:

  • Nested descriptor composition: Accepts keyword arguments where each key is a field name and each value is an IODescriptor instance. Nested Multipart descriptors are explicitly disallowed with a validation check in __init__.
  • HTTP request parsing: Uses populate_multipart_requests to split multipart form data into individual sub-requests per field. If field names do not match, falls back to positional matching by iterating through form values and descriptors in order.
  • HTTP response generation: Concurrently converts all field values to individual responses via asyncio.gather, then assembles them into a multipart response using concat_to_multipart_response.
  • gRPC protobuf serialization: Converts between pb.Multipart protobuf messages and dictionaries. Uses validate_proto_fields to determine which protobuf representation each child descriptor expects. Supports both v1 and v1alpha1 protocol versions through _to_proto_impl.
  • Input validation: The validate_input_mapping method checks that provided field keys match the declared descriptor keys, raising InvalidArgument for unknown fields.
  • OpenAPI schema generation: Produces an object schema with properties derived from each child descriptor's schema. Aggregates component schemas from all child descriptors.
  • from_sample not supported: The _from_sample method raises NotImplementedError since multipart descriptors cannot be constructed from a single sample.

Usage

Use this descriptor when a BentoML service endpoint needs to accept or return multiple different data types simultaneously, such as an image along with JSON metadata, or a numpy array paired with annotation data.

Code Reference

Source Location

Signature

class Multipart(
    IODescriptor[t.Dict[str, t.Any]],
    descriptor_id="bentoml.io.Multipart",
    proto_fields=("multipart",),
):
    def __init__(self, **inputs: IODescriptor[t.Any]): ...

    def _from_sample(cls, sample: dict[str, t.Any]) -> t.Any: ...
    def input_type(self) -> dict[str, t.Type[t.Any] | UnionType | LazyType[t.Any]]: ...
    def to_spec(self) -> dict[str, t.Any]: ...
    @classmethod
    def from_spec(cls, spec: dict[str, t.Any]) -> t.Self: ...
    def openapi_schema(self) -> Schema: ...
    def openapi_components(self) -> dict[str, t.Any] | None: ...
    def openapi_example(self) -> t.Any: ...
    def openapi_request_body(self) -> dict[str, t.Any]: ...
    def openapi_responses(self) -> OpenAPIResponse: ...
    async def from_http_request(self, request: Request) -> dict[str, t.Any]: ...
    async def to_http_response(self, obj: dict[str, t.Any], ctx: Context | None = None) -> Response: ...
    def validate_input_mapping(self, field: t.MutableMapping[str, t.Any]) -> None: ...
    async def from_proto(self, field: pb.Multipart) -> dict[str, t.Any]: ...
    async def to_proto(self, obj: dict[str, t.Any]) -> pb.Multipart: ...
    async def to_proto_v1alpha1(self, obj: dict[str, t.Any]) -> pb_v1alpha1.Multipart: ...

Import

from bentoml.io import Multipart

I/O Contract

Inputs

Name Type Required Description
**inputs IODescriptor[Any] Yes Keyword arguments where each key is a field name and each value is an IODescriptor instance (e.g., NumpyNdarray, JSON, Image, Text, File). Nested Multipart is not allowed.

Outputs

Name Type Description
dict[str, Any] dict A dictionary mapping field names to their deserialized values, where each value is determined by the corresponding child IO descriptor.

Usage Examples

from __future__ import annotations
from typing import TYPE_CHECKING, Any

import bentoml
from bentoml.io import NumpyNdarray, Multipart, JSON

if TYPE_CHECKING:
    from numpy.typing import NDArray

runner = bentoml.sklearn.get("sklearn_model_clf").to_runner()
svc = bentoml.legacy.Service("iris-classifier", runners=[runner])

input_spec = Multipart(arr=NumpyNdarray(), annotations=JSON())
output_spec = Multipart(output=NumpyNdarray(), result=JSON())

@svc.api(input=input_spec, output=output_spec)
async def predict(
    arr: NDArray[Any], annotations: dict[str, Any]
) -> dict[str, NDArray[Any] | dict[str, Any]]:
    res = await runner.run(arr)
    return {"output": res, "result": annotations}

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment