Reputation: 1194
I'm using pycaret as my ML workflow, I tried to create an API using FastAPI. This is my first time playing into production level, so I'm bit confused about API
I have 10 features; age: float, live_province: str, live_city: str, live_area_big: str, live_area_small: str, sex: float, marital: float, bank: str, salary: float, amount: float and a label which it contains the binary value (0 and 1).
This is what my script for building the API
from pydantic import BaseModel
import numpy as np
from pycaret.classification import *
import uvicorn
from fastapi import FastAPI
app = FastAPI()
model = load_model('catboost_cm_creditable')
class Data(BaseModel):
age: float
live_province: str
live_city: str
live_area_big: str
live_area_small: str
sex: float
marital: float
bank: str
salary: float
amount: float
input_dict = Data
@app.post("/predict")
def predict(model, input_dict):
predictions_df = predict_model(estimator=model, data=input_dict)
predictions = predictions_df['Score'][0]
return predictions
When I tried to run uvicorn script:app
and went to the documentation I can't find the parameter for my features, the parameters only show model and input_dict
How to take my Features onto Parameters in the API?
Upvotes: 4
Views: 966
Reputation: 20766
You need to Type-hint your Pydantic model to make it work with your FastAPI
Imagine like you are really working with Standard Python, when you need to documentate that function,
def some_function(price: int) ->int:
return price
With Pydantic there is nothing different than the example above
Your class Data
is actually a python @dataclass
with super-powers(comes from Pydantic)
from fastapi import Depends
class Data(BaseModel):
age: float
live_province: str
live_city: str
live_area_big: str
live_area_small: str
sex: float
marital: float
bank: str
salary: float
amount: float
@app.post("/predict")
def predict(data: Data = Depends()):
predictions_df = predict_model(estimator=model, data=data)
predictions = predictions_df["Score"][0]
return predictions
There is a one little trick, with Depends, you 'll get a single queries like when you are defining each field seperately.
Upvotes: 3
Reputation: 2118
Your problem is with the definition of the API's function. You added an argument for you data input but you didn't tell FastAPI it's type. Also I assume that you mean't to use the model that you've loaded globally instead of received it as a parameter. Also you don't need to create a global instance for your input data, as you want to get it from the user.
Therefore, simply change the signature of your function to:
def predict(input_dict: Data):
and remove the line:
input_dict = Data
(Which just creates an Alias to your class Data
, named input_dict
)
You'll end up with:
app = FastAPI()
model = load_model('catboost_cm_creditable')
class Data(BaseModel):
age: float
live_province: str
live_city: str
live_area_big: str
live_area_small: str
sex: float
marital: float
bank: str
salary: float
amount: float
@app.post("/predict")
def predict(input_dict: Data):
predictions_df = predict_model(estimator=model, data=input_dict)
predictions = predictions_df['Score'][0]
return predictions
Also, I would recommend changing the name of the class Data
to something more clear and easier to understand, even DataUnit
would be better in my opinion as Data
is too general.
Upvotes: 1