dumdum788 commited on
Commit
52b03fc
·
1 Parent(s): 99f7ec8

commit pertama docker api

Browse files
Files changed (4) hide show
  1. Dockerfile +13 -0
  2. app.py +175 -0
  3. model_cnn_best.h5 +3 -0
  4. requirements.txt +6 -0
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+
7
+ RUN pip install --no-cache-dir -r requirements.txt
8
+
9
+ COPY . .
10
+
11
+ EXPOSE 7860
12
+
13
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from pydantic import BaseModel, Field
4
+ import tensorflow as tf
5
+ import numpy as np
6
+
7
+ # =====================================================
8
+ # LOAD MODEL
9
+ # =====================================================
10
+
11
+ MODEL_PATH = "model_cnn_best.h5"
12
+
13
+ model = tf.keras.models.load_model(MODEL_PATH)
14
+
15
+ # =====================================================
16
+ # FASTAPI
17
+ # =====================================================
18
+
19
+ app = FastAPI(
20
+ title="CNN Pose Classifier API",
21
+ version="1.0.0",
22
+ description="API klasifikasi aktivitas menggunakan CNN + MediaPipe Pose"
23
+ )
24
+
25
+ # =====================================================
26
+ # CORS
27
+ # =====================================================
28
+
29
+ app.add_middleware(
30
+ CORSMiddleware,
31
+ allow_origins=["*"], # ganti dengan domain website jika production
32
+ allow_credentials=True,
33
+ allow_methods=["*"],
34
+ allow_headers=["*"],
35
+ )
36
+
37
+ # =====================================================
38
+ # REQUEST MODEL
39
+ # =====================================================
40
+
41
+ class PoseInput(BaseModel):
42
+
43
+ features: list[float] = Field(
44
+ ...,
45
+ min_length=66,
46
+ max_length=66,
47
+ description="66 pose features (x,y landmark)"
48
+ )
49
+
50
+ # =====================================================
51
+ # ROOT
52
+ # =====================================================
53
+
54
+ @app.get("/")
55
+ def home():
56
+
57
+ return {
58
+ "status": "running",
59
+ "message": "CNN Pose Classifier API",
60
+ "input_shape": [66],
61
+ "output": "binary classification"
62
+ }
63
+
64
+ # =====================================================
65
+ # HEALTH CHECK
66
+ # =====================================================
67
+
68
+ @app.get("/health")
69
+
70
+ def health():
71
+
72
+ return {
73
+ "status": "healthy"
74
+ }
75
+
76
+ # =====================================================
77
+ # PREDICTION
78
+ # =====================================================
79
+
80
+ @app.post("/predict")
81
+
82
+ def predict(data: PoseInput):
83
+
84
+ try:
85
+
86
+ # -----------------------------
87
+ # Convert ke numpy
88
+ # -----------------------------
89
+
90
+ features = np.array(
91
+ data.features,
92
+ dtype=np.float32
93
+ )
94
+
95
+ # -----------------------------
96
+ # Validasi jumlah fitur
97
+ # -----------------------------
98
+
99
+ if features.shape != (66,):
100
+
101
+ raise HTTPException(
102
+ status_code=400,
103
+ detail="Input harus terdiri dari 66 fitur."
104
+ )
105
+
106
+ # -----------------------------
107
+ # Validasi NaN dan Inf
108
+ # -----------------------------
109
+
110
+ if np.isnan(features).any():
111
+
112
+ raise HTTPException(
113
+ status_code=400,
114
+ detail="Input mengandung NaN."
115
+ )
116
+
117
+ if np.isinf(features).any():
118
+
119
+ raise HTTPException(
120
+ status_code=400,
121
+ detail="Input mengandung Infinity."
122
+ )
123
+
124
+ # -----------------------------
125
+ # Reshape sesuai model
126
+ # (batch,66,1)
127
+ # -----------------------------
128
+
129
+ features = features.reshape(
130
+ 1,
131
+ 66,
132
+ 1
133
+ )
134
+
135
+ # -----------------------------
136
+ # Predict
137
+ # -----------------------------
138
+
139
+ prediction = model.predict(
140
+ features,
141
+ verbose=0
142
+ )
143
+
144
+ probability = float(prediction[0][0])
145
+
146
+ if probability >= 0.5:
147
+ label = "berbahaya"
148
+ else:
149
+ label = "aman"
150
+
151
+ return {
152
+
153
+ "success": True,
154
+
155
+ "prediction": label,
156
+
157
+ "probability": round(probability, 4),
158
+
159
+ "confidence": round(
160
+ max(probability, 1 - probability),
161
+ 4
162
+ )
163
+
164
+ }
165
+
166
+ except HTTPException:
167
+
168
+ raise
169
+
170
+ except Exception as e:
171
+
172
+ raise HTTPException(
173
+ status_code=500,
174
+ detail=str(e)
175
+ )
model_cnn_best.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3cb82eebaf13172dcb1f3c644eee1b670c4ad02ca646243844b1049e928c623b
3
+ size 900328
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ tensorflow==2.17.0
4
+ numpy
5
+ pydantic
6
+ h5py