Python Tools to Deploy
Your Machine Learning
Models Faster 🛩
Jeff Hale
Welcome Aboard!
Pilot: Jeff Hale
● linkedin.com/in/-jeffhale/
● twitter@discdiver
● jeffhale.medium.com/
Jeff Hale ✈ @discdiver 2
Preflight check
See questions in Slack 🙂
Jeff Hale ✈ @discdiver 3
Planes
Jeff Hale ✈ @discdiver 4
Flight plans
● Test flights for each plane
○ Hello world
○ Show data
○ Plot
○ Predict
○ Cruising altitude & turbulence (pros & cons)
● Grab your luggage (takeaways)
● Post-flight data (Q&A and questionnaire)
● Disembark
Jeff Hale ✈ @discdiver 5
Flight plan materials
● GitHub repo:
https://github.com/discdiver/dsdc-deploy-models
Jeff Hale ✈ @discdiver 6
Ultralight
New, quick to fly, experimental
Jeff Hale ✈ @discdiver 7
Gradio
Gradio Demo 1: Hello world
8
Jeff Hale ✈ @discdiver 9
Gradio #1: Hello world
- pip install gradio
- python gradio_hello.py
Jeff Hale ✈ @discdiver 10
Gradio #1: Hello world
import gradio as gr
def hello(plane):
return f"I'm an ultralight {plane} 🛩"
iface = gr.Interface(
fn=hello,
inputs=['text'],
outputs=['text']
).launch()
Jeff Hale ✈ @discdiver 11
Gradio Demo 2: Show data
12
Gradio #2: Show me the data!
def show_pens(alpha):
return pd.read_csv(
'https://raw.githubusercontent…/penguins.csv')
iface = gr.Interface(
fn=show_pens,
inputs=['text'],
outputs=[gr.outputs.Dataframe()],
description="Table of Palmer Penguins"
).launch(share=True)
Jeff Hale ✈ @discdiver 13
Gradio #2: Show me the data!
- pip install gradio pandas seaborn
- python gradio_pandas.py
Jeff Hale ✈ @discdiver 14
Gradio Demo 3: Plotting
15
Gradio #3: Plot it
- Plotly doesn’t work as of 2.8.7 (targeted for 2.9) ☹
- You can use Matplotlib as of Gradio 2.8.2
Jeff Hale ✈ @discdiver 16
Gradio #3: Plot it
Jeff Hale ✈ @discdiver 17
Gradio #3: Plot it
def plot_pens(place_holder):
"""scatter plot penguin chars using matplotlib"""
df_pens = pd.read_csv("https://raw.githubuser…/penguins.csv")
fig = plt.figure()
plt.scatter(
x=df_pens["bill_length_mm"], y=df_pens["bill_depth_mm"])
return fig
Jeff Hale ✈ @discdiver 18
Gradio #3: Plot it
iface = gr.Interface(
fn=plot_pens,
layout="vertical",
inputs=["checkbox"],
outputs=["plot"],
title="Scatterplot of Palmer Penguins",
description="Let's talk pens. Click to see a plot.",
article="Talk more about Penguins here, shall we?",
theme="peach",
live=True,
).launch()
Jeff Hale ✈ @discdiver 19
Gradio Demo 4: Predict
20
Gradio #4: Model inference
import gradio as gr
gr.Interface.load('huggingface/gpt2').launch()
Jeff Hale ✈ @discdiver 21
Gradio #4: Predict - prettier
gr.Interface.load(
"huggingface/gpt2",
title="Storytelling with GPT2",
css="""
body {background: rgb(2,0,36);
background: linear-gradient(
180deg,
rgba(2,0,36,1) 0%,
rgba(7,51,99,1) 70%,
rgba(6,3,17,1) 100%);}
.title {color: white !important;}
""",
).launch()
Jeff Hale ✈ @discdiver 22
Gradio #4: Predict - prettier
Jeff Hale ✈ @discdiver 23
Gradio Data API - One Click!
Jeff Hale ✈ @discdiver 24
Gradio Pros
● Quick demos for ML 🚀
● Built-in interpretability (sometimes) 🔎
● Auto-docs 📃
● Nice Hugging Face model integration 🤗
● Bright future 😎
● Easy hosting at Hugging Face spaces
https://huggingface.co/spaces/discdiver/gpt2
Jeff Hale ✈ @discdiver 25
Gradio Cons
- Rough around the edges - early stage 🔪
- Not easy to customize elements ✨
- Single page only 1⃣
Jeff Hale ✈ @discdiver 26
Gradio - Hugging Face Acquisition
Abubakar Abid + 🤗
Jeff Hale ✈ @discdiver 27
Cessna Citation Longitude
Light, quick to takeoff, easy flying Jeff Hale ✈ @discdiver 28
Streamlit
Streamlit Demo 1: Hello world
29
Streamlit #1: Hello world
import streamlit as st
name = "Jeff"
st.title(f"Hello from Streamlit, {name}!")
- pip install streamlit
- streamlit run streamlit_hello.py
Jeff Hale ✈ @discdiver 30
Streamlit Demo 2: Show data
31
Streamlit #2: Show data
Jeff Hale ✈ @discdiver 32
Streamlit #2: Show data
import streamlit as st
import pandas as pd
st.title("Streamlit with pandas")
show = st.checkbox("Show dataframe")
df_pens = pd.read_csv( "https://raw.githubusercontent…/penguins.csv")
if show:
df_pens
Jeff Hale ✈ @discdiver 33
Streamlit Demo 3: Plotting
34
Streamlit #3: Plotting
Jeff Hale ✈ @discdiver 35
Streamlit #3: Plotting
choice = st.radio("Select color", ["species", "island"])
fig = px.scatter_3d(
data_frame=df_pens,
x="bill_depth_mm",
y="bill_length_mm",
z="body_mass_g",
color=choice,
title="Penguins in 3D!",
)
fig Jeff Hale ✈ @discdiver 36
Streamlit Demo 4:
Predict
37
Streamlit #4: Predict
Jeff Hale ✈ @discdiver 38
Streamlit #4: Predict
import streamlit as st
from transformers import pipeline
st.header("GPT-2 Stories")
input_text = st.text_area("Enter your text here:")
generator = pipeline("text-generation", model="gpt2")
output = generator(input_text, max_length=100)
output[0]["generated_text"]
Jeff Hale ✈ @discdiver 39
Streamlit #4: Predict
Jeff Hale ✈ @discdiver 40
Streamlit #4: Predict - prettier
Jeff Hale ✈ @discdiver 41
Streamlit #4: Predict - prettier
st.header("Story time")
st.image("https://cdn.pixabay.com/photo/2017/07/12/19/03/highway-2497900_960_720.jpg")
col1, col2 = st.columns(2)
with col1:
input_text = st.text_area("Enter your text here:")
with st.spinner("Generating story..."):
generator = pipeline("text-generation", model="gpt2")
if input_text:
generated_text = generator(input_text, max_length=60)
st.success("Here's your story:")
generated_text[0]["generated_text"]
with col2:
st.header("I'm in another column") Jeff Hale ✈ @discdiver 42
Streamlit Serving Options
- Serve from Streamlit’s servers for free: bit.ly/st-6plots
- Serve from Hugging Face Spaces or Heroku for free 🤗
- Pay Streamlit for more/better hosting 💰
- Host elsewhere
Jeff Hale ✈ @discdiver 43
Streamlit Pros
● Quick websites for many Python use cases 🐍
● Many intuitive interactive widgets ✅
● Caching ⏱
● Nice hosting options 🎁
● Thoughtful docs 📄
● Strong development cadence & team 💪
Jeff Hale ✈ @discdiver 44
Streamlit Cons
● Some customizations cumbersome ✨
● Single page only (without hacks) 1⃣
Jeff Hale ✈ @discdiver 45
Streamlit Snowflake Acquisition
Recent acquisition by Snowflake
Jeff Hale ✈ @discdiver 46
Image Source: Snowflake, Public domain, via Wikimedia Commons
FastAPI
Boeing 737
Commercial grade, fast, smart!
Jeff Hale ✈ @discdiver 47
Jeff Hitchcock, CC BY 2.0 <https://creativecommons.org/licenses/by/2.0>, via Wikimedia Commons
FastAPI Demo 1: Hello world
48
FastAPI #1: Hello world
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def home():
return {"Hello world": "How's it going?"}
if __name__ == "__main__":
uvicorn.run("fastapi_hello:app") Jeff Hale ✈ @discdiver 49
FastAPI #1: Hello world
pip install fastapi uvicorn
python fastapi_hello.py
Returns json
{"Hello world":"How's it going ?"}
Jeff Hale ✈ @discdiver 50
FastAPI
Jeff Hale ✈ @discdiver 51
https://giphy.com/gifs/maverick-the-need-for-speed-i-feel-26vUzl3ufQxx9dims
FastAPI Speed
- Uses Starlette - ASGI (Asynchronous Server Gateway
Interface)
- Fastest Python framework - Techempower benchmark
Jeff Hale ✈ @discdiver 52
FastAPI Demo 2: Show data
53
Automatic docs
Jeff Hale ✈ @discdiver 54
FastAPI #2: Show me the data!
@app.get("/df")
async def pens_data():
df_pens = pd.read_csv(
"https://raw.githubuser…/penguins.csv")
df_no_nans = df_pens.fillna(-1.01)
return df_no_nans
Jeff Hale ✈ @discdiver 55
FastAPI #2: Show me the data!
Return DataFrame, get back JSON 😎
{"species":{"0":"Adelie","1":"Adelie"...
Jeff Hale ✈ @discdiver 56
FastAPI Demo 3: Plotting
57
FastAPI #3: Plotting
Jeff Hale ✈ @discdiver 58
FastAPI #3: Plotting
@app.get("/plot")
async def plot() -> HTMLResponse:
"""return a plotly plot"""
fig = px.scatter_3d(
data_frame=df,
x="bill_depth_mm",
y="bill_length_mm",
z="body_mass_g",
color="species",
title="Penguins in 3D!",
)
return HTMLResponse(fig.to_html())
Jeff Hale ✈ @discdiver 59
FastAPI Demo 4: Predict
60
FastAPI #4: Predict: Form
Jeff Hale ✈ @discdiver 61
FastAPI #4: Predict: Form
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/form", response_class=HTMLResponse)
async def features_form(request: Request):
"""form for getting data"""
return templates.TemplateResponse(
"form.html",
{"request": request})
Jeff Hale ✈ @discdiver 62
FastAPI #4: Predict: HTML Template
<body>
<h1>Enter characteristics of your property in Ames, Iowa</h1>
<form method='POST' enctype="multipart/form-data">
<label for="OverallQual">Overall House Quality</label><br>
<input type="number" name="OverallQual">
<label for="FullBath">Number of Full Bathrooms</label><br>
<input type="number" name="FullBath">
<label for="GarageArea">Garage Area</label><br>
<input type="number" name="GarageArea">
<label for="LotArea">Lot Area</label><br>
<input type="number" name="LotArea">
<p><button type="submit" value="Submit">Submit</button></p>
</form>
</body> Jeff Hale ✈ @discdiver 63
FastAPI #4: Predict: pydantic schema for form
class FeaturesForm(BaseModel):
"""pydantic model to get the form input we want"""
OverallQual: int
FullBath: int
GarageArea: int
LotArea: int
@classmethod
def as_form(cls, OverallQual: int = Form(...), FullBath: int = Form(...),
GarageArea: int = Form(...), LotArea: int = Form(...)):
return cls(OverallQual=OverallQual, FullBath=FullBath,
GarageArea=GarageArea, LotArea=LotArea)
Jeff Hale ✈ @discdiver 64
FastAPI #4: Display prediction
Jeff Hale ✈ @discdiver 65
FastAPI #4: Predict: process
@app.post("/form", response_class=HTMLResponse)
async def make_prediction(
request: Request,
user_input: FeaturesForm=Depends(FeaturesForm.as_form)
):
"""accept form submission and make prediction"""
…load model and make prediction
return templates.TemplateResponse(
"results.html", {"request": request, "prediction": pred}
) Jeff Hale ✈ @discdiver 66
FastAPI #4: Display prediction
<body>
<div class='container'>
<div class='row'>
<div class='col-lg text-center'>
<h2> Your 🏡 house is worth
{{"${:,.2f}".format(prediction) }}.<h2>
<h3> Cool! 🎉 </h3 </div>
</div>
</div>
</body>
Jeff Hale ✈ @discdiver 67
FastAPI Pros
● Fastest Python API framework - async ASGI 🏎
● Automatic API documentation ⭐
● Extensive docs 📃
● Nice test client 👌
● Nice dependency injection 💉
● Data validation with pydantic / SQL Model integration ↔
● Security / authentication support 🔐
Jeff Hale ✈ @discdiver 68
FastAPI Pros
Sebastian Ramirez
Jeff Hale ✈ @discdiver 69
FastAPI Cons
● Reliant on a single maintainer 😬
● Overriding uvicorn logging is a bit of a pain 🌳
● HTML templating more painful than Flask ⌨
Jeff Hale ✈ @discdiver 70
Grab your luggage (take aways)
71
Web App Data API
Yes Yes
Yes No
Yes (Jinja templates) Yes
72
Source: https://star-history.t9t.io/#streamlit/streamlit&tiangolo/fastapi&gradio-app/gradio
73
Source: https://star-history.com/#tiangolo/fastapi&pallets/flask&Date
74
What about flask?
● Huge inspiration for FastAPI
● Now has more async support, but not easily full async
● FastAPI is faster
● FastAPI leverages typing
● FastAPI winning mindshare
● Gradio just switched to FastAPI backend
● Flask is nicer for quick web app
Jeff Hale ✈ @discdiver 75
Grab Your Luggage
(takeaways)
76
Use what you know, unless it
doesn’t meet your needs
77
Blank slate?
78
Learn what’s popular, growing,
and quick to get off the ground
79
For single-page app that doesn’t
need custom styling
80
Gradio for quick 🤗 models for fun
81
FastAPI for serving data
What to learn next?
(Newer to Python)
82
Post-flight
● Questions?
● Please fill out short form:
https://forms.gle/pEz4suEqZTbBHhdC7
Jeff Hale ✈ @discdiver 83
Disembark
Thank you for flying the deployment skies!
Jeff Hale
● linkedin.com/in/-jeffhale/
● @discdiver
● jeffhale.medium.com/
Jeff Hale ✈ @discdiver 84
Versions used
● Gradio 2.8.7
● Streamlit 1.5.1
● FastAPI 0.75.0
Jeff Hale ✈ @discdiver 85
Python Tools to Deploy
Your Machine Learning
Models Faster 🛩
Jeff Hale

Python tools to deploy your machine learning models faster

  • 1.
    Python Tools toDeploy Your Machine Learning Models Faster 🛩 Jeff Hale
  • 2.
    Welcome Aboard! Pilot: JeffHale ● linkedin.com/in/-jeffhale/ ● twitter@discdiver ● jeffhale.medium.com/ Jeff Hale ✈ @discdiver 2
  • 3.
    Preflight check See questionsin Slack 🙂 Jeff Hale ✈ @discdiver 3
  • 4.
  • 5.
    Flight plans ● Testflights for each plane ○ Hello world ○ Show data ○ Plot ○ Predict ○ Cruising altitude & turbulence (pros & cons) ● Grab your luggage (takeaways) ● Post-flight data (Q&A and questionnaire) ● Disembark Jeff Hale ✈ @discdiver 5
  • 6.
    Flight plan materials ●GitHub repo: https://github.com/discdiver/dsdc-deploy-models Jeff Hale ✈ @discdiver 6
  • 7.
    Ultralight New, quick tofly, experimental Jeff Hale ✈ @discdiver 7 Gradio
  • 8.
    Gradio Demo 1:Hello world 8
  • 9.
    Jeff Hale ✈@discdiver 9
  • 10.
    Gradio #1: Helloworld - pip install gradio - python gradio_hello.py Jeff Hale ✈ @discdiver 10
  • 11.
    Gradio #1: Helloworld import gradio as gr def hello(plane): return f"I'm an ultralight {plane} 🛩" iface = gr.Interface( fn=hello, inputs=['text'], outputs=['text'] ).launch() Jeff Hale ✈ @discdiver 11
  • 12.
    Gradio Demo 2:Show data 12
  • 13.
    Gradio #2: Showme the data! def show_pens(alpha): return pd.read_csv( 'https://raw.githubusercontent…/penguins.csv') iface = gr.Interface( fn=show_pens, inputs=['text'], outputs=[gr.outputs.Dataframe()], description="Table of Palmer Penguins" ).launch(share=True) Jeff Hale ✈ @discdiver 13
  • 14.
    Gradio #2: Showme the data! - pip install gradio pandas seaborn - python gradio_pandas.py Jeff Hale ✈ @discdiver 14
  • 15.
    Gradio Demo 3:Plotting 15
  • 16.
    Gradio #3: Plotit - Plotly doesn’t work as of 2.8.7 (targeted for 2.9) ☹ - You can use Matplotlib as of Gradio 2.8.2 Jeff Hale ✈ @discdiver 16
  • 17.
    Gradio #3: Plotit Jeff Hale ✈ @discdiver 17
  • 18.
    Gradio #3: Plotit def plot_pens(place_holder): """scatter plot penguin chars using matplotlib""" df_pens = pd.read_csv("https://raw.githubuser…/penguins.csv") fig = plt.figure() plt.scatter( x=df_pens["bill_length_mm"], y=df_pens["bill_depth_mm"]) return fig Jeff Hale ✈ @discdiver 18
  • 19.
    Gradio #3: Plotit iface = gr.Interface( fn=plot_pens, layout="vertical", inputs=["checkbox"], outputs=["plot"], title="Scatterplot of Palmer Penguins", description="Let's talk pens. Click to see a plot.", article="Talk more about Penguins here, shall we?", theme="peach", live=True, ).launch() Jeff Hale ✈ @discdiver 19
  • 20.
    Gradio Demo 4:Predict 20
  • 21.
    Gradio #4: Modelinference import gradio as gr gr.Interface.load('huggingface/gpt2').launch() Jeff Hale ✈ @discdiver 21
  • 22.
    Gradio #4: Predict- prettier gr.Interface.load( "huggingface/gpt2", title="Storytelling with GPT2", css=""" body {background: rgb(2,0,36); background: linear-gradient( 180deg, rgba(2,0,36,1) 0%, rgba(7,51,99,1) 70%, rgba(6,3,17,1) 100%);} .title {color: white !important;} """, ).launch() Jeff Hale ✈ @discdiver 22
  • 23.
    Gradio #4: Predict- prettier Jeff Hale ✈ @discdiver 23
  • 24.
    Gradio Data API- One Click! Jeff Hale ✈ @discdiver 24
  • 25.
    Gradio Pros ● Quickdemos for ML 🚀 ● Built-in interpretability (sometimes) 🔎 ● Auto-docs 📃 ● Nice Hugging Face model integration 🤗 ● Bright future 😎 ● Easy hosting at Hugging Face spaces https://huggingface.co/spaces/discdiver/gpt2 Jeff Hale ✈ @discdiver 25
  • 26.
    Gradio Cons - Rougharound the edges - early stage 🔪 - Not easy to customize elements ✨ - Single page only 1⃣ Jeff Hale ✈ @discdiver 26
  • 27.
    Gradio - HuggingFace Acquisition Abubakar Abid + 🤗 Jeff Hale ✈ @discdiver 27
  • 28.
    Cessna Citation Longitude Light,quick to takeoff, easy flying Jeff Hale ✈ @discdiver 28 Streamlit
  • 29.
    Streamlit Demo 1:Hello world 29
  • 30.
    Streamlit #1: Helloworld import streamlit as st name = "Jeff" st.title(f"Hello from Streamlit, {name}!") - pip install streamlit - streamlit run streamlit_hello.py Jeff Hale ✈ @discdiver 30
  • 31.
    Streamlit Demo 2:Show data 31
  • 32.
    Streamlit #2: Showdata Jeff Hale ✈ @discdiver 32
  • 33.
    Streamlit #2: Showdata import streamlit as st import pandas as pd st.title("Streamlit with pandas") show = st.checkbox("Show dataframe") df_pens = pd.read_csv( "https://raw.githubusercontent…/penguins.csv") if show: df_pens Jeff Hale ✈ @discdiver 33
  • 34.
    Streamlit Demo 3:Plotting 34
  • 35.
    Streamlit #3: Plotting JeffHale ✈ @discdiver 35
  • 36.
    Streamlit #3: Plotting choice= st.radio("Select color", ["species", "island"]) fig = px.scatter_3d( data_frame=df_pens, x="bill_depth_mm", y="bill_length_mm", z="body_mass_g", color=choice, title="Penguins in 3D!", ) fig Jeff Hale ✈ @discdiver 36
  • 37.
  • 38.
    Streamlit #4: Predict JeffHale ✈ @discdiver 38
  • 39.
    Streamlit #4: Predict importstreamlit as st from transformers import pipeline st.header("GPT-2 Stories") input_text = st.text_area("Enter your text here:") generator = pipeline("text-generation", model="gpt2") output = generator(input_text, max_length=100) output[0]["generated_text"] Jeff Hale ✈ @discdiver 39
  • 40.
    Streamlit #4: Predict JeffHale ✈ @discdiver 40
  • 41.
    Streamlit #4: Predict- prettier Jeff Hale ✈ @discdiver 41
  • 42.
    Streamlit #4: Predict- prettier st.header("Story time") st.image("https://cdn.pixabay.com/photo/2017/07/12/19/03/highway-2497900_960_720.jpg") col1, col2 = st.columns(2) with col1: input_text = st.text_area("Enter your text here:") with st.spinner("Generating story..."): generator = pipeline("text-generation", model="gpt2") if input_text: generated_text = generator(input_text, max_length=60) st.success("Here's your story:") generated_text[0]["generated_text"] with col2: st.header("I'm in another column") Jeff Hale ✈ @discdiver 42
  • 43.
    Streamlit Serving Options -Serve from Streamlit’s servers for free: bit.ly/st-6plots - Serve from Hugging Face Spaces or Heroku for free 🤗 - Pay Streamlit for more/better hosting 💰 - Host elsewhere Jeff Hale ✈ @discdiver 43
  • 44.
    Streamlit Pros ● Quickwebsites for many Python use cases 🐍 ● Many intuitive interactive widgets ✅ ● Caching ⏱ ● Nice hosting options 🎁 ● Thoughtful docs 📄 ● Strong development cadence & team 💪 Jeff Hale ✈ @discdiver 44
  • 45.
    Streamlit Cons ● Somecustomizations cumbersome ✨ ● Single page only (without hacks) 1⃣ Jeff Hale ✈ @discdiver 45
  • 46.
    Streamlit Snowflake Acquisition Recentacquisition by Snowflake Jeff Hale ✈ @discdiver 46 Image Source: Snowflake, Public domain, via Wikimedia Commons
  • 47.
    FastAPI Boeing 737 Commercial grade,fast, smart! Jeff Hale ✈ @discdiver 47 Jeff Hitchcock, CC BY 2.0 <https://creativecommons.org/licenses/by/2.0>, via Wikimedia Commons
  • 48.
    FastAPI Demo 1:Hello world 48
  • 49.
    FastAPI #1: Helloworld import uvicorn from fastapi import FastAPI app = FastAPI() @app.get("/") def home(): return {"Hello world": "How's it going?"} if __name__ == "__main__": uvicorn.run("fastapi_hello:app") Jeff Hale ✈ @discdiver 49
  • 50.
    FastAPI #1: Helloworld pip install fastapi uvicorn python fastapi_hello.py Returns json {"Hello world":"How's it going ?"} Jeff Hale ✈ @discdiver 50
  • 51.
    FastAPI Jeff Hale ✈@discdiver 51 https://giphy.com/gifs/maverick-the-need-for-speed-i-feel-26vUzl3ufQxx9dims
  • 52.
    FastAPI Speed - UsesStarlette - ASGI (Asynchronous Server Gateway Interface) - Fastest Python framework - Techempower benchmark Jeff Hale ✈ @discdiver 52
  • 53.
    FastAPI Demo 2:Show data 53
  • 54.
    Automatic docs Jeff Hale✈ @discdiver 54
  • 55.
    FastAPI #2: Showme the data! @app.get("/df") async def pens_data(): df_pens = pd.read_csv( "https://raw.githubuser…/penguins.csv") df_no_nans = df_pens.fillna(-1.01) return df_no_nans Jeff Hale ✈ @discdiver 55
  • 56.
    FastAPI #2: Showme the data! Return DataFrame, get back JSON 😎 {"species":{"0":"Adelie","1":"Adelie"... Jeff Hale ✈ @discdiver 56
  • 57.
    FastAPI Demo 3:Plotting 57
  • 58.
    FastAPI #3: Plotting JeffHale ✈ @discdiver 58
  • 59.
    FastAPI #3: Plotting @app.get("/plot") asyncdef plot() -> HTMLResponse: """return a plotly plot""" fig = px.scatter_3d( data_frame=df, x="bill_depth_mm", y="bill_length_mm", z="body_mass_g", color="species", title="Penguins in 3D!", ) return HTMLResponse(fig.to_html()) Jeff Hale ✈ @discdiver 59
  • 60.
    FastAPI Demo 4:Predict 60
  • 61.
    FastAPI #4: Predict:Form Jeff Hale ✈ @discdiver 61
  • 62.
    FastAPI #4: Predict:Form app = FastAPI() templates = Jinja2Templates(directory="templates") @app.get("/form", response_class=HTMLResponse) async def features_form(request: Request): """form for getting data""" return templates.TemplateResponse( "form.html", {"request": request}) Jeff Hale ✈ @discdiver 62
  • 63.
    FastAPI #4: Predict:HTML Template <body> <h1>Enter characteristics of your property in Ames, Iowa</h1> <form method='POST' enctype="multipart/form-data"> <label for="OverallQual">Overall House Quality</label><br> <input type="number" name="OverallQual"> <label for="FullBath">Number of Full Bathrooms</label><br> <input type="number" name="FullBath"> <label for="GarageArea">Garage Area</label><br> <input type="number" name="GarageArea"> <label for="LotArea">Lot Area</label><br> <input type="number" name="LotArea"> <p><button type="submit" value="Submit">Submit</button></p> </form> </body> Jeff Hale ✈ @discdiver 63
  • 64.
    FastAPI #4: Predict:pydantic schema for form class FeaturesForm(BaseModel): """pydantic model to get the form input we want""" OverallQual: int FullBath: int GarageArea: int LotArea: int @classmethod def as_form(cls, OverallQual: int = Form(...), FullBath: int = Form(...), GarageArea: int = Form(...), LotArea: int = Form(...)): return cls(OverallQual=OverallQual, FullBath=FullBath, GarageArea=GarageArea, LotArea=LotArea) Jeff Hale ✈ @discdiver 64
  • 65.
    FastAPI #4: Displayprediction Jeff Hale ✈ @discdiver 65
  • 66.
    FastAPI #4: Predict:process @app.post("/form", response_class=HTMLResponse) async def make_prediction( request: Request, user_input: FeaturesForm=Depends(FeaturesForm.as_form) ): """accept form submission and make prediction""" …load model and make prediction return templates.TemplateResponse( "results.html", {"request": request, "prediction": pred} ) Jeff Hale ✈ @discdiver 66
  • 67.
    FastAPI #4: Displayprediction <body> <div class='container'> <div class='row'> <div class='col-lg text-center'> <h2> Your 🏡 house is worth {{"${:,.2f}".format(prediction) }}.<h2> <h3> Cool! 🎉 </h3 </div> </div> </div> </body> Jeff Hale ✈ @discdiver 67
  • 68.
    FastAPI Pros ● FastestPython API framework - async ASGI 🏎 ● Automatic API documentation ⭐ ● Extensive docs 📃 ● Nice test client 👌 ● Nice dependency injection 💉 ● Data validation with pydantic / SQL Model integration ↔ ● Security / authentication support 🔐 Jeff Hale ✈ @discdiver 68
  • 69.
  • 70.
    FastAPI Cons ● Relianton a single maintainer 😬 ● Overriding uvicorn logging is a bit of a pain 🌳 ● HTML templating more painful than Flask ⌨ Jeff Hale ✈ @discdiver 70
  • 71.
    Grab your luggage(take aways) 71
  • 72.
    Web App DataAPI Yes Yes Yes No Yes (Jinja templates) Yes 72
  • 73.
  • 74.
  • 75.
    What about flask? ●Huge inspiration for FastAPI ● Now has more async support, but not easily full async ● FastAPI is faster ● FastAPI leverages typing ● FastAPI winning mindshare ● Gradio just switched to FastAPI backend ● Flask is nicer for quick web app Jeff Hale ✈ @discdiver 75
  • 76.
  • 77.
    Use what youknow, unless it doesn’t meet your needs 77
  • 78.
    Blank slate? 78 Learn what’spopular, growing, and quick to get off the ground
  • 79.
    79 For single-page appthat doesn’t need custom styling
  • 80.
    80 Gradio for quick🤗 models for fun
  • 81.
  • 82.
    What to learnnext? (Newer to Python) 82
  • 83.
    Post-flight ● Questions? ● Pleasefill out short form: https://forms.gle/pEz4suEqZTbBHhdC7 Jeff Hale ✈ @discdiver 83
  • 84.
    Disembark Thank you forflying the deployment skies! Jeff Hale ● linkedin.com/in/-jeffhale/ ● @discdiver ● jeffhale.medium.com/ Jeff Hale ✈ @discdiver 84
  • 85.
    Versions used ● Gradio2.8.7 ● Streamlit 1.5.1 ● FastAPI 0.75.0 Jeff Hale ✈ @discdiver 85
  • 86.
    Python Tools toDeploy Your Machine Learning Models Faster 🛩 Jeff Hale