FastAPI is a powerful Python framework, and one of its uses is making it simple to create and deploy machine learning models as web services. With its speed and ease of use, you can have your model up and running in no time. In this guide, we'll walk through the straightforward process of using FastAPI to serve a machine-learning model.
Einblick allows you to deploy these models directly from our canvas, meaning you no longer need to use third-party services or manage additional deployment resources in order to bring your model to production. Want to try it yourself? Simply clone this canvas and try it yourself.
NOTE: Even the Einblick free tier allows you to create Endpoints, but will expire after 30 minutes of inactivity.
Jump to Just the Python Code
1. Quickly Create a Machine Learning Model to Deploy
We use the Iris dataset and XGBoost
to create a classification model, and then use joblib
to save that model to disk. If you need help training a model on your own data, just reach out to us at support@einblick.ai.
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# Load the Iris dataset
iris = load_iris()
X, y = iris.data, iris.target
# Train XGBoost classifier
xgb_classifier = xgb.XGBClassifier()
xgb_classifier.fit(X, y)
joblib.dump(xgb_classifier, 'xgb_model.joblib') # Save to a file
2. Creating Class Definitions with Pydantic
FastAPI leverages Pydantic
models to automatically handle request and response data validation. With Pydantic
's powerful model definition capabilities, you can ensure data integrity by specifying data types, constraints, and validation rules concisely.
Here, we have a relatively simple class definition for inputs and outputs – the inputs are four numeric (float
) values, and the expected output is a single true/false output.
# Create a Pydantic model for input data
class IrisData(BaseModel):
sepal_length: float
sepal_width: float
petal_length: float
petal_width: float
class PredictionResult(BaseModel):
predicted_species: bool
3. Creating the /predict Endpoint
The following FastAPI code snippet demonstrates how to deploy a machine learning model for species prediction. The model, loaded via joblib
, takes in specific features—sepal length, sepal width, petal length, and petal width—calculates the prediction, and responds with the predicted species.
Upon receiving a POST request at the /predict
endpoint and providing input data conforming to the IrisData
schema, this function uses the classifier to predict the species of an Iris flower. The response_model=PredictionResult
ensures that the response adheres to the defined data structure.
# Load the model from disk
xgb_classifier = joblib.load('xgb_model.joblib')
@app.post("/predict", response_model=PredictionResult, tags=["Prediction"])
def predict_species(data: IrisData):
features = np.array([[
data.sepal_length,
data.sepal_width,
data.petal_length,
data.petal_width
]])
prediction = xgb_classifier.predict(features)
return {"predicted_species": prediction[0]}
Within Einblick, you must first enable incoming connections to your Canvas by going to Kernel Settings → Incoming Connections. Remember to keep your URL string safe, as the unique prefix acts as your API key.

4. Start the App
Finally, we start the app. For Einblick, you want to use host="0.0.0.0", port=7000
. You will access the endpoint by posting data to https://your-einblick-endpoint-string.proxy.einblick.ai/predict
Note that we use nest_asyncio because Jupyter Notebook itself already runs its own event loop. When you attempt to run code that creates another event loop (eg Fast API) it can cause conflicts.
import nest_asyncio
nest_asyncio.apply()
def run():
uvicorn.run(app, host="0.0.0.0", port=7000, loop="none")
# If the notebook is the main program, invoke the run function
if __name__ == "__main__":
run()
Call the endpoint and observe that we receive a response. For this example new data point, we receive false
when I use curl
to post it from my local Mac Terminal:

5. Creating Webpages
FastAPI facilitates the creation of web pages effortlessly. For instance, the endpoint /hello
generates a simple "Hello!" webpage. The Response class is utilized to define the response content explicitly as HTML.
@app.get("/hello")
async def hello():
html_content = """
<html>
<head><title>Hello Page</title></head>
<body><h1>Hello!</h1></body>
</html>"""
return Response(content=html_content, media_type="text/html")

6. Automatic Endpoint Documentation
One of the best time-saving aspects of FastAPI is its ability to automatically create documentation for your deployed endpoint. Leveraging the type annotations and Pydantic
models used to define routes and request/response structures, FastAPI dynamically generates comprehensive and interactive documentation based on the OpenAPI standard.
The docs can be accessed at https://your-einblick-endpoint-string.proxy.einblick.ai/docs#/
You’ll notice that you get well-formatted documentation and even interactive testing. End users will always have insight into input requirements, available endpoints, expected parameters, and response formats.

Just the Python Code
!pip install fastapi uvicorn nest_asyncio xgboost
from fastapi import FastAPI, Response
import uvicorn
###
### Imports
###
import xgboost as xgb
import joblib
from pydantic import BaseModel
import numpy as np
#Jupyter Notebook itself already runs its own event loop, and when you attempt to run code that creates another event loop it can cause conflicts. nest_asyncio is a workaround
import nest_asyncio
nest_asyncio.apply()
###
### Create Model
### Replace this with your model
xgb_classifier = xgb.XGBClassifier()
xgb_classifier.fit(X_train, y_train)
joblib.dump(xgb_classifier, 'xgb_model.joblib')
###
### Start the Endpoint
###
app = FastAPI()
# Load the model during startup
xgb_classifier = joblib.load('xgb_model.joblib')
# Create a Pydantic model for input data
class IrisData(BaseModel):
sepal_length: float
sepal_width: float
petal_length: float
petal_width: float
class PredictionResult(BaseModel):
predicted_species: bool
### Endpoint to predict using the loaded XGBoost model
@app.post("/predict", response_model=PredictionResult, tags=["Prediction"])
def predict_species(data: IrisData):
features = np.array([[
data.sepal_length,
data.sepal_width,
data.petal_length,
data.petal_width
]])
prediction = xgb_classifier.predict(features)
return {"predicted_species": prediction[0]}
### Return "Hello World"
@app.get("/")
async def root():
return {"message": "Hello World"}
### Create an HTML page that just says "Hello!"
@app.get("/hello")
async def hello():
html_content = """
<html>
<head><title>Hello Page</title></head>
<body><h1>Hello!</h1></body>
</html>"""
return Response(content=html_content, media_type="text/html")
def run():
uvicorn.run(app, host="0.0.0.0", port=7000, loop="none")
# If the notebook is the main program, invoke the run function
if __name__ == "__main__":
run()
About
Einblick is an AI-native data science platform that provides data teams with an agile workflow to swiftly explore data, build predictive models, and deploy data apps. Founded in 2020, Einblick was developed based on six years of research at MIT and Brown University. Einblick is funded by Amplify Partners, Flybridge, Samsung Next, Dell Technologies Capital, and Intel Capital. For more information, please visit www.einblick.ai and follow us on LinkedIn and Twitter.