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:

ModePola pemanggilanLatensi khasKarakter volumeTitik biaya utamaContoh
Batch terjadwalSekali semalam/minggu, jutaan baris sekaligusMenit–jam per prosesSangat besar per prosesMesin besar sesaatSkor kredit bulanan, perkiraan permintaan
API real-timeSatu permintaan = satu prediksiDi bawah 1 detikSedang, datang kapan sajaServer yang selalu siapRekomendasi di halaman checkout
StreamingPer kejadian dari antrean pesanMilidetik–detikSangat tinggi, mengalir terusKluster pemroses pesanPenilaian transaksi saat pembayaran
Edge/on-deviceDi perangkat pengguna, bisa luringMilidetik, tanpa jaringanTersebar di jutaan perangkatPengembangan dan pembaruan aplikasiAutokoreksi 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.

python
# 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:

text
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 kasus

Mari kita telaah baris-baris kode yang berperan penting:

  1. 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), dan di_perangkat (apakah prediksi wajib dihitung di perangkat pengguna).
  2. 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.
  3. 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.
  4. Baris 70–76 (loop utama): setiap kasus dipetakan fungsi rekomendasi_mode, mode direkam ke daftar hasil, lalu satu baris tabel dicetak dengan lebar kolom tetap (:<48, :>12) supaya kolomnya sejajar.
  5. Baris 80–81 (rekap): sorted(set(hasil)) mengurutkan mode unik secara alfabetis sehingga rekap selalu tercetak dalam urutan yang sama, lalu hasil.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:

StrategiMekanismeTrafik model baruKeunggulan utamaKebutuhan infrastruktur
Shadow deploymentModel baru menerima salinan permintaan; hasil dibandingkan di latar belakang tanpa memengaruhi pengguna0% keputusan nyataKalibrasi pada data nyata tanpa risikoJalur inferensi ganda
CanarySebagian kecil trafik diarahkan ke model baru, diperbesar bertahap jika metrik sehat1–20%, bertahapMasalah terdeteksi pada skala kecilPembagi trafik dan metrik per versi
Blue-greenDua lingkungan utuh; perpindahan dilakukan sekaligus dan bisa dibalik cepat0% → 100%Peralihan seragam dan mundur seketikaKapasitas 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 #