Nipun commited on
Commit
e3e1326
·
1 Parent(s): 9d6ff4e

Deploy ML app with LFS

Browse files
Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY app/ app/
9
+ COPY models/ models/
10
+
11
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
README.md CHANGED
@@ -1,10 +1,106 @@
1
  ---
2
- title: Ml Deploy App
3
- emoji: 🔥
4
- colorFrom: indigo
5
- colorTo: green
6
  sdk: docker
7
- pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Iris Classification
3
+ emoji: 🌺
4
+ colorFrom: green
5
+ colorTo: purple
6
  sdk: docker
7
+ app_port: 8000
8
  ---
9
 
10
+ # FastAPI ML Deployment Tutorial
11
+
12
+ This repository demonstrates how to serve and deploy a Machine Learning application using FastAPI and Docker. We use the classic Iris dataset to keep the ML part simple and focus on the deployment mechanics.
13
+
14
+ ## Project Structure
15
+
16
+ ```
17
+ .
18
+ ├── app/
19
+ │ ├── __init__.py
20
+ │ ├── main.py # FastAPI application
21
+ │ └── model.py # Model loading and prediction logic
22
+ ├── model_training/
23
+ │ └── train.py # Script to train and save the model
24
+ ├── models/ # Directory to store the saved model artifact
25
+ ├── requirements.txt # Python dependencies
26
+ ├── Dockerfile # Container definition
27
+ └── README.md # This tutorial
28
+ ```
29
+
30
+ ## Prerequisites
31
+
32
+ - Python 3.9+
33
+ - Docker (optional, for containerization)
34
+
35
+ ## Step 1: Setup Environment
36
+
37
+ 1. Clone the repository:
38
+ ```bash
39
+ git clone <repository-url>
40
+ cd ml-deploy-app
41
+ ```
42
+
43
+ 2. Create a virtual environment:
44
+ ```bash
45
+ python -m venv venv
46
+ source venv/bin/activate # On Windows: venv\Scripts\activate
47
+ ```
48
+
49
+ 3. Install dependencies:
50
+ ```bash
51
+ pip install -r requirements.txt
52
+ ```
53
+
54
+ ## Step 2: Train the Model
55
+
56
+ Run the training script to generate the model artifact (`models/iris_model.joblib`):
57
+
58
+ ```bash
59
+ python model_training/train.py
60
+ ```
61
+
62
+ You should see output indicating the model was saved successfully.
63
+
64
+ ## Step 3: Run the API Locally
65
+
66
+ Start the FastAPI server using Uvicorn:
67
+
68
+ ```bash
69
+ uvicorn app.main:app --reload
70
+ ```
71
+
72
+ The API will be available at `http://127.0.0.1:8000`.
73
+
74
+ ### Interactive Documentation
75
+
76
+ Visit `http://127.0.0.1:8000/docs` to see the Swagger UI. You can test the `/predict` endpoint directly from the browser.
77
+
78
+ **Example Request Body:**
79
+
80
+ ```json
81
+ {
82
+ "sepal_length": 5.1,
83
+ "sepal_width": 3.5,
84
+ "petal_length": 1.4,
85
+ "petal_width": 0.2
86
+ }
87
+ ```
88
+
89
+ ## Step 4: Run with Docker
90
+
91
+ 1. Build the Docker image:
92
+ ```bash
93
+ docker build -t iris-app .
94
+ ```
95
+
96
+ 2. Run the container:
97
+ ```bash
98
+ docker run -p 8000:8000 iris-app
99
+ ```
100
+
101
+ The API will be accessible at `http://127.0.0.1:8000` (and `http://127.0.0.1:8000/docs`).
102
+
103
+ ## Next Steps
104
+
105
+ - **Hugging Face Spaces**: You can deploy this easily to Hugging Face Spaces by adding a `README.md` with YAML metadata and pushing the code.
106
+ - **Cloud Deployment**: This Docker container can be deployed to AWS ECS, Google Cloud Run, or Azure Container Apps.
app/__pycache__/main.cpython-312.pyc ADDED
Binary file (1.38 kB). View file
 
app/__pycache__/model.cpython-312.pyc ADDED
Binary file (2.44 kB). View file
 
app/main.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from app.model import IrisModel, IrisInput, IrisPrediction
3
+
4
+ app = FastAPI(title="Iris Classification API", version="1.0.0")
5
+
6
+ # Initialize model
7
+ model = IrisModel()
8
+
9
+ @app.get("/")
10
+ def read_root():
11
+ return {"message": "Welcome to the Iris Classification API"}
12
+
13
+ @app.get("/health")
14
+ def health_check():
15
+ return {"status": "healthy"}
16
+
17
+ @app.post("/predict", response_model=IrisPrediction)
18
+ def predict_iris(input_data: IrisInput):
19
+ try:
20
+ prediction = model.predict(input_data)
21
+ return prediction
22
+ except Exception as e:
23
+ raise HTTPException(status_code=500, detail=str(e))
app/model.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import joblib
2
+ import os
3
+ from pydantic import BaseModel
4
+ from typing import List
5
+
6
+ class IrisInput(BaseModel):
7
+ sepal_length: float
8
+ sepal_width: float
9
+ petal_length: float
10
+ petal_width: float
11
+
12
+ class IrisPrediction(BaseModel):
13
+ class_name: str
14
+ class_id: int
15
+
16
+ class IrisModel:
17
+ def __init__(self):
18
+ self.model = None
19
+ self.class_names = ["setosa", "versicolor", "virginica"]
20
+ self.load_model()
21
+
22
+ def load_model(self):
23
+ model_path = os.path.join("models", "iris_model.joblib")
24
+ if os.path.exists(model_path):
25
+ self.model = joblib.load(model_path)
26
+ else:
27
+ raise FileNotFoundError(f"Model not found at {model_path}. Please train the model first.")
28
+
29
+ def predict(self, input_data: IrisInput) -> IrisPrediction:
30
+ if not self.model:
31
+ self.load_model()
32
+
33
+ data = [[
34
+ input_data.sepal_length,
35
+ input_data.sepal_width,
36
+ input_data.petal_length,
37
+ input_data.petal_width
38
+ ]]
39
+
40
+ prediction = self.model.predict(data)[0]
41
+ return IrisPrediction(
42
+ class_name=self.class_names[prediction],
43
+ class_id=int(prediction)
44
+ )
model_training/train.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import joblib
3
+ import pandas as pd
4
+ from sklearn.datasets import load_iris
5
+ from sklearn.ensemble import RandomForestClassifier
6
+
7
+ # Set up directories
8
+ MODEL_DIR = "models"
9
+ os.makedirs(MODEL_DIR, exist_ok=True)
10
+ MODEL_PATH = os.path.join(MODEL_DIR, "iris_model.joblib")
11
+
12
+ def train_model():
13
+ print("Loading Iris dataset...")
14
+ iris = load_iris()
15
+ X, y = iris.data, iris.target
16
+
17
+ print("Training Random Forest Classifier...")
18
+ clf = RandomForestClassifier(n_estimators=100, random_state=42)
19
+ clf.fit(X, y)
20
+
21
+ print(f"Saving model to {MODEL_PATH}...")
22
+ joblib.dump(clf, MODEL_PATH)
23
+ print("Model saved successfully!")
24
+
25
+ if __name__ == "__main__":
26
+ train_model()
models/iris_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2c1ec61ba2ac7f6623402209dce9c13ac0175fa4c4285e5503666fcb8b10c15f
3
+ size 186753
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi==0.109.0
2
+ uvicorn==0.27.0
3
+ scikit-learn==1.4.0
4
+ joblib==1.3.2
5
+ pandas==2.2.0
6
+ numpy==1.26.3
7
+ pydantic==2.6.0