Creating APIs with FastAPI for Model Serving

Tutorial 2 of 5

1. Introduction

Goal of the Tutorial

This tutorial aims to guide you on how to create APIs using FastAPI for serving machine learning models.

Learning Outcomes

By the end of this tutorial, you will be able to:
- Understand the basics of FastAPI.
- Understand how to serve machine learning models using APIs.
- Create a FastAPI application that serves a machine learning model.

Prerequisites

  • Python programming knowledge.
  • Basic knowledge of Machine Learning and its models.
  • Python environment setup with FastAPI and Uvicorn installed.

2. Step-by-Step Guide

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.

Setting up FastAPI

First, we need to install FastAPI and Uvicorn, an ASGI server, using pip:

pip install fastapi uvicorn

Creating an API endpoint

Next, we create an API endpoint. An API endpoint is a point at which an API – the code that allows two software programs to communicate with each other – interacts with the software program.

Here's a simple example:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

In the above example, @app.get("/") means that the function underneath will answer HTTP get requests (a common request to retrieve information) that go to the URL /.

Serving a Machine Learning Model

Let's create a simple linear regression model using sklearn, train it on some data, and then serve it using FastAPI.

from fastapi import FastAPI
from sklearn.linear_model import LinearRegression
import numpy as np

app = FastAPI()

# Train a model
model = LinearRegression()
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
y = np.dot(X, np.array([1, 2])) + 3
model.fit(X, y)

@app.get("/predict/{data}")
def predict(data: str):
    # Convert string of numbers to list of numbers
    data = [float(num) for num in data.split(",")]
    prediction = model.predict([data])
    return {"prediction": prediction[0]}

In the code above, we create a simple linear regression model and serve it using FastAPI. The function predict takes a string of comma-separated numbers and returns a prediction based on the trained model.

3. Code Examples

Here are some practical examples:

Example 1: Basic FastAPI Application

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

Example 2: FastAPI Application with Path Parameters

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id}

Example 3: FastAPI Application Serving a Machine Learning Model

from fastapi import FastAPI
from sklearn.linear_model import LinearRegression
import numpy as np

app = FastAPI()

# Train a model
model = LinearRegression()
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
y = np.dot(X, np.array([1, 2])) + 3
model.fit(X, y)

@app.get("/predict/{data}")
def predict(data: str):
    # Convert string of numbers to list of numbers
    data = [float(num) for num in data.split(",")]
    prediction = model.predict([data])
    return {"prediction": prediction[0]}

4. Summary

In this tutorial, you learned how to create APIs using FastAPI and serve machine learning models. You also learned how to create FastAPI applications and use path parameters in FastAPI applications.

5. Practice Exercises

  1. Create a FastAPI application that serves a different machine learning model. This could be a model from sklearn or a model you've created and trained yourself.

  2. Create a FastAPI application with more complex routing. Use FastAPI's routing features to create an application with several different endpoints and HTTP methods.

Solutions

  1. This solution will vary depending on the model you chose to serve. However, the code will be similar to the code in the 'Serving a Machine Learning Model' section.

  2. Here's a simple solution for a more complex FastAPI application:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id}

@app.post("/items/")
def create_item(name: str, price: float):
    return {"name": name, "price": price}

In this solution, we've added a post method that can be used to create new items.