Section sebelumnya ditutup dengan kode yang sudah aman: pipeline, transformasi, dan metrik dilindungi oleh pytest pada Chapter Testing untuk Kode Machine Learning. Akan tetapi, model yang menetap di notebook belum menghasilkan nilai apa pun — prediksinya baru berguna ketika bisa diakses sistem lain secara teratur, terkendali, dan dapat dipulihkan ketika terjadi masalah. Chapter ini membahas keputusan paling mendasar dalam deployment: bagaimana prediksi disajikan — massal sekali semalam, sewaktu-waktu lewat API, mengalir per kejadian, atau berjalan langsung di perangkat pengguna. Keputusan tersebut menentukan biaya infrastruktur, batas latensi, dan bentuk monitoring jauh sebelum baris kode serving pertama ditulis.
Dari Notebook ke Produksi #
Notebook dirancang untuk eksplorasi: sel memuat data, melatih model, lalu menampilkan hasil dalam satu sesi yang manusiawi. Produksi membalik asumsi tersebut — sesi berjalan berbulan-bulan, permintaan datang dari mesin, dan tidak ada manusia yang mengawasi setiap prediksi. Jembatan antara keduanya adalah artefak model: berkas hasil serialisasi yang memuat pipeline terlatih secara utuh (algoritme, bobot, fitted parameters, dan langkah preprocessing). Dengan joblib, sebuah Pipeline scikit-learn yang sudah dilatih dapat disimpan ke satu berkas dan dimuat kembali di proses lain, siap dipanggil predict().
Masalahnya, artefak tidak berdiri sendiri. Sebuah model produksi sebenarnya adalah gabungan tiga hal yang harus berversi bersamaan:
- Kode — versi scikit-learn, versi Python, dan setiap transformer kustom yang dirujuk pipeline.
- Data — snapshot data pelatihan yang menghasilkan bobot tersebut, beserta metrik validasinya.
- Environment — daftar dependensi tempat artefak dilatih dan akan dimuat.
Ketiga komponen inilah yang sering disebut masalah versioning model. Pipeline hasil joblib.dump() menyimpan referensi ke kelas Python; memuat artefak tersebut dengan versi pustaka yang berbeda dapat gagal, atau lebih buruk: berhasil dimuat tetapi menghasilkan prediksi yang berbeda secara halus. Karena itu, praktik industri menyimpan artefak bersama metadata (versi pustaka, tanggal pelatihan, metrik, hash data) di satu tempat terpusat yang biasa disebut model registry. Di lingkungan Course kita belum memasang alat registry seperti MLflow, jadi konsepnya cukup dipahami: setiap artefak yang beredar harus bisa ditelusuri kembali ke kode, data, dan environment yang menghasilkannya.
Empat Mode Menyajikan Prediksi #
Sebelum membahas teknologi serving, kita perlu memilih pola penyajian. Empat mode berikut menutup hampir semua kebutuhan nyata:
| Mode | Pola pemanggilan | Latensi khas | Karakter volume | Titik biaya utama | Contoh |
|---|---|---|---|---|---|
| Batch terjadwal | Sekali semalam/minggu, jutaan baris sekaligus | Menit–jam per proses | Sangat besar per proses | Mesin besar sesaat | Skor kredit bulanan, perkiraan permintaan |
| API real-time | Satu permintaan = satu prediksi | Di bawah 1 detik | Sedang, datang kapan saja | Server yang selalu siap | Rekomendasi di halaman checkout |
| Streaming | Per kejadian dari antrean pesan | Milidetik–detik | Sangat tinggi, mengalir terus | Kluster pemroses pesan | Penilaian transaksi saat pembayaran |
| Edge/on-device | Di perangkat pengguna, bisa luring | Milidetik, tanpa jaringan | Tersebar di jutaan perangkat | Pengembangan dan pembaruan aplikasi | Autokoreksi papan ketik ponsel |
Tabel tersebut pada dasarnya memetakan tiga sumbu pertukaran: latensi, throughput, dan biaya. Mode batch paling murah per prediksi karena perangkat hanya menyala sesaat, tetapi tidak bisa menjawab permintaan interaktif. Mode API memberi jawaban seketika dengan biaya server yang menyala terus, dan throughputnya dibatasi kapasitas server tersebut. Mode streaming menyerap volume sangat tinggi dengan menjawab per kejadian, tetapi menuntut infrastruktur antrean pesan yang berjalan tanpa henti. Mode edge memindahkan biaya ke proses pengembangan: model harus cukup ringkas untuk perangkat dan pembaruannya menumpang rilis aplikasi — imbalannya, data pengguna tidak perlu meninggalkan perangkat.
Memilih Mode dari Anggaran Latensi dan Volume #
Pemilihan mode tidak perlu jadi perdebatan arsitektur yang panjang; cukup turunkan dari dua angka yang sudah dimiliki tiap pemangku kebutuhan: anggaran latensi maksimum (berapa lama pengguna bersedia menunggu jawaban) dan volume prediksi per hari. Ditambah satu pertanyaan: apakah prediksi harus dihitung di perangkat pengguna karena jaringan atau privasi? Skrip berikut memetakan enam kasus penggunaan menjadi rekomendasi mode dengan aturan berurutan yang sederhana.
# Memetakan kebutuhan bisnis ke mode deployment dengan aturan berurutan.
# Skrip ini tidak melatih model apa pun: fokusnya adalah keputusan arsitektur
# yang diambil dari anggaran latensi, volume harian, dan lokasi eksekusi.
KASUS_PENGGUNAAN = [
{
"nama": "Skor kredit pembaruan bulanan",
"latensi_teks": "12 jam",
"latensi_maks_ms": 43_200_000,
"volume_harian": 800_000,
"di_perangkat": False,
},
{
"nama": "Perkiraan permintaan produk mingguan",
"latensi_teks": "24 jam",
"latensi_maks_ms": 86_400_000,
"volume_harian": 5_000,
"di_perangkat": False,
},
{
"nama": "Rekomendasi produk di halaman checkout",
"latensi_teks": "500 ms",
"latensi_maks_ms": 500,
"volume_harian": 60_000,
"di_perangkat": False,
},
{
"nama": "Penilaian transaksi tidak wajar saat pembayaran",
"latensi_teks": "300 ms",
"latensi_maks_ms": 300,
"volume_harian": 2_500_000,
"di_perangkat": False,
},
{
"nama": "Autokoreksi ketikan di papan ketik ponsel",
"latensi_teks": "50 ms",
"latensi_maks_ms": 50,
"volume_harian": 10_000_000,
"di_perangkat": True,
},
{
"nama": "Deteksi objek pada foto yang diunggah pengguna",
"latensi_teks": "2 detik",
"latensi_maks_ms": 2_000,
"volume_harian": 300_000,
"di_perangkat": False,
},
]
def rekomendasi_mode(kasus):
"""Aturan dievaluasi berurutan; cabang pertama yang terpenuhi menang."""
if kasus["latensi_maks_ms"] >= 3_600_000:
return "batch terjadwal"
if kasus["di_perangkat"]:
return "edge/on-device"
if kasus["volume_harian"] > 1_000_000:
return "streaming"
return "API real-time"
def format_volume(volume):
return f"{volume:,}".replace(",", ".")
print(f"{'Kasus penggunaan':<48} {'Latensi maks':<12} "
f"{'Volume/hari':>12} {'Perangkat':>9} Mode")
print("-" * 106)
hasil = []
for kasus in KASUS_PENGGUNAAN:
mode = rekomendasi_mode(kasus)
hasil.append(mode)
perangkat = "ya" if kasus["di_perangkat"] else "tidak"
print(f"{kasus['nama']:<48} {kasus['latensi_teks']:<12} "
f"{format_volume(kasus['volume_harian']):>12} {perangkat:>9} {mode}")
print()
print("Rekap mode yang direkomendasikan:")
for mode in sorted(set(hasil)):
print(f" {mode:<16} {hasil.count(mode)} kasus")Output yang Dihasilkan:
Kasus penggunaan Latensi maks Volume/hari Perangkat Mode
----------------------------------------------------------------------------------------------------------
Skor kredit pembaruan bulanan 12 jam 800.000 tidak batch terjadwal
Perkiraan permintaan produk mingguan 24 jam 5.000 tidak batch terjadwal
Rekomendasi produk di halaman checkout 500 ms 60.000 tidak API real-time
Penilaian transaksi tidak wajar saat pembayaran 300 ms 2.500.000 tidak streaming
Autokoreksi ketikan di papan ketik ponsel 50 ms 10.000.000 ya edge/on-device
Deteksi objek pada foto yang diunggah pengguna 2 detik 300.000 tidak API real-time
Rekap mode yang direkomendasikan:
API real-time 2 kasus
batch terjadwal 2 kasus
edge/on-device 1 kasus
streaming 1 kasusMari kita telaah baris-baris kode yang berperan penting:
- Baris 5–48 (
KASUS_PENGGUNAAN): enam kasus penggunaan dinyatakan sebagai data — bukan opini. Setiap kasus membawa tiga atribut keputusan:latensi_maks_ms(anggaran waktu jawab dalam milidetik),volume_harian(jumlah prediksi per hari), dandi_perangkat(apakah prediksi wajib dihitung di perangkat pengguna). - Baris 51–59 (
def rekomendasi_mode): aturan dievaluasi berurutan dan cabang pertama yang terpenuhi menang. Urutannya disengaja: kasus dengan anggaran longgar (≥ 1 jam) langsung jatuh ke batch apa pun volumenya, karena tidak ada alasan membayar infrastruktur interaktif ketika pengguna bersedia menunggu semalam. Setelah itu perangkat pengguna menang atas pertimbangan lain, lalu volume sangat tinggi (> 1.000.000 per hari) memaksa mode streaming, dan sisanya cukup dilayani API real-time. - Baris 62–63 (
def format_volume):f"{volume:,}"menghasilkan pemisah ribuan bergaya Inggris (2,500,000); pemanggilan.replace(",", ".")mengubahnya ke konvensi Indonesia (2.500.000) agar tabel konsisten dengan prosa. - Baris 70–76 (loop utama): setiap kasus dipetakan fungsi
rekomendasi_mode, mode direkam ke daftarhasil, lalu satu baris tabel dicetak dengan lebar kolom tetap (:<48,:>12) supaya kolomnya sejajar. - Baris 80–81 (rekap):
sorted(set(hasil))mengurutkan mode unik secara alfabetis sehingga rekap selalu tercetak dalam urutan yang sama, laluhasil.count(mode)menghitung jumlah kasus per mode.
Perhatikan hasilnya: kasus penilaian transaksi dan autokoreksi sama-sama menuntut jawaban di bawah satu detik, tetapi terpisah ke dua mode berbeda karena perbedaan di mana jawaban harus dihitung. Sebaliknya, skor kredit dan perkiraan permintaan sama-sama jatuh ke batch meskipun volumenya berbeda tiga besar — anggaran latensi yang longgar menyatukan keduanya. Tabel kecil ini menunjukkan bahwa keputusan deployment memang bisa direduksi menjadi data dan aturan, bukan perdebatan selera.
Strategi Rilis Bertahap #
Memilih mode serving menyelesaikan pertanyaan “bagaimana prediksi disajikan”; pertanyaan kedua adalah “bagaimana model baru menggantikan model lama dengan aman”. Pergantian model selalu membawa risiko: model baru mungkin lebih baik pada data validasi historis tetapi menurun pada trafik nyata. Tiga strategi rilis bertahap menjadi standar industri:
| Strategi | Mekanisme | Trafik model baru | Keunggulan utama | Kebutuhan infrastruktur |
|---|---|---|---|---|
| Shadow deployment | Model baru menerima salinan permintaan; hasil dibandingkan di latar belakang tanpa memengaruhi pengguna | 0% keputusan nyata | Kalibrasi pada data nyata tanpa risiko | Jalur inferensi ganda |
| Canary | Sebagian kecil trafik diarahkan ke model baru, diperbesar bertahap jika metrik sehat | 1–20%, bertahap | Masalah terdeteksi pada skala kecil | Pembagi trafik dan metrik per versi |
| Blue-green | Dua lingkungan utuh; perpindahan dilakukan sekaligus dan bisa dibalik cepat | 0% → 100% | Peralihan seragam dan mundur seketika | Kapasitas dua lingkungan penuh |
Ketiganya berbagi satu prinsip: jangan pernah mengganti model tanpa kemampuan mundur. Pada mode shadow, keputusan pengguna sepenuhnya tetap di tangan model lama sampai bukti terkumpul. Mode canary menukar sebagian kecil trafik sehingga dampak kesalahan terbatas secara matematis. Mode blue-green mempertahankan lingkungan lama tetap siap sehingga pemulihan hanya berarti mengembalikan penunjuk trafik. Strategi mana yang dipilih bergantung pada biaya kesalahan satu prediksi: makin mahal konsekuensi keputusan, makin awal investasi pada shadow dan canary.
Dari keempat mode penyajian, API real-time adalah pintu masuk yang paling instruktif untuk dipraktikkan: seluruh komponennya (validasi masukan, artefak, pengujian) dapat dibangun dan diuji dalam satu proses Python. Itulah materi Chapter Model Serving dengan FastAPI, tempat kita merakit API prediksi lengkap — dari skema Pydantic hingga uji TestClient — tanpa satu pun server nyata.
Referensi Resmi #
- Model persistence — scikit-learn — panduan resmi penyimpanan dan pemuatan model, termasuk peringatan kompatibilitas antarversi pustaka.
- joblib — Persistence
— dokumentasi resmi mekanisme
dump/loadyang dipakai untuk artefak pipeline.