
From Fine-Tune to API: Packaging Any ML Model as a Production Service with BentoML
Chris Harper
3 min read
Jul 24, 2026 · 12:02 UTC
TL;DR: BentoML wraps any trained model — HuggingFace, PyTorch, sklearn, even a QLoRA fine-tune from Unsloth — in a production-ready REST/gRPC API with adaptive batching, health checks, Docker export, and cloud deploy, all from a single Python decorator.
What you'll be able to do after this:
- Package any fine-tuned model as a FastAPI-backed REST service with one
@bentoml.servicedecorator - Build and containerize a Bento into a portable Docker image with
bentoml build+bentoml containerize— no Dockerfile required - Deploy to BentoCloud or any Docker host with adaptive batching,
/metrics(Prometheus), and OpenTelemetry tracing already wired in
Resource: How to Deploy ML Models in Production with BentoML by Valerio Velardo (The Sound of AI), YouTube — covers the complete lifecycle: model saving, service definition, local dev server, Docker export, and cloud deployment options. Official docs: BentoML quickstart.
Why BentoML bridges the gap after fine-tuning
You trained a model with Unsloth, evaluated it with lm-eval, and it performs well. Now what? Dropping it into a raw FastAPI endpoint works for demos but skips everything production needs: batching, health checks, dependency pinning, metrics, containerization. BentoML handles all of it with minimal extra code — the interface you define is almost identical to a plain Python class.
The three-step pattern
# Step 1: Save your model (after training with HuggingFace/TRL/Unsloth)
import bentoml
from transformers import pipeline
bentoml.transformers.save_model(
"my-fine-tuned-mistral",
pipeline("text-generation", model=model, tokenizer=tokenizer),
)
# Step 2: Define a Service (service.py)
import bentoml
@bentoml.service(
resources={"gpu": 1},
traffic={"timeout": 30},
)
class MistralService:
model_ref = bentoml.models.get("my-fine-tuned-mistral:latest")
def __init__(self):
self.pipeline = self.model_ref.load_model()
@bentoml.api
def generate(self, prompt: str) -> str:
return self.pipeline(prompt, max_new_tokens=256)[0]["generated_text"]
# Step 3: Serve, build, containerize
bentoml serve service:MistralService --reload # dev server at :3000
bentoml build # creates a Bento artifact
bentoml containerize my-fine-tuned-mistral:latest # outputs a Docker image
docker run -p 3000:3000 my-fine-tuned-mistral:latest
What you get for free
Adaptive batching groups concurrent requests into a single forward pass — critical for GPU throughput under load. You enable it with one decorator argument (@bentoml.api(batchable=True)). Health checks (/healthz, /readyz, /livez) are built in. The Docker image pins your exact Python dependencies, includes the model weights, and passes a docker inspect right away.
Connecting to vLLM
BentoML also ships a vLLM runner example that wraps vLLM's async engine behind a BentoML service — giving you the packaging, metrics, and deploy tooling of BentoML with vLLM's PagedAttention throughput underneath.
Sources: How to Deploy ML Models in Production with BentoML — The Sound of AI (YouTube) · BentoML Hello World quickstart · BentoML + vLLM integration · BentoML GitHub