Abstract / Overview

Deploying AI models requires scalability and user accessibility. Ray Serve provides distributed serving for machine learning models, while Gradio creates simple, interactive web UIs. When combined, they enable scalable backend deployments with intuitive frontends. This article explains how to integrate Ray Serve and Gradio, includes runnable code, and demonstrates a full real-world example of deploying an image classifier.

ChatGPT Image Sep 26, 2025, 07_35_10 PM

Conceptual Background

Step-by-Step Walkthrough

1. Install Dependencies

pip install "ray[serve]" gradio fastapi torch torchvision

2. Start Ray Serve

from ray import serve
serve.start()

3. Create a Deployment with PyTorch Image Classifier

import torch
import torchvision.models as models
import torchvision.transforms as transforms
from PIL import Image
import requests
from io import BytesIO

# Preprocessing pipeline
transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225]),
])

# Load pretrained model
model = models.resnet18(pretrained=True)
model.eval()

# Labels
LABELS_URL = "https://raw.githubusercontent.com/pytorch/hub/master/imagenet_classes.txt"
labels = requests.get(LABELS_URL).text.splitlines()

@serve.deployment
class ImageClassifier:
    def __call__(self, image: bytes) -> str:
        img = Image.open(BytesIO(image)).convert("RGB")
        tensor = transform(img).unsqueeze(0)
        with torch.no_grad():
            outputs = model(tensor)
        _, predicted = outputs.max(1)
        return labels[predicted.item()]

ImageClassifier.deploy()

This deployment loads a pretrained ResNet-18 model and classifies input images.

4. Expose Deployment via FastAPI

from fastapi import FastAPI, UploadFile

app = FastAPI()

@serve.deployment
@serve.ingress(app)
class ImageAPI:
    @app.post("/classify")
    async def classify(self, file: UploadFile):
        image_bytes = await file.read()
        classifier = await ImageClassifier.get_handle().remote()
        result = await classifier.remote(image_bytes)
        return {"prediction": result}

ImageAPI.deploy()

Now, you can send POST requests with an image to http://127.0.0.1:8000/classify.

5. Add Gradio Interface

import gradio as gr
import requests

def classify_image(image):
    response = requests.post(
        "http://127.0.0.1:8000/classify", 
        files={"file": ("image.png", image, "image/png")}
    )
    return response.json()["prediction"]

gr.Interface(
    fn=classify_image,
    inputs="image",
    outputs="text",
    title="Ray Serve + Gradio Image Classifier"
).launch()

Opening the Gradio interface lets you upload an image and view the prediction in real time.

Workflow Diagram: Ray Serve + Gradio

ray-serve-gradio-image-classifier

Use Cases / Scenarios

Limitations / Considerations

Fixes and Troubleshooting

FAQs

Q1. Can I connect multiple models with one Gradio app?
Yes, by deploying multiple Ray Serve endpoints and wiring them into one Gradio interface.

Q2. How do I scale deployments?
Ray Serve supports automatic scaling across CPUs/GPUs and nodes in a cluster.

Q3. Can this run in the cloud?
Yes, Ray Serve can run on AWS, GCP, Azure, and Kubernetes.

Q4. Is Gradio secure enough for production?
Not by default. Use authentication, API gateways, or reverse proxies.

Conclusion

Ray Serve and Gradio form a powerful combination: Ray ensures scalable backend deployment, while Gradio provides user-friendly UIs. Together, they allow developers to serve AI models efficiently and make them accessible to end users. For production, Gradio should complement Ray Serve APIs as a demonstration layer, while Ray handles distributed workloads.

References