BentoML 输入输出类型(IO Types)完全指南:定义 Service API 数据契约
发布时间:2026/9/25 2:20:15来源:尧图网络
模型推理服务人工智能后端大模型MLOpsLLMOps【免费下载链接】BentoMLThe easiest way to serve AI apps and models - Build Model Inference APIs, Job queues, LLM apps, Multi-model pipelines, and more!项目地址https://gitcode.com/gh_mirrors/be/BentoML点击查看免费下载本文围绕 BentoML 官方文档 iotypes.rst 展开系统讲解如何通过 Python 类型注解为 BentoML Service 的 API 定义输入输出IO类型。你将掌握标准 Python 类型、Pydantic 模型、张量numpy/torch/tensorflow、Pandas DataFrame、PIL 图像与pathlib.Path文件类型、根输入Root input以及复合类型的完整用法并了解 BentoML 内置的bentoml.validators校验器与底层实现原理从而直接写出可被 BentoML 客户端与 UI 正确消费的 API 数据契约。概述为什么 IO 类型如此重要在 BentoML 中创建 Service 时必须为 Service 的每个 API 明确指定输入和输出IO类型。这些类型决定了 Service API 的逻辑形态引导数据在 Service 内部和外部的流动方式。BentoML 支持 Python 常见的数据类型、Pydantic 类型以及机器学习ML工作流专属的类型这使得 BentoML Service 能够无缝对接不同的数据源和 ML 框架。支持的类型总体分为四类标准 Python 类型str、int、float、boolean、list、dict等基础类型Pydantic 字段类型借助 Pydantic 提供结构化、可校验的复杂数据模式ML 专属类型numpy.ndarray、torch.Tensor、tensorflow.Tensor张量数据、pandas.DataFrame表格数据、PIL.Image.Image图像数据、pathlib.Path文件路径根输入Root input允许 API 只接收一个仅按位置传递positional-only的参数请求体中无需任何 key。你通过 Python 类型注解来声明每个 API 端点的预期输入输出类型。这不仅能按声明的 schema 校验数据还能增强代码的可读性。类型注解在生成 API、BentoML 客户端和 UI 组件时扮演关键角色确保与 Service 的交互一致且可预期。此外还可以用pydantic.Field为参数补充默认值与描述等附加信息提升 API 的可用性并提供基础文档。从实现层面看bentoml.api装饰器会为每个 API 方法构造APIMethod对象其input_spec与output_spec均由 decorators.py 中的api()包装并通过IODescriptor.from_input/from_output从函数签名中动态推断出来见 io_models.py。也就是说你在方法签名里写下的每一个注解都会被反射式地转换成请求解析与响应序列化的真实 schema。定义 API Schema各类类型实战标准 Python 类型字符串、整数、浮点数、布尔值、列表和字典等标准类型最常用于简单数据结构可以轻松集成到 Service 中。以下示例展示了带默认值与描述的标准类型参数from pydantic import Field import bentoml bentoml.service class LanguageModel: bentoml.api def generate( self, prompt: str Field(descriptionThe prompt text), temperature: float Field(default0.0, descriptionA sampling temperature between 0 and 2), max_tokens: int Field(default1000, descriptionmax tokens to use), ) - Generator[str, None, None]: # Implementation of the language generation model ...示例要点使用str、float、int等标准类型注解声明每个参数的期望类型返回类型是一个Generator表示响应可以流式输出。BentoML 检测到生成器函数后会将output_spec的media_type自动设置为text/event-stream见 method.py并在IO层通过StreamingResponse逐块发送数据见 io_models.pypydantic.Field用于设置默认值并为参数提供描述这些描述最终会进入 OpenAPI schema成为 API 文档的一部分。示例值与可空输入可以为接受示例值或可空字段的 API 定义输入。设置示例值使用pydantic.Field的examples参数from pydantic import Field import bentoml bentoml.service class IrisClassifier: bentoml.api def classify(self, input: np.ndarray Field(examples[[0.1, 0.4, 0.2, 1.0]]) - np.ndarray: ...处理可空输入则使用Optionalfrom pydantic import Field from typing import Optional import bentoml bentoml.service class LanguageModel: bentoml.api def generate( self, prompt: int Field(descriptionThe prompt text), temperature: Optional[float] Field(defaultNone, descriptionA sampling temperature between 0 and 2), max_tokens: Optional[float] Field(defaultNone, descriptionmax tokens to use), ) - Generator[str, None, None]: ...在LanguageModel中temperature和max_tokens被标记为Optional意味着它们可以是None。使用Optional类型时必须提供默认值此处为defaultNone。通用的 Union 类型目前不受支持——这一点在源码中有明确印证IOMixin.__pydantic_init_subclass__只放行X | None这种恰好两个成员且其一为None的联合类型其他 Union 会直接抛出TypeError见 io_models.py。Pydantic 模型Pydantic 模型支持更结构化、带校验的数据特别适合需要严格校验复杂数据结构的场景。以下示例定义了一个广告文案生成服务的结构化输入from pydantic import BaseModel, Field import bentoml # Define a Pydantic model for structured data input class AdsGenerationParams(BaseModel): prompt: str Field(descriptionThe prompt text) industry: str Field(descriptionThe industry the company belongs to) target_audience: str Field(descriptionTarget audience for the advertisement) temperature: float Field(default0.0, descriptionA sampling temperature between 0 and 2) bentoml.service class AdsWriter: bentoml.api def generate(self, params: AdsGenerationParams) - str: # Implementation logic ...AdsGenerationParams定义了输入数据的结构与校验规则每个字段都标注了类型可以包含默认值和描述。Pydantic 会自动按该 schema 校验传入数据若数据不符合 schema会在方法执行前抛出错误。你还可以把 Pydantic 模型直接作为 Service API 的顶层输入top level无需将 payload 包装在某个 key 之下from pydantic import BaseModel, Field import typing as t import bentoml class AdsGenerationParams(BaseModel): prompt: str Field(descriptionThe prompt text) industry: str Field(descriptionThe industry the company belongs to) target_audience: str Field(descriptionTarget audience for the advertisement) temperature: float Field(default0.0, descriptionA sampling temperature between 0 and 2) bentoml.service class AdsWriter: bentoml.api(input_specAdsGenerationParams) def generate(self, **params: t.Any) - str: # Access parameters from the request prompt params[prompt] industry params[industry] target_audience params[target_audience] temperature params[temperature] # Use the parameters in your Service logic ...此时请求中经过校验与解析的所有字段会以关键字参数的形式进入params字典可以直接按AdsGenerationParams中定义的字段名作为 key 访问。从源码看**params会被IODescriptor.from_input识别为VAR_KEYWORD参数并映射为内部kwargs字段见 io_models.py而显式传入input_spec时method.py 中的_io_descriptor_converter会直接复用该模型作为输入描述符。注意Pydantic 的BaseModel只支持 Python 内置类型作为字段类型。需要支持numpy.ndarray、pandas.DataFrame、torch.Tensor等类型时应改用bentoml.IODescriptorimport bentoml class MyInputParams(bentoml.IODescriptor): data: np.ndarray[tuple[int], np.dtype[np.float16]]bentoml.IODescriptor本质上是IOMixin BaseModel的组合见 io_models.py它通过__get_pydantic_core_schema__在 Pydantic 校验链路中注入 BentoML 对张量、DataFrame、图像、文件等类型的自定义编解码逻辑。文件Files使用pathlib.Path处理文件输入和输出适用于处理音频、图像、文档等文件型数据的 Service。下面是一个接受Path对象作为输入指向一个音频文件的简单示例from pathlib import Path import bentoml bentoml.service class WhisperX: bentoml.api def to_text(self, audio: Path) - str: # Implementation for converting audio files to text ...要限制文件类型例如只接受音频可以使用ContentType校验器配合Annotated类型。例如让 API 方法只接受 MP3 音频文件from pathlib import Path from bentoml.validators import ContentType from typing import Annotated # Python 3.9 or above from typing_extensions import Annotated # Older than 3.9 import bentoml bentoml.service class WhisperX: bentoml.api def to_text(self, audio: Annotated[Path, ContentType(audio/mp3)]) - str: ...若要以路径形式输出文件可以使用context.temp_dir为每个请求提供独立临时目录并存放输出文件。bentoml.Context在内部通过request_temp_dir()为每个请求从TempfilePool获取唯一的临时目录并在请求结束时自动回收见 context.py 与 context.pyfrom pathlib import Path import bentoml bentoml.service class Vits: bentoml.api def to_speech(self, text: str, context: bentoml.Context) - Path: # Example text-to-speech synthesis implementation audio_bytes self.tts.synthesize(text) # Writing the audio bytes to a file in the temporary directory with open(Path(context.temp_dir) / output.mp3, wb) as f: f.write(audio_bytes) # Returning the path to the generated audio file directly return Path(context.temp_dir) / output.mp3当方法返回指向生成文件的Path对象时BentoML 会将该文件序列化并包含在响应中发送给客户端。底层实现中IO.to_http_response会对Path类型输出自动使用FileResponse并根据 MIME 类型决定是内联展示如image/*用inline还是作为附件下载见 io_models.py。更多文件处理的实用示例向文件追加字符串from pathlib import Path from bentoml.validators import ContentType from typing import Annotated # Python 3.9 or above from typing_extensions import Annotated # Older than 3.9 import bentoml bentoml.service class AppendStringToFile: bentoml.api() def append_string_to_eof( self, context: bentoml.Context, txt_file: Annotated[Path, ContentType(text/plain)], input_string: str, ) - Annotated[Path, ContentType(text/plain)]: with open(txt_file, a) as file: file.write(input_string) return txt_file把 PDF 的第一页转换为图像from bentoml.validators import ContentType from typing import Annotated # Python 3.9 or above from typing_extensions import Annotated # Older than 3.9 from PIL import Image as im import bentoml bentoml.service class PDFtoImage: bentoml.api def pdf_first_page_as_image( self, pdf: Annotated[Path, ContentType(application/pdf)], ) - Image: from pdf2image import convert_from_path pages convert_from_path(pdf) return pages[0].resize(pages[0].size, im.ANTIALIAS)加速音频文件from pathlib import Path from bentoml.validators import ContentType from typing import Annotated # Python 3.9 or above from typing_extensions import Annotated # Older than 3.9 import bentoml bentoml.service class AudioSpeedUp: bentoml.api def speed_up_audio( self, context: bentoml.Context, audio: Annotated[Path, ContentType(audio/mpeg)], velocity: float, ) - Annotated[Path, ContentType(audio/mp3)]: import os from pydub import AudioSegment output_path os.path.join(context.temp_dir, output.mp3) sound AudioSegment.from_file(audio) sound sound.speedup(velocity) sound.export(output_path, formatmp3) return Path(output_path)如果不想把临时文件落盘可以直接返回bytes而不是pathlib.Path并用ContentType正确标注类型。这对于实时生成数据的 Service 更加高效。需要注意的是ContentType校验器在接收文件时会校验实际上传的媒体类型是否与声明匹配使用fnmatch通配匹配不匹配会抛出ValueError见 validators.py。张量TensorsBentoML 支持numpy.ndarray、torch.Tensor、tensorflow.Tensor等多种张量类型。还可以使用bentoml.Shape与bentoml.DType校验器分别对应bentoml.validators.Shape、bentoml.validators.DType来强制张量输入的具体形状与数据类型import torch from bentoml.validators import Shape, DType from typing import Annotated # Python 3.9 or above from typing_extensions import Annotated # Older than 3.9 from pydantic import Field import bentoml bentoml.service class IrisClassifier: bentoml.api def classify( self, input: Annotated[torch.Tensor, Shape((1, 4)), DType(float32)] Field(descriptionA 1x4 tensor with float32 dtype) ) - np.ndarray: ...示例解读classify方法期望torch.Tensor输入Annotated结合Shape与DType校验器指定期望张量的形状为(1, 4)、数据类型为float32pydantic.Field为输入参数提供附加描述提升 API 可读性。张量校验的底层逻辑在TensorSchema中实现JSON 模式下张量会被序列化为嵌套数组校验时会按formatnumpy-array/tf-tensor/torch-tensor分派到对应框架构造张量并执行reshape与 dtype 转换序列化时若设备是 GPU 会自动cpu()后再转 numpy见 validators.py。表格数据TabularPandas DataFrame 是机器学习中最常用的表格数据处理结构。BentoML 支持 Pandas DataFrame 输入并允许用校验器注解来确保数据符合预期结构from typing import Annotated # Python 3.9 or above from typing_extensions import Annotated # Older than 3.9 import pandas as pd from bentoml.validators import DataframeSchema import bentoml bentoml.service class IrisClassifier: bentoml.api def classify( self, input: Annotated[pd.DataFrame, DataframeSchema(orientrecords, columns[petal_length, petal_width]) ) - int: # Classification logic using the input DataFrame ...示例解读classify方法接受 Pandas DataFrame 作为输入Annotated结合DataframeSchema指定 DataFrame 的期望方向和列orientrecords表示 DataFrame 期望以记录导向record-oriented格式传入columns[petal_length, petal_width]指定 DataFrame 的期望列。DataframeSchema校验器支持以下两种方向orient决定 API 接收到的数据结构records每一行表示为一个字典key 为列名columns数据按列组织字典的每个 key 代表一列对应值为该列的取值列表。在源码实现中records方向使用df.to_dict(orientrecords)序列化、columns方向使用df.to_dict(orientlist)校验侧则通过pd.DataFrame(obj, columnsself.columns)重构 DataFrame见 validators.py。图像ImagesBentoML Service 可以通过PIL.Image.Image和pathlib.Path处理图像。方式一直接传递PIL.Image.Image对象from PIL import Image as im from PIL.Image import Image import bentoml bentoml.service class ImageResize: bentoml.api def generate(self, image: Image, height: int 64, width: int 64) - Image: size height, width return image.resize(size, im.LANCZOS)方式二使用pathlib.PathContentType处理图像文件from pathlib import Path from typing import Annotated # Python 3.9 or above from typing_extensions import Annotated # Older than 3.9 from bentoml.validators import ContentType import bentoml bentoml.service class MnistPredictor: bentoml.api def infer(self, input: Annotated[Path, ContentType(image/jpeg)]) - int: ...PIL 图像的编解码由PILImageEncoder实现接收bytes、UploadFile、文件对象或图像对象统一用PILImage.open解码输出时保存为图片原始格式缺省 PNG并返回二进制见 validators.py。根输入Root input根输入是一种特殊的输入类型API 请求体中不需要 key输入数据本身直接作为请求体传入。这对处理图像、音频或原始文本等二进制数据特别有用。定义根输入使用 Python 的仅限位置参数positional-only arguments即函数签名中/之前的参数重要限制最多只能有一个仅限位置参数/之前的参数一旦指定了仅限位置参数除bentoml.Context之外不允许再有其他参数。示例实现from PIL import Image import bentoml bentoml.service class ImageProcessor: bentoml.api def upload_image(self, image: Image.Image, /) - int: # Process the image and return a result ...在这个示例中upload_image的image参数是仅限位置参数意味着调用时必须不带 key 传递。客户端必须把图像数据直接放在 HTTP 请求体中不带任何 JSON 包装。使用curl调用示例curl -XPOST -sL http://localhost:3000/upload_image --data-binarymyimage.png对应的 HTTP 请求如下POST /upload_image HTTP/1.1 Content-Type: image/png image binary使用 BentoML 客户端调用带根输入的 API 时必须用位置参数且不能指定参数名client bentoml.SyncClient(http://localhost:3000) image_path Path(demo.png) result client.upload_image(image_path) # CORRECT result client.upload_image(imageimage_path) # WRONG源码佐证IODescriptor.from_input在检测到POSITIONAL_ONLY参数时会将其包装为IORootModel并打上__root_input__标记见 io_models.py单元测试 test_decorators.py 同时验证了根输入的正确定义以及多个仅限位置参数或仅限位置参数后还有其他参数均会抛出TypeError的非法用法。复合类型Compound高级场景中单一数据类型往往不够用复杂场景可能需要组合多种数据类型。例如同时处理图像与 JSON 输入from pydantic import BaseModel, Field from PIL import Image as PILImage import bentoml class ImageMetadata(BaseModel): description: str Field(descriptionDescription of the image) timestamp: str Field(descriptionTimestamp of when the image was captured) bentoml.service class ImageProcessingService: bentoml.api def process_image(self, image: PILImage, metadata: ImageMetadata) - dict: # Implementation for processing the image and metadata ...示例中PILImage处理图像数据而 Pydantic 模型ImageMetadata处理 JSON 输入。BentoML 在检测到多个字段中存在文件类型时会将这些 API 的请求媒体类型设为multipart/form-data非文件字段则以application/json编码传输见 io_models.py 与 method.py。BentoML 还支持复杂类型的列表输入与输出例如图像和文件路径的列表。以下示例同时处理一批图像和一批文件路径from PIL import Image as PILImage from pathlib import Path from typing import List, Dict import bentoml bentoml.service class BatchImageService: bentoml.api def enhance_images(self, images: List[PILImage]) - PILImage: # Process images and return a single image ... bentoml.api def process_files(self, files: List[Path]) - List[Dict]: # Process files and return a list of dictionaries ...当前限制BentoML 目前不支持输出包含多个原始二进制数据也不支持将原始二进制数据如图像或文件与普通字典数据直接组合输出。数据校验Validate data对输入数据做正确校验对 BentoML Service 至关重要它能确保被处理的数据格式符合预期、达到必要的质量标准。BentoML 提供了一套简单的校验机制并且默认支持 Pydantic 提供的全部校验特性可对数据的结构、类型和约束进行全面检查。以下示例使用annotated_types的约束注解from typing import Annotated # Python 3.9 or above from typing_extensions import Annotated # older than 3.9 from annotated_types import Ge, Lt, Gt, MultipleOf, MaxLen import bentoml bentoml.service class LLMPredictor: bentoml.api def predict( self, prompt: Annotated[str, MaxLen(1000)], temperature: Annotated[float, Ge(0), Lt(2)], max_tokens: Annotated[int, Gt(0), MultipleOf(100)] ) - int: ...示例中的校验器确保prompt字符串长度不超过 1000 个字符MaxLen(1000)temperature取值介于 0 和 2 之间Ge(0)且Lt(2)max_tokens是大于 0 且为 100 的倍数Gt(0)且MultipleOf(100)。常用 ML 类型的校验BentoML 为张量、DataFrame 等常见 ML 数据类型提供校验能力确保喂给模型的数据完整可靠。上文各节已给出这些数据类型的校验示例。下表汇总了 BentoML 额外支持的、专门面向 ML 场景的输入输出类型以及每种类型可用的注解用于进一步细化与校验数据类型名称说明允许的注解numpy.ndarray用于数值数据的多维数组常用于 ML 任务bentoml.validators.Shape、bentoml.validators.DTypetorch.TensorPyTorch 中表示张量数据的张量类型bentoml.validators.Shape、bentoml.validators.DTypetensorflow.TensorTensorFlow 中表示张量数据的张量类型bentoml.validators.Shape、bentoml.validators.DTypepandas.DataFrame表格数据结构常用于数据分析bentoml.validators.DataframeSchemaPIL.Image.ImagePIL 库的图像数据类型用于图像处理bentoml.validators.ContentTypepathlib.Path文件路径用于文件输入与输出bentoml.validators.ContentType此外BentoML 还支持 Pydantic 的所有注解类型进行校验。bentoml.validators模块的导出定义可在 validators.py 中查看其核心实现ContentType、Shape、DType、DataframeSchema、TensorSchema、FileSchema、PILImageEncoder位于 src/_bentoml_sdk/validators.py。附录输入/输出类型速查表输入类型类型输入注解HTTP 内容类型HTTP 请求体示例JSONpredict(self, input1: str, input2: int)application/jsoncurl -XPOST -d { input1: input_value, input2: 2 }张量predict(self, input1: torch.Tensor)、predict(self, input1: numpy.ndarray)、predict(self, input1: tensorflow.Tensor)application/jsoncurl -XPOST -d { input1: [[1, 1, 1, 1], [2, 2, 2, 2]] }表格数据predict(self, input1: pandas.DataFrame)application/jsoncurl -XPOST -d { input1: [{col1: 1, col2: 2}, {col1: 1, col2: 2}] }图像predict(self, input1: str, input2: PIL.Image.Image)multipart/form-data路径curl -XPOST -F input1enter_your_prompt_here -F input2image/path/to/image.jpgURLcurl -XPOST -F input1enter_your_prompt_here -F input2http://domain/path/to/image.jpg文件predict(self, input1: str, input2: pathlib.Path)multipart/form-data路径curl -XPOST -F input1enter_your_prompt_here -F input2image/path/to/image.jpgURLcurl -XPOST -F input1enter_your_prompt_here -F input2http://domain/path/to/file.mp3输出类型类型输出注解HTTP 内容类型HTTP 响应体示例纯文本- str、- bytestext/plainstringJSON- int、- float、- dict、- listapplication/json3、1.1、{}、[]张量- torch.Tensor、- numpy.ndarray、- tensorflow.Tensorapplication/json[[1, 1, 1, 1], [2, 2, 2, 2]]表格数据- pandas.DataFrameapplication/json[{ col1: 1, col2: 2 }, { col1: 1, col2: 2 }]图像- PIL.Image.Imageimage/auto MIME type二进制 body文件- pathlib.Pathauto MIME type二进制 body自定义文件- Annotated[pathlib.Path, ContentType(custom-type)]custom-type二进制 body这些 MIME 类型的自动推导逻辑可在IOMixin.mime_type()中找到见 io_models.py根输入下字符串类型默认text/plainContentType声明的文件类型返回其声明值图像/音频/视频分别映射到image/*、audio/*、video/*其余文件默认application/octet-stream。延伸阅读BentoML Service 定义了解bentoml.service与 API 方法组织的完整机制BentoML 客户端掌握如何通过同步/异步客户端正确调用带各类 IO 类型的 APISDK 参考查看bentoml.api、bentoml.IODescriptor与bentoml.validators的完整 API 说明IO 校验器单元测试包含根输入、张量注解、DataFrame 注解的实证用例HTTP Server 端到端测试覆盖 multipart 图像与文件输入的真实请求场景。赞分享模型推理服务人工智能后端大模型MLOpsLLMOps【免费下载链接】BentoMLThe easiest way to serve AI apps and models - Build Model Inference APIs, Job queues, LLM apps, Multi-model pipelines, and more!项目地址https://gitcode.com/gh_mirrors/be/BentoML点击查看免费下载相关推荐AWX 自定义凭据类型Custom Credential Types完全指南inputs 输入定义与 injectors 注入实战AWX 自定义凭据类型Custom Credential Types完全指南inputs 输入定义与 injectors 注入实战 本文围绕 AWX 的后端运维任务调度Zoo Text-to-CAD UI用自然语言设计机械零件的革命性工具Zoo Text to CAD UI用自然语言设计机械零件的革命性工具 还在为复杂的CAD软件界面而困扰吗想用简单的文字描述就能生成专业的机械设计图纸吗Z前端AI 应用3D渲染Isaac Lab IO Descriptors 完全指南策略输入输出描述、导出与自定义接入Isaac Lab IO Descriptors 完全指南策略输入输出描述、导出与自定义接入 本教程面向在 Isaac Lab 中使用 ManagerBase人工智能强化学习机器人具身智能深度学习上一篇Robotiq 开源项目教程下一篇视频转码API指南深入浅出video-dev/video-transcoding-api创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网