eaedk commited on
Commit
6272ed2
1 Parent(s): fe2dab3
Files changed (1) hide show
  1. main.py +174 -0
main.py ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ import uvicorn
3
+ from typing import List, Literal, Optional
4
+ from pydantic import BaseModel
5
+ import pandas as pd
6
+ import pickle
7
+ import os
8
+ import json
9
+ import logging
10
+
11
+ # logger = logging.getLogger(__name__)
12
+ logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
13
+
14
+ # logging.debug('This is a debug message')
15
+ # logging.info('This is an info message')
16
+ # logging.warning('This is a warning message')
17
+ # logging.error('This is an error message')
18
+ # logging.critical('This is a critical message')
19
+
20
+
21
+ # Util Functions & Classes
22
+ def loading(fp):
23
+ with open(fp, "rb") as f:
24
+ data = pickle.load(f)
25
+
26
+ print(f"INFO: Loaded data : {data}")
27
+ return data
28
+
29
+
30
+ def predict(df, endpoint="simple"):
31
+ """Take a dataframe as input and use it to make predictions"""
32
+
33
+ print(
34
+ f"[Info] 'predict' function has been called through the endpoint '{endpoint}'.\n"
35
+ )
36
+
37
+ logging.info(f" \n{df.to_markdown()}")
38
+
39
+ # scaling
40
+ scaled_df = scaler.transform(df)
41
+ logging.info(f" Scaler output is of type {type(scaled_df)}")
42
+
43
+ # prediction
44
+ prediction = model.predict_proba(scaled_df)
45
+ print(f"INFO: Prediction output: {prediction}")
46
+
47
+ # Formatting of the prediction
48
+ ## extract highest proba
49
+ highest_proba = prediction.max(axis=1)
50
+ print(f"INFO: Highest probabilities : {highest_proba}")
51
+
52
+ ## extract indexes of the highest proba
53
+ highest_proba_idx = prediction.argmax(axis=1)
54
+ print(f"INFO: Highest probability indexes : {highest_proba_idx}")
55
+
56
+ ## Maching prediction with classes
57
+ predicted_classes = [labels[i] for i in highest_proba_idx]
58
+ print(f"INFO: Predicted classes : {predicted_classes}")
59
+ # prediction[:, highest_proba_idx]
60
+
61
+ # save in df
62
+ df["predicted proba"] = highest_proba
63
+ df["predicted label"] = predicted_classes
64
+
65
+ print(f"INFO: dataframe filled with prediction\n{df.to_markdown()}\n")
66
+
67
+ # parsing prediction
68
+ # parsed = json.loads(df.to_json(orient="index")) # or
69
+ parsed = df.to_dict("records")
70
+
71
+ return parsed
72
+
73
+
74
+ ## INPUT MODELING
75
+ class Land(BaseModel):
76
+ """Modeling of one input data in a type-restricted dictionary-like format
77
+
78
+ column_name : variable type # strictly respect the name in the dataframe header.
79
+
80
+ eg.:
81
+ =========
82
+ customer_age : int
83
+ gender : Literal['male', 'female', 'other']
84
+ """
85
+
86
+ N: float
87
+ P: float
88
+ K: float
89
+ temperature: float
90
+ humidity: float
91
+ ph: float
92
+ rainfall: float
93
+
94
+
95
+ class Lands(BaseModel):
96
+ inputs: List[Land]
97
+
98
+ def return_list_of_dict(
99
+ cls,
100
+ ):
101
+ # return [land.dict() for land in cls.inputs]
102
+ return [i.dict() for i in cls.inputs]
103
+
104
+
105
+ # API
106
+ app = FastAPI(title="API")
107
+ ml_objects = loading(fp=os.path.join("assets", "ml", "crop_recommandation2.pkl"))
108
+ ## Extract the ml components
109
+ model = ml_objects["model"]
110
+ scaler = ml_objects["scaler"].set_output(transform="pandas")
111
+ labels = ml_objects["labels"]
112
+ # = ml_objects[""]
113
+
114
+
115
+ # Endpoints
116
+ @app.get("/")
117
+ def root():
118
+ return {"API": " This is an API to ... ."}
119
+
120
+
121
+ @app.get("/checkup")
122
+ def test(a: Optional[int], b: int):
123
+ return {"a": a, "b": b}
124
+
125
+
126
+ ## ML endpoint
127
+ @app.post("/predict")
128
+ def make_prediction(
129
+ N: float,
130
+ P: float,
131
+ K: float,
132
+ temperature: float,
133
+ humidity: float,
134
+ ph: float,
135
+ rainfall: float,
136
+ ):
137
+ """Make prediction with the passed data"""
138
+
139
+ df = pd.DataFrame(
140
+ {
141
+ "N": [N],
142
+ "P": [P],
143
+ "K": [K],
144
+ "temperature": [temperature],
145
+ "humidity": [humidity],
146
+ "ph": [ph],
147
+ "rainfall": [rainfall],
148
+ }
149
+ )
150
+
151
+ parsed = predict(df=df) # df.to_dict('records')
152
+
153
+ return {
154
+ "output": parsed,
155
+ }
156
+
157
+
158
+ @app.post("/predict_multi")
159
+ def make_multi_prediction(multi_lands: Lands):
160
+ """Make prediction with the passed data"""
161
+ print(f"Mutiple inputs passed: {multi_lands}\n")
162
+ df = pd.DataFrame(multi_lands.return_list_of_dict())
163
+
164
+ parsed = predict(df=df, endpoint="multi inputs") # df.to_dict('records')
165
+
166
+ return {
167
+ "output": parsed,
168
+ "author": "Stella Archar",
169
+ "api_version": ";)",
170
+ }
171
+
172
+
173
+ if __name__ == "__main__":
174
+ uvicorn.run("main:app", reload=True)