Implementation:Bentoml BentoML IO Models
| Knowledge Sources | |
|---|---|
| Domains | SDK, IO Descriptors, HTTP Serialization |
| Last Updated | 2026-02-13 15:00 GMT |
Overview
Defines the core I/O descriptor model system for the BentoML SDK, providing Pydantic-based classes that automatically infer input/output schemas from Python function signatures and handle HTTP request/response serialization.
Description
This module is the backbone of BentoML's type-safe API contract system. It bridges Python function type annotations to HTTP request parsing and response serialization. The major components are:
IOMixin: A mixin class that adds I/O capabilities to Pydantic models. It provides:multipart_fields: Automatically detects which fields require multipart form encoding (file/image fields).mime_type(): Determines the correct MIME type based on the model schema (JSON, text, multipart, file types, etc.).openapi_components(): Generates OpenAPI schema components for documentation.from_inputs(): Constructs an IO descriptor from positional and keyword arguments, supporting*argsand**kwargs.from_http_request(): Parses an HTTP request into a typed model using a pluggableSerde.to_http_response(): Converts model instances to HTTP responses, with support for streaming (async generators and generators), file responses, image responses, and standard JSON/text responses.
IODescriptor: The primary model class (extendsIOMixinandBaseModel). Provides two factory class methods:from_input(func): Inspects a function's signature to create a typed input descriptor. Handles positional-only, keyword,*args, and**kwargsparameters. SupportsContentTypeannotations for custom media types.from_output(func): Inspects a function's return annotation to create a typed output descriptor. Handles iterator types for streaming andContentTypeannotations.
IORootModel: A generic wrapper for single-value I/O types (analogous to Pydantic'sRootModel). Used when an API endpoint accepts or returns a single value rather than a structured object. Overridesmodel_dump,model_validate, andmodel_json_schemato unwrap therootfield.
IterableResponse: A custom StarletteResponsesubclass that sends chunked HTTP responses from a synchronous iterable.
ensure_io_descriptor(typ_): A utility function that wraps arbitrary types intoIODescriptorsubclasses. If the type is already a PydanticBaseModelwithIOMixin, it returns it as-is; otherwise it wraps it in anIORootModel.
Usage
This module is used internally by the BentoML SDK when decorating service methods with @bentoml.api. The framework calls IODescriptor.from_input() and IODescriptor.from_output() to automatically infer API schemas from function signatures. Users typically interact with this system indirectly through type annotations on their service methods.
Code Reference
Source Location
- Repository: Bentoml_BentoML
- File: src/_bentoml_sdk/io_models.py
- Lines: 1-520
Signature
class IOMixin:
multipart_fields: ClassVar[t.List[str]]
media_type: ClassVar[t.Optional[str]] = None
@classmethod
def from_inputs(cls, *args: t.Any, **kwargs: t.Any) -> IODescriptor: ...
@classmethod
async def from_http_request(cls, request: Request, serde: Serde) -> IODescriptor: ...
@classmethod
async def to_http_response(cls, obj: t.Any, serde: Serde) -> Response: ...
class IODescriptor(IOMixin, BaseModel):
@classmethod
def from_input(cls, func: t.Callable[..., t.Any], *, skip_self: bool = False, skip_names: t.Container[str] = ()) -> type[IODescriptor]: ...
@classmethod
def from_output(cls, func: t.Callable[..., t.Any]) -> type[IODescriptor]: ...
class IORootModel(IODescriptor, t.Generic[RootModelRootType]):
root: RootModelRootType
def ensure_io_descriptor(typ_: type, root_default: t.Any = inspect.Signature.empty) -> type[IODescriptor]: ...
Import
from _bentoml_sdk.io_models import IODescriptor
from _bentoml_sdk.io_models import IORootModel
from _bentoml_sdk.io_models import ensure_io_descriptor
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| func | Callable | Yes | The service function whose signature is inspected to create I/O descriptors |
| skip_self | bool | No | Whether to skip the first parameter (for bound methods) |
| skip_names | Container[str] | No | Parameter names to skip (e.g., context parameters) |
| request | starlette.Request | Yes (for from_http_request) | The incoming HTTP request to parse |
| serde | Serde | Yes (for HTTP methods) | Serialization/deserialization strategy |
Outputs
| Name | Type | Description |
|---|---|---|
| IODescriptor subclass | type[IODescriptor] | A dynamically created Pydantic model class representing the I/O schema |
| Response | starlette.Response | An HTTP response (JSON, file, streaming, or text) for output serialization |
Usage Examples
import bentoml
from _bentoml_sdk.io_models import IODescriptor
# IODescriptor is typically used indirectly via @bentoml.api
@bentoml.service
class MyService:
@bentoml.api
def predict(self, input_data: dict) -> dict:
# IODescriptor.from_input and from_output are called
# automatically by the framework
return {"result": "prediction"}
# Direct usage for advanced scenarios
input_desc = IODescriptor.from_input(my_function)
output_desc = IODescriptor.from_output(my_function)