zidea21 commited on
Commit
049998a
·
verified ·
1 Parent(s): af08210

Upload 4 files

Browse files
fertilizer_api.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from pydantic import BaseModel, Field
3
+ import pandas as pd
4
+ import joblib
5
+ import os
6
+ import logging
7
+ from typing import Dict, List
8
+
9
+ # Set up logging
10
+ logging.basicConfig(level=logging.INFO)
11
+ logger = logging.getLogger(__name__)
12
+
13
+ app = FastAPI(title="Fertilizer Recommendation API")
14
+
15
+ # Define model file paths
16
+ PIPELINE_PATH = r"fertilizer_pipeline.joblib"
17
+ ENCODER_PATH = r"fertilizer_label_encoder.joblib"
18
+
19
+ # Valid crops
20
+ VALID_CROPS = [
21
+ 'Sugarcane', 'Jowar', 'Cotton', 'Rice', 'Wheat', 'Groundnut',
22
+ 'Maize', 'Tur', 'Urad', 'Moong', 'Gram', 'Masoor', 'Soybean',
23
+ 'Ginger', 'Turmeric', 'Grapes'
24
+ ]
25
+
26
+ # Load pipeline and encoder at startup
27
+ try:
28
+ pipeline = joblib.load(PIPELINE_PATH)
29
+ label_encoder = joblib.load(ENCODER_PATH)
30
+ logger.info("Pipeline and encoder loaded successfully")
31
+ except Exception as e:
32
+ logger.error(f"Failed to load pipeline or encoder: {str(e)}")
33
+ raise Exception(f"Failed to load pipeline or encoder: {str(e)}")
34
+
35
+ # Pydantic model for input validation
36
+ class FertilizerInput(BaseModel):
37
+ Nitrogen: float = Field(..., ge=20, le=150, description="Nitrogen content in soil (kg/ha)")
38
+ Phosphorus: float = Field(..., ge=10, le=90, description="Phosphorus content in soil (kg/ha)")
39
+ Potassium: float = Field(..., ge=5, le=150, description="Potassium content in soil (kg/ha)")
40
+ pH: float = Field(..., ge=5.5, le=8.5, description="Soil pH value")
41
+ Rainfall: float = Field(..., ge=300, le=1700, description="Rainfall in millimeters")
42
+ Temperature: float = Field(..., ge=10, le=40, description="Temperature in Celsius")
43
+ Crop: str = Field(..., description="Crop type", enum=VALID_CROPS)
44
+
45
+ # Synchronous prediction function
46
+ def predict_fertilizer(input_data: Dict) -> Dict:
47
+ try:
48
+ # Convert input to DataFrame
49
+ input_df = pd.DataFrame([input_data])
50
+
51
+ # Validate required columns
52
+ required_cols = ['Nitrogen', 'Phosphorus', 'Potassium', 'pH', 'Rainfall', 'Temperature', 'Crop']
53
+ missing_cols = set(required_cols) - set(input_df.columns)
54
+ if missing_cols:
55
+ raise ValueError(f"Missing required columns: {missing_cols}")
56
+
57
+ # Predict
58
+ y_pred_encoded = pipeline.predict(input_df)
59
+ y_pred_label = label_encoder.inverse_transform(y_pred_encoded)[0]
60
+
61
+ return {
62
+ "fertilizer": y_pred_label,
63
+ "status": "success"
64
+ }
65
+ except Exception as e:
66
+ logger.error(f"Prediction error: {str(e)}")
67
+ return {
68
+ "fertilizer": "",
69
+ "status": "failure",
70
+ "error": str(e)
71
+ }
72
+
73
+ @app.post("/predict_fertilizer")
74
+ async def predict_fertilizer_endpoint(input_data: FertilizerInput):
75
+ try:
76
+ # Check if files exist
77
+ for path in [PIPELINE_PATH, ENCODER_PATH]:
78
+ if not os.path.exists(path):
79
+ raise HTTPException(status_code=500, detail=f"File not found: {path}")
80
+
81
+ # Convert Pydantic model to dict
82
+ input_dict = input_data.dict()
83
+
84
+ # Make prediction
85
+ result = predict_fertilizer(input_dict)
86
+
87
+ if result["status"] == "failure":
88
+ raise HTTPException(status_code=400, detail=result["error"])
89
+
90
+ return result
91
+
92
+ except Exception as e:
93
+ logger.error(f"Error processing prediction: {str(e)}")
94
+ raise HTTPException(status_code=500, detail=f"Error processing prediction: {str(e)}")
95
+
96
+ @app.get("/")
97
+ async def root():
98
+ return {"message": "Fertilizer Recommendation API is running. Use /predict_fertilizer endpoint to send input data."}
99
+
100
+ @app.get("/valid_inputs")
101
+ async def get_valid_inputs():
102
+ return {
103
+ "Nitrogen": {"min": 20, "max": 150, "unit": "kg/ha"},
104
+ "Phosphorus": {"min": 10, "max": 90, "unit": "kg/ha"},
105
+ "Potassium": {"min": 5, "max": 150, "unit": "kg/ha"},
106
+ "pH": {"min": 5.5, "max": 8.5, "unit": "pH"},
107
+ "Rainfall": {"min": 300, "max": 1700, "unit": "mm"},
108
+ "Temperature": {"min": 10, "max": 40, "unit": "Celsius"},
109
+ "Crop": VALID_CROPS
110
+ }
fertilizer_label_encoder.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b0013e565006a0f4760832ae8cdc87934a1367d96c5fd64f37db595eaccb99b3
3
+ size 866
fertilizer_pipeline.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:20ac229f796c164db8dcfdbff6eb3bf9f9c25e7cd0d4ee0a5f6457f5f05484df
3
+ size 46438490
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ fastapi==0.112.2
2
+ uvicorn==0.32.1
3
+ pandas==2.2.3
4
+ scikit-learn==1.6.1
5
+ numpy==2.0.2
6
+ joblib==1.4.2
7
+ pydantic==2.10.3
8
+ markupsafe==2.1.5
9
+ anyio==4.7.0