1

I’m working with FastAPI for Model inference in Machine Learning, so I need to have as inputs an array of JSON like this:

[
  {
    "Id":"value",
    "feature1":"value",
    "feature2":"value",
    "feature3":"value"
  },
  {
    "Id":"value",
    "feature1":"value",
    "feature2":"value",
    "feature3":"value"
  },
  {
    "Id":"value",
    "feature1":"value",
    "feature2":"value",
    "feature3":"value"
  }
]

The output (result of prediction) should look like this :

[
  {
    "Id":"value",
    "prediction":"value"
  },
  {
    "Id":"value",
    "prediction":"value"
  },
  {
    "Id":"value",
    "prediction":"value"
  }
]

How to implement this with FastAPI in Python?

Chris
  • 18,724
  • 6
  • 46
  • 80
Legna
  • 125
  • 1
  • 1
  • 10
  • Have you seen how you can describe input and output schemas (response_model) using Pydantic models? https://fastapi.tiangolo.com/tutorial/body/ – MatsLindh Apr 12 '22 at 16:05
  • Yes I’m using Pydantic but I only know how to use it on one single input (one json in requestbody as showing in the link you sent), I wanna know how can I use it to get an array of json (multiple inputs and outputs) – Legna Apr 12 '22 at 16:51

1 Answers1

2

You can declare a request JSON body using a Pydantic model (let's say Item), as described here, and use List[Item] to accept a JSON array (a Python List), as documented here. In a similar way, you can define a Response model. Example below:

from pydantic import BaseModel
from typing import List

class ItemIn(BaseModel):
    Id: str
    feature1: str
    feature2: str
    feature3: str

class ItemOut(BaseModel):
    Id: str
    prediction: str
    
@app.post('/predict', response_model=List[ItemOut])
def predict(items: List[ItemIn]):
    return [{"Id":  "value", "prediction": "value"}, {"Id":  "value", "prediction": "value"}]

Update

You can send the data to the predict() function, as described in this answer. Example below:

@app.post('/predict', response_model=List[ItemOut])
def predict(items: List[ItemIn]):
    for item in items:
        pred = model.predict([[item.feature1, item.feature2, item.feature3]])[0] 

or, use the following, as described here (Option 3), to avoid looping over the items and calling the predict() function multiple times:

import pandas as pd

@app.post('/predict', response_model=List[ItemOut])
def predict(items: List[ItemIn]):
    df = pd.DataFrame([i.dict() for i in items])
    pred = model.predict(df)
Chris
  • 18,724
  • 6
  • 46
  • 80
  • Thank you so much for your feedback, I get an error when I try to assign items directly in prediction = model.predict(items) , also do you have any idea how to exclude "Id" variable when giving items to model.predict because it's only an informative variable and not part of the features (where the models was trained on) – Legna Apr 12 '22 at 17:41
  • Thank you so much, it worked!! Is it necessary to use a dataframe? can't we use it directly, and for the output with type ItemOut here you didn't use it, how can I display the deleted "Id" and prediction result as the output (Response) – Legna Apr 12 '22 at 18:30