Spaces:
Sleeping
title: MPG Highway API
emoji: π
colorFrom: green
colorTo: blue
sdk: docker
app_port: 7860
π MPG Highway API: R MLOps dengan Vetiver, Pins, dan Plumber
REST API menggunakan R Plumber untuk prediksi efisiensi bahan bakar.
Sistem deployment dan monitoring untuk model machine learning R menggunakan tidymodels, vetiver, pins, dan plumber.
Proyek ini adalah sistem monitoring performa model Machine Learning (menggunakan dataset mpg untuk memprediksi efisiensi bahan bakar) secara real-time. Proyek ini mencakup API inferensi, pencatatan log data batch ke database, serta visualisasi data drift dan performa menggunakan Shiny dan echarts4r.
β Status Proyek: Migrasi database ke PostgreSQL (Supabase) Selesai & Stabil.
π Fitur Utama
- β Model Versioning: Menggunakan Vetiver dan Pins untuk manajemen siklus hidup model.
- β Cloud Logging: Pencatatan log prediksi otomatis ke Supabase Cloud.
- β Actuals Ingestion: Sinkronisasi data aktual lapangan dengan log prediksi menggunakan Composite Primary Key.
- β
Secure Credentials: Manajemen akses database yang aman menggunakan file
.envdan paketdotenv. - β Monitoring Dashboard: Shiny dashboard yang menarik data secara real-time langsung dari PostgreSQL.
- β
PostgreSQL Optimized: Implementasi kueri yang dioptimalkan untuk dialek Postgres (
ON CONFLICT,$1placeholders).
π οΈ Requirements
Proyek ini menggunakan renv untuk manajemen package. Sebelum memulai, pastikan Anda telah merestorasi environment dengan membuka R di folder ini dan menjalankan:
renv::restore()
π Struktur File
.
βββ 01_train_and_version.R # Training dan versioning model
βββ 02_api_plumber.R # API dengan monitoring & DB Logging
βββ 03_run_server.R # Jalankan API Server local
βββ 04_test_client.R # Test API Server local
βββ 05_monitoring_dashboard.R # Shiny dashboard monitoring
βββ 07_ab_testing.R # Review champion dan challenger model
βββ 08_ingest_actuals.R # Script untuk memasukkan data aktual
βββ simulasi_prediksi.R # Script untuk memasukkan log data prediksi
βββ Makefile # Otomatisasi perintah terminal
βββ Dockerfile # Docker image
βββ docker-compose.yml # Docker orchestration
βββ models/ # Model storage & train stats
ποΈ Skema Database (Supabase SQL)
Jalankan kueri ini di SQL Editor Supabase Anda untuk menyiapkan tabel di skema mlops:
CREATE SCHEMA IF NOT EXISTS mlops;
-- Tabel untuk Log Prediksi
CREATE TABLE mlops.predictions (
request_id TEXT,
row_id TEXT,
variant TEXT,
version TEXT,
input_features JSONB,
predicted_value NUMERIC,
status TEXT,
error_message TEXT,
timestamp TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (request_id, row_id)
);
-- Tabel untuk Data Aktual
CREATE TABLE mlops.actuals (
request_id TEXT,
row_id TEXT,
actual_value NUMERIC,
logged_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (request_id, row_id)
);
β οΈ Catatan Penting Implementasi
1. Dialek PostgreSQL vs SQLite
Jangan gunakan sintaks SQLite seperti INSERT OR IGNORE. Proyek ini menggunakan standar PostgreSQL:
- Placeholder: Menggunakan
$1, $2, ...(bukan?). - Conflict Handling: Menggunakan
ON CONFLICT (request_id, row_id) DO NOTHING.
2. Database Connection
Koneksi database dipusatkan di 00_db_helper.R. Selalu gunakan DBI::dbExecute(con, "SET search_path TO mlops") setelah membuka koneksi untuk memastikan kueri mengarah ke skema yang benar.
3. Permission
Jika terjadi error Permission Denied, pastikan user database memiliki hak akses penuh ke skema mlops:
GRANT USAGE ON SCHEMA mlops TO authenticated;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA mlops TO authenticated;
π Quick Start
1. Training dan Versioning Model
source("01_train_and_version.R")
Output:
- Model tersimpan di
models/dengan versioning - Training statistics untuk drift detection
- Metadata model (RMSE, RΒ², dll)
2. Jalankan API Server
source("03_run_server.R")
API akan berjalan di http://localhost:8000 dengan endpoints:
GET /ping- Health checkGET /metadata- Model metadataGET /prototype- Akses data prototypePOST /predict- Standard predictionPOST /predict_custom- Custom post-prediction
3. Test API
source("04_test_client.R")
4. Jalankan Monitoring Dashboard
shiny::runApp("05_monitoring_dashboard.R")
Dashboard akan berjalan di http://localhost:7667
π API Usage
Custom Batch Prediction (Mengirim JSON Fitur & Auto-Log)
curl -X POST "http://localhost:8000/predict_custom" \
-H "Content-Type: application/json" \
-d '[
{
"row_id": "client_id_1",
"displ": 2.4,
"year": 2008,
"cyl": 4,
"class": "compact"
},
{"row_id":"client_id_A", "displ":2.0,"year":2008,"cyl":4,"class":"compact"},
{"row_id":"client_id_B", "displ":5.0,"year":2008,"cyl":8,"class":"suv"}
]'
Response:
{
"request_id": "REQ-260403101334-2334",
"results": [
{
"row_id": "client_id_1",
"prediction": 29.3853
},
{
"row_id": "client_id_A",
"prediction": 29.1273
},
{
"row_id": "client_id_B",
"prediction": 17.4506
}
]
}
π Monitoring Dashboard
Dashboard menyediakan:
Performance Tab
- Trend prediksi over time
- Distribusi prediksi
- Performance metrics
Data Drift Tab
- Z-score chart untuk setiap feature
- Drift detection table
- Alert jika ada drift
Prediction Logs Tab
- Tabel semua prediksi
- Filter dan search
Feature Distributions Tab
- Perbandingan distribusi training vs production
- Untuk setiap feature
π³ Docker Deployment
Build dan Run
# Build image
docker build -t ml-api .
# Run container
docker run -p 8000:8000 -v $(pwd)/models:/app/models -v $(pwd)/logs:/app/logs ml-api
Menggunakan Docker Compose
docker-compose up -d
Untuk stop:
docker-compose down
π Drift Detection
Sistem mendeteksi drift dengan cara:
- Statistical Drift: Membandingkan distribusi feature production vs training menggunakan Z-score
- Threshold: Z-score > 2 dianggap sebagai drift
- Features Monitored: Semua numerical features (displ, year, cyl)
Formula Z-score:
z = |recent_mean - train_mean| / train_sd
π Performance Monitoring
Metrics yang dimonitor:
- Prediction Statistics: mean, median, SD, min, max
- Input Statistics: distribusi input features
- Volume: jumlah prediksi per window
- Trend: perubahan prediksi over time
π Model Update Workflow
- Train model baru dengan data terbaru
- Version model dengan vetiver
- Pin model baru ke board
- Restart API server
- API otomatis load model versi terbaru
- Monitor performance dan drift
# Update model
source("01_train_and_version.R")
# Restart API (model akan auto-load versi terbaru)
source("03_run_server.R")
π― Best Practices
1. Monitoring Window Size
- Small window (50-100): Deteksi drift lebih cepat, tapi lebih sensitif
- Large window (500-1000): Lebih stabil, tapi deteksi drift lebih lambat
2. Drift Threshold
- Threshold = 2: Standard (95% confidence)
- Threshold = 3: Lebih konservatif (99.7% confidence)
3. Log Management
Pembersihan Log Berkala (Pindah ke SQLite) Karena data log saat ini disimpan di SQLite, Anda dapat membersihkan log lama (misal menyisakan 10.000 data terakhir) dengan kueri SQL berikut agar database tidak terlalu bengkak:
con <- DBI::dbConnect(RSQLite::SQLite(), "logs/model_monitoring.sqlite")
DBI::dbExecute(con, "
DELETE FROM predictions
WHERE id NOT IN (SELECT id FROM predictions ORDER BY timestamp DESC LIMIT 10000)
")
DBI::dbDisconnect(con)
4. Model Retraining Triggers
Retrain model jika:
- Drift terdeteksi pada multiple features
- Performance degradation signifikan
- Data pattern berubah
- Scheduled retraining (e.g., monthly)
π Production Considerations
1. Authentication
Tambahkan authentication di Plumber:
#* @filter auth
function(req, res) {
if (is.null(req$HTTP_AUTHORIZATION)) {
res$status <- 401
return(list(error = "Unauthorized"))
}
plumber::forward()
}
2. Rate Limiting
#* @filter ratelimit
function(req, res) {
# Implement rate limiting logic
plumber::forward()
}
3. Logging
Gunakan logger package:
library(logger)
log_info("Prediction request from {req$REMOTE_ADDR}")
4. Error Handling
tryCatch({
prediction <- predict(v, input_data)
}, error = function(e) {
log_error("Prediction error: {e$message}")
return(list(error = "Prediction failed"))
})
π Advanced Pins Boards
S3 Board (AWS)
library(pins)
board <- board_s3(
bucket = "my-models",
region = "us-east-1"
)
vetiver_pin_write(board, v)
RStudio Connect
board <- board_connect(
server = "https://connect.example.com",
key = Sys.getenv("CONNECT_API_KEY")
)
vetiver_pin_write(board, v)
Azure Blob
board <- board_azure(
container = "models",
account = "myaccount",
key = Sys.getenv("AZURE_STORAGE_KEY")
)
π Troubleshooting
Model tidak load
# Check pins board
board <- board_folder("models")
pin_list(board)
pin_versions(board, "mpg_highway_model")
# Read model manually
v <- vetiver_pin_read(board, "mpg_highway_model")
API error 500
# Check logs
source("02_api_plumber.R")
api %>%
pr_run(
host = "0.0.0.0",
port = 8000,
debug = TRUE) # Enable debug mode
Drift false positives
# Adjust threshold
threshold <- 3 # More conservative
# Or increase window size
window <- 500
π Resources
π€ Contributing
Silakan customize sesuai kebutuhan project Anda:
- Ganti dataset dengan data Anda
- Modifikasi recipe dan model sesuai use case
- Tambahkan metrics monitoring spesifik
- Implementasi alerting (email, Slack, dll)
π License
MIT License - feel free to use and modify