| # Python API untuk Klasifikasi Bibit Kelapa Sawit | |
| API server Python ini menggunakan model Hybrid DenseNet-SVM untuk mengklasifikasikan umur bibit kelapa sawit (3 Bulan, 6 Bulan, 9 Bulan). | |
| ## π Struktur File | |
| ``` | |
| python-api/ | |
| βββ app.py # Main Flask application | |
| βββ requirements.txt # Python dependencies | |
| βββ Dockerfile # Docker configuration | |
| βββ .dockerignore # Docker ignore rules | |
| βββ models/ # Folder untuk model files | |
| βββ svm_densenet201_rbf.joblib # Model SVM (ANDA LETAKKAN DI SINI) | |
| βββ metadata.json # Model metadata (ANDA LETAKKAN DI SINI) | |
| βββ metadata.json.example # Contoh format metadata | |
| ``` | |
| ## π§ Persiapan | |
| ### 1. Letakkan File Model Anda | |
| Setelah training model Anda di Google Colab, letakkan file-file berikut ke folder `models/`: | |
| **File yang diperlukan:** | |
| - `svm_densenet201_rbf.joblib` - File model SVM hasil training | |
| - `metadata.json` - File metadata dengan format: | |
| ```json | |
| { | |
| "class_names": ["3 Bulan", "6 Bulan", "9 Bulan"], | |
| "img_size": 224, | |
| "model_type": "DenseNet201 + SVM", | |
| "description": "Klasifikasi perkembangan bibit kelapa sawit berdasarkan umur" | |
| } | |
| ``` | |
| ### 2. Setup Koneksi Supabase (Optional tapi Recommended) | |
| Python API bisa menyimpan hasil prediksi langsung ke database. | |
| **Set environment variables:** | |
| ```env | |
| SUPABASE_URL=https://xyddxrfiacdcnipdclas.supabase.co | |
| SUPABASE_ANON_KEY=your-anon-key | |
| ``` | |
| π **Detail lengkap:** Lihat `SUPABASE_SETUP.md` | |
| ### 3. Verifikasi File | |
| Pastikan struktur folder seperti ini: | |
| ``` | |
| python-api/ | |
| βββ app.py | |
| βββ requirements.txt | |
| βββ Dockerfile | |
| βββ .env (optional untuk local) | |
| βββ models/ | |
| βββ svm_densenet201_rbf.joblib β File model Anda | |
| βββ metadata.json β Metadata Anda | |
| ``` | |
| ## π Cara Deploy | |
| ### Opsi 1: Deploy ke Hugging Face Spaces (RECOMMENDED - Gratis) | |
| 1. **Buat Account di Hugging Face** | |
| - Daftar di https://huggingface.co/join | |
| - Buat Space baru (New Space) | |
| - Pilih Docker sebagai SDK | |
| 2. **Upload Files** | |
| - Upload semua file dari folder `python-api/` | |
| - Pastikan file model sudah ada di folder `models/` | |
| 3. **Setting Environment Variables** | |
| - Go to Settings β Variables and secrets | |
| - Add secrets: | |
| - `SUPABASE_URL` | |
| - `SUPABASE_ANON_KEY` | |
| 4. **Dapatkan URL API** | |
| - Setelah deploy, Anda akan mendapat URL seperti: `https://username-spacename.hf.space` | |
| ### Opsi 2: Deploy ke Railway.app | |
| 1. **Install Railway CLI** | |
| ```bash | |
| npm install -g @railway/cli | |
| ``` | |
| 2. **Login ke Railway** | |
| ```bash | |
| railway login | |
| ``` | |
| 3. **Deploy dari folder python-api** | |
| ```bash | |
| cd python-api | |
| railway init | |
| railway up | |
| ``` | |
| 4. **Set Environment Variables** | |
| ```bash | |
| railway variables set SUPABASE_URL=https://xyddxrfiacdcnipdclas.supabase.co | |
| railway variables set SUPABASE_ANON_KEY=your-key | |
| ``` | |
| 5. **Generate Domain** | |
| ```bash | |
| railway domain | |
| ``` | |
| ### Opsi 3: Deploy ke Google Cloud Run | |
| 1. **Install Google Cloud SDK** | |
| 2. **Build dan Push Docker Image** | |
| ```bash | |
| cd python-api | |
| # Build image | |
| gcloud builds submit --tag gcr.io/PROJECT_ID/palm-classifier | |
| # Deploy to Cloud Run | |
| gcloud run deploy palm-classifier \ | |
| --image gcr.io/PROJECT_ID/palm-classifier \ | |
| --platform managed \ | |
| --region asia-southeast2 \ | |
| --allow-unauthenticated \ | |
| --set-env-vars SUPABASE_URL=https://xyddxrfiacdcnipdclas.supabase.co,SUPABASE_ANON_KEY=your-key | |
| ``` | |
| ### Opsi 4: Local Testing (Development) | |
| ```bash | |
| cd python-api | |
| # Install dependencies | |
| pip install -r requirements.txt | |
| # Run server | |
| python app.py | |
| ``` | |
| Server akan berjalan di `http://localhost:5000` | |
| ## π Integrasi dengan Aplikasi Web | |
| Setelah API ter-deploy, tambahkan URL API ke Supabase Edge Function: | |
| ### Via Supabase Dashboard: | |
| 1. Buka Supabase Dashboard | |
| 2. Pilih Project Anda | |
| 3. Pergi ke **Edge Functions** β **classify-seedling** | |
| 4. Klik **Secrets/Environment Variables** | |
| 5. Tambahkan secret baru: | |
| - Name: `PYTHON_API_URL` | |
| - Value: `https://your-api-url.com` (URL API yang sudah di-deploy) | |
| ### Via CLI (jika menggunakan Supabase CLI): | |
| ```bash | |
| supabase secrets set PYTHON_API_URL=https://your-api-url.com | |
| ``` | |
| ## π‘ API Endpoints | |
| ### 1. Health Check | |
| ```bash | |
| GET /health | |
| ``` | |
| Response: | |
| ```json | |
| { | |
| "status": "healthy", | |
| "model_loaded": true, | |
| "device": "cpu", | |
| "classes": ["3 Bulan", "6 Bulan", "9 Bulan"] | |
| } | |
| ``` | |
| ### 2. Classify Image | |
| ```bash | |
| POST /classify | |
| Content-Type: application/json | |
| { | |
| "image": "data:image/jpeg;base64,/9j/4AAQ..." | |
| } | |
| ``` | |
| Response: | |
| ```json | |
| { | |
| "predicted_class": "6 Bulan", | |
| "confidence": 0.8543, | |
| "probabilities": { | |
| "3 Bulan": 0.0812, | |
| "6 Bulan": 0.8543, | |
| "9 Bulan": 0.0645 | |
| }, | |
| "mode": "real", | |
| "saved_to_db": true, | |
| "id": "uuid-here" | |
| } | |
| ``` | |
| ### 3. Reload Model | |
| ```bash | |
| POST /reload-model | |
| ``` | |
| Digunakan jika Anda mengupdate model tanpa restart server. | |
| ## π§ͺ Testing API | |
| ### Test dengan cURL: | |
| ```bash | |
| # Health check | |
| curl https://your-api-url.com/health | |
| # Classify (dengan base64 image) | |
| curl -X POST https://your-api-url.com/classify \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"image": "data:image/jpeg;base64,YOUR_BASE64_IMAGE_HERE"}' | |
| ``` | |
| ### Test dengan Python: | |
| ```python | |
| import requests | |
| import base64 | |
| # Read image | |
| with open('bibit.jpg', 'rb') as f: | |
| img_data = base64.b64encode(f.read()).decode() | |
| # Send request | |
| response = requests.post( | |
| 'https://your-api-url.com/classify', | |
| json={'image': f'data:image/jpeg;base64,{img_data}'} | |
| ) | |
| print(response.json()) | |
| ``` | |
| ## π Troubleshooting | |
| ### Model tidak ditemukan | |
| ``` | |
| β Model file not found at models/svm_densenet201_rbf.joblib | |
| Using simulation mode until model is uploaded | |
| ``` | |
| **Solusi:** Pastikan file `svm_densenet201_rbf.joblib` ada di folder `models/` | |
| ### Error saat load model | |
| ``` | |
| Error loading model: ... | |
| ``` | |
| **Solusi:** | |
| - Pastikan versi scikit-learn sama dengan yang digunakan saat training | |
| - Cek apakah file model tidak corrupt | |
| - Pastikan format file adalah `.joblib` | |
| ### API timeout | |
| **Solusi:** | |
| - Tingkatkan timeout di Dockerfile (sudah diset 120 detik) | |
| - Untuk Cloud Run, set `--timeout 300` | |
| ### Memory error | |
| **Solusi:** | |
| - Upgrade instance ke memory lebih besar | |
| - Untuk Cloud Run: `--memory 2Gi` | |
| - Untuk Hugging Face: Upgrade ke Space berbayar | |
| ## π Mode Operasi | |
| API memiliki 2 mode: | |
| 1. **Real Mode** - Menggunakan model asli Anda | |
| - Response: `"mode": "real"` | |
| - Memerlukan file model di folder `models/` | |
| 2. **Simulation Mode** - Menggunakan random prediction | |
| - Response: `"mode": "simulation"` | |
| - Aktif jika model belum diupload | |
| - Berguna untuk testing integrasi | |
| ## π Security Notes | |
| - API ini tidak memerlukan authentication (sesuai design untuk demo) | |
| - Jika ingin menambah security, tambahkan API key di header | |
| - Untuk production, pertimbangkan rate limiting | |
| ## π‘ Tips | |
| 1. **Monitoring**: Cek logs untuk melihat performa model | |
| 2. **Update Model**: Upload model baru dan panggil `/reload-model` | |
| 3. **Scaling**: Gunakan multiple workers di gunicorn untuk handle traffic tinggi | |
| 4. **Caching**: Pertimbangkan caching untuk request yang sama | |
| ## π Support | |
| Jika ada masalah, cek: | |
| 1. Logs dari platform deployment Anda | |
| 2. Response dari `/health` endpoint | |
| 3. Pastikan semua dependencies terinstall dengan benar | |