pythonjsonmachine-learningfastapipredict

FastAPI array of JSON in Request Body for Machine Learning prediction


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?


Solution

  • You could have your endpoint expecting a JSON request body, using a Pydantic model, as described here (see this answer for more options as well). To that end, create a Pydantic model (let's say ItemIn) with the required parameters (for defining optional parameters, see this answer), and define a parameter of List[ItemIn] type in your endpoint, in order for the endpoint to expect a list of JSON objects (in Python, that is, dict objects), as documented here. In a similar way, you could define a Response model (e.g., ItemOut in the example below).

    Example

    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 could send the data to the predict() function and get the results, 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 in this answer (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)