How to Build Machine Learning Applications with FastAPI

A tutorial on building FastAPI for Machine Learning model usability

Josephine Amponsah
7 min readJun 17, 2023

Introduction

For Data Scientists, machine learning or statistical models are only useful when applications or users can interact with them. Hence, serving models via APIs to applications as part of features or features themselves to provide value to end users.

FastAPI is a python micro-framework used for building APIs. Compared to other frameworks, it’s fast and has embedded features and dependencies that makes it easier to work with.

In this article, we will walk through the various elements of FastAPI, it’s dependencies, and build a machine learning application for practical understanding of its implementation.

Prerequisites

  • Knowledge of what APIs are
  • Knowledge of modules and functions

Table of Content

  1. Elements of FastAPI
  2. Data Validation
  3. Modules / Functionalities
  4. Code Implementation
  5. Testing with Postman

Elements of FastAPI

  • HTTP request methods
  • Path operation
    The path operation function, is written as ‘@app.get(‘/’)’, refers to the function that handles a specific HTTP request to a particular route or endpoint defined in your API.
    ‘@app.get’ is a decorator of the fastAPI, with ‘app’ as the instance of FastAPI and ‘get’ as the HTTP method to be used for the endpoint. The arguments in bracket succeeding the HTTP method, are path names, and other optional arguments like response models, classes, depending on the features of your application.
  • Path Operation/Endpoint function
    This refers to the function succeeding each path operation function. It is responsible for processing the incoming requests, performing any necessary operations, and generating the appropriate responses.
  • Query paramater
    This refers to the values passed to the endpoint function inside the function. They are passed to endpoint functions as additional information of an HTTP request and typically used to modify the data in an endpoint.
  • Request body
    The body is the part of the HTTP request that contains raw data, representing documents, files, or form submissions. In fastAPI, it is usually encoded in json and can also be defined with data models using pydantic and typing.
  • HTTP responses
    By default, fastAPI converts whatever you return from your endpoint function to json. It can however also be structured and validated with Pydantic classes, just like data in request bodies.
  • Automated documentation
    With Swagger UI, fastAPI renders an automatic documentation of your API endpoints. It can be viewed by adding “/docs” to the url of your API, this can be localhost url during development or a live url.
  • Dependencies
    FastAPI incorporates Python’s type annotation feature and is built on top of Starlette, a Python’s ASGI toolkit. It also uses Pydantic as an essential building block for validating data models, and is commonly run on an asynchronous server; uvicorn.

To set up for your fastAPI application, you will need to install the following libraries.

pip install uvicorn
pip install httpie
pip install httpx
pip install pydantic

FastAPI has really great documentation. Explore that to learn about more parameter types and elements for more advanced applications. In this tutorial however, we will limit ourselves to the basics elements, which are enough for a simple ML application

Data Validation with Pydantic

Data validation ensures that data received and produced by endpoints are accurate and meet the requirements of the application. This prevents endpoints from wasting time and resources to process invalid data

With FastAPI, pydantic is used for data validation. It has a simple syntax for defining the structure of request and response data models as classes. They are the passed as data types of input variables of functions or endpoints.

In addition to pydantic, another library, typing, is used to define the data types of keys in the data model. Beyond basic data types like string, int and lists, pydantic has in-built validators for common data formats like emails, constraints on size of ints or strings, etc.

Functionalities of Pydantic

  • Automating data validation
  • Reporting errors
  • Conversion of data
  • Defining data models

Explore Pydantic’s documentation for more information on its functionalities and implementation examples.

Code Implementation

The application in this tutorial is for sentimental analysis of reviews submitted by users of a service.

  • Create folder for your application.
  • In the application folder, create ‘main.py’
  • Create a folder for your modules. You can name it modules’.
  • Create __init__.py to initialize the module as a package in the modules folder.
  • In the same modules folder, create files named data_model.py for your data models and funtions.py for all the functions you will need for your application.

Let’s look at the code for our various files:

data_model.py

# import pydantic, typing 
# from pydantic import BaseModels for data model classes and other data validators
# ! pip install email-validator to enable pydantic's EmailStr work
from pydantic import BaseModel, EmailStr, PastDate
from datetime import datetime
from typing import List, Optional


# for our input data , we will take the email, date and comment from customer
# as seen for the date field, you can make an input value optional, giving ...
# ... the user the choice to submit that field or not
class InputData(BaseModel):
date: Optional[datetime] = None
email: EmailStr
review: str


# in our output data , we simply want to add a new field to the submitted data
# hence we simply inherit the InputData data model and add a new field
class OutputData(InputData):
sentiment: str

functions.py

# import textblob library for sentimental analysis
from textblob import TextBlob

# import data models from data_model.py to validate function inputs
from modules.data_models import InputData, OutputData


# define function for generating polarity of sentiment of a string
def sentimental_analysis(sent):
blob = TextBlob(sent)
analysis = blob.polarity
if analysis < 0:
ans = 'Negative'
elif analysis == 0:
ans = 'Neutral'
else:
ans = 'Positive'
return ans

# define function for retriving comment, running sentimental analysis ..
# ... adding output as new field to the output data
def analyze_data(data: InputData):

review = data.review
sentiment = sentimental_analysis(review)
output = data.dict()
output["sentiment"] = sentiment
return output

main.py


# import data models and functions
from modules.data_models import InputData, OutputData
from modules.functions import analyze_data, sentimental_analysis
from fastapi import FastAPI
import uvicorn

# create instance of fastAPI
app = FastAPI()


# define endpoint that accepts user name as path parameter,...
# and returns data using provided parameter
@app.get('/greet/{name}')
def greet_user(name: str):
greeting = f"Hi {name} , share your experience with us."
return {"greet": greeting}

# define endpoint that accepts user review in the form of the defined input data
# specify data model of reponse data
@app.post('/analysis', response_model=OutputData)
def generate_sentiment(response: InputData):
result = analyze_data(response)
return result


# specify host and port number on which fastAPI application runs
# localhost is used here
if __name__ == "__main__":
uvicorn.run("main:app", host="127.0.0.1", port=8000,
reload=True)

Testing with Postman

Postman is a software application used for building, testing, modifying and documenting APIs. In this tutorial, we will set it up in VSCode to test the endpoints of our API.

Setting up Postman

  • Install Postman extension in VSCode
  • Add Postman to side view. Open interface and sign up.
  • You will be redirected to a website to sign up. After sign up, you will be redirected back to VSCode.

Testing endpoints

  • In the postman extension interface, select the HTTP method of an endpoint and provide the path.
  • In the greet endpoint, the name is set as a query parameter and added to the endpoint url as shown below. The result will be displayed in the second half of the interface as shown in the output image.
input of test
output of test
  • For the analysis endpoint, the request data is a body parameter. This will be submitted in the body tab below the url input section. Data models are read as json hence, state the input in a json format with keys just as specified in the data model.
input of endpoint test
output of endpoint test

Conclusion

In this article, we have looked at parts of a fastAPI application, how to build data models with pydantic and typing libraries and learnt how to test API endpoints with Postman.
Further reading on the libraries used will provide information on how to build more advanced APIs for complex machine learning applications.

I hope you learnt a great deal from this article. Do not leave your models in notebooks, make them production ready 😉. Share, comment and react.

--

--