CI/CD model biologi harus memperlakukan dataset, kode, konfigurasi, bobot, dan lingkungan runtime sebagai satu unit rilis yang tidak dapat dipisahkan. Pipeline yang hanya menguji kode atau membuat container belum cukup: model dapat lolos deployment tetapi menghasilkan keluaran berbeda akibat dataset berubah, bobot tertukar, dependensi bergeser, atau perangkat keras menjalankan kernel numerik yang berbeda.
Rilis world model untuk biologi protein dari Biohub memberi konteks mengapa kebutuhan engineering ini muncul. Ketika ukuran model, cakupan data, dan biaya komputasi membesar, pelatihan ulang pada setiap commit tidak realistis. Solusinya adalah pipeline berlapis yang melakukan pemeriksaan murah di pull request, memvalidasi artefak secara menyeluruh saat membuat kandidat rilis, lalu mempromosikan artefak yang sama dari staging ke produksi.
Menentukan unit rilis yang dapat direproduksi
Dalam aplikasi biasa, commit Git dan container image sering dianggap cukup untuk mengidentifikasi rilis. Model biologi membutuhkan identitas yang lebih lengkap. Setiap rilis sekurang-kurangnya harus mengunci empat komponen berikut:
- Dataset: snapshot data mentah, hasil transformasi, pembagian train-validation-test, serta kode atau parameter preprocessing.
- Kode: commit Git yang menjalankan preprocessing, pelatihan, evaluasi, dan inferensi.
- Konfigurasi: arsitektur, tokenizer atau featurizer, parameter inferensi, dan kebijakan evaluasi.
- Bobot model: checkpoint final beserta checksum dan format serialisasinya.
Tambahkan identitas container, lockfile dependensi, dan laporan benchmark agar hasil dapat ditelusuri sampai ke lingkungan eksekusinya. Gunakan identifier berbasis konten, seperti SHA-256, untuk artefak immutable. Nomor versi semantik tetap berguna bagi manusia, tetapi tidak menggantikan digest.
Tag seperti model-latest boleh digunakan sebagai pointer, bukan sebagai sumber kebenaran. Manifest rilis harus menunjuk digest yang immutable.
Manifest rilis
Simpan sebuah manifest yang menghubungkan semua komponen. Contoh berikut bersifat konseptual; nama field dapat disesuaikan dengan sistem penyimpanan tim.
release_id: protein-model-2025-03-rc1
code:
git_commit: 7d3f...
data:
snapshot_uri: s3://biology-artifacts/datasets/protein-v17/manifest.json
manifest_sha256: a42c...
schema_version: protein-input-v3
config:
uri: s3://biology-artifacts/configs/inference-v8.yaml
sha256: 62be...
weights:
uri: s3://biology-artifacts/models/protein-v8/model.safetensors
sha256: 90af...
runtime:
container_digest: registry.example.org/bio/model@sha256:17bc...
dependency_lock_sha256: 1ca9...
evaluation:
benchmark_report_uri: s3://biology-artifacts/reports/protein-v8.json
policy_version: release-policy-v4
Manifest itu sendiri perlu diberi checksum dan, untuk rantai pasok yang lebih ketat, ditandatangani. Jangan mengandalkan ETag object storage sebagai checksum universal karena nilainya tidak selalu sama dengan hash isi, terutama pada unggahan multipart.
Versioning dataset tanpa menduplikasi semuanya
Dataset besar dapat dikelola dengan DVC, lakeFS, katalog internal, atau manifest immutable di object storage. Pilihan alat tidak mengubah prinsip dasarnya:
- Data mentah bersifat append-only atau disimpan sebagai snapshot immutable.
- Setiap objek memiliki checksum, ukuran, format, dan lokasi penyimpanan.
- Transformasi data diidentifikasi oleh commit kode dan hash konfigurasi.
- ID sampel pada setiap split disimpan, bukan dibuat ulang secara acak saat evaluasi.
- Manifest mencatat data yang dikeluarkan, dideduplikasi, atau dikoreksi.
- Hak akses, lisensi, kebijakan retensi, dan batas penggunaan data dicatat terpisah dari container.
Pembekuan split sangat penting untuk mencegah kebocoran evaluasi. Jika benchmark diperbarui, perlakukan perubahan tersebut sebagai versi benchmark baru; jangan menimpa hasil lama seolah-olah masih dapat dibandingkan langsung.
Struktur repositori untuk pipeline model
Pisahkan kode runtime, konfigurasi, kontrak data, dan kebijakan rilis. File besar tidak perlu dimasukkan ke Git; repositori cukup menyimpan manifest dan referensi immutable.
biology-model/
├── src/
│ ├── preprocessing/
│ ├── inference/
│ └── evaluation/
├── schemas/
│ ├── protein-input-v3.json
│ └── prediction-output-v2.json
├── configs/
│ ├── train.yaml
│ ├── inference.yaml
│ └── benchmark-policy.yaml
├── tests/
│ ├── fixtures/
│ ├── test_schema.py
│ ├── test_smoke_inference.py
│ └── test_reproducibility.py
├── benchmarks/
│ ├── dataset-manifest.json
│ └── evaluate.py
├── releases/
│ └── manifest-template.yaml
├── containers/
│ └── Dockerfile
├── scripts/
│ ├── fetch_artifact.py
│ ├── verify_manifest.py
│ └── promote_release.py
└── dependency.lock
Fixture untuk CI sebaiknya kecil, legal untuk disimpan, dan mewakili kasus penting: input minimum, panjang maksimum yang didukung, residu atau token tidak dikenal, masking, serta batch dengan panjang bervariasi. Fixture ini bukan pengganti benchmark penuh.
Validasi artefak dan kontrak input
Validasi kandidat rilis harus mengikuti urutan yang memudahkan diagnosis. Periksa manifest dan checksum sebelum memuat model; periksa skema input sebelum menjalankan inferensi; kemudian validasi kontrak output.
Checksum dan pemeriksaan integritas
Unduh artefak ke file sementara, hitung SHA-256 selama proses streaming, lalu pindahkan secara atomik ke cache hanya jika hash cocok. Pendekatan ini mencegah proses lain menggunakan unduhan parsial.
sha256sum model.safetensors
# Bandingkan hasilnya dengan weights.sha256 dalam manifest rilis.
Checksum membuktikan bahwa byte sesuai dengan manifest, tetapi tidak membuktikan siapa yang menerbitkannya. Untuk menghadapi pemalsuan artefak, tambahkan signature pada manifest atau attestation dari sistem build. Kredensial object storage juga harus read-only pada job validasi dan dibatasi ke prefix yang diperlukan.
Validasi skema input
Validasi sebaiknya mencakup nama field, tipe data, dimensi, rentang nilai, satuan, dan hubungan antar-field. Contoh Python berikut memeriksa kontrak generik untuk input token protein dan attention mask:
import numpy as np
def validate_batch(path: str, max_length: int) -> tuple[np.ndarray, np.ndarray]:
batch = np.load(path, allow_pickle=False)
required = {"token_ids", "attention_mask"}
if not required.issubset(batch.files):
missing = required - set(batch.files)
raise ValueError(f"Field input hilang: {sorted(missing)}")
token_ids = batch["token_ids"]
mask = batch["attention_mask"]
if token_ids.dtype != np.int64:
raise TypeError(f"token_ids harus int64, ditemukan {token_ids.dtype}")
if token_ids.ndim != 2 or token_ids.shape != mask.shape:
raise ValueError("token_ids dan attention_mask harus berbentuk [batch, length]")
if token_ids.shape[1] > max_length:
raise ValueError("Panjang input melampaui konfigurasi model")
if not np.isin(mask, [0, 1]).all():
raise ValueError("attention_mask hanya boleh berisi 0 atau 1")
return token_ids, mask
Rentang token valid dan panjang maksimum jangan ditulis ulang di banyak tempat. Ambil nilai tersebut dari konfigurasi yang checksum-nya tercatat dalam manifest. Jika preprocessing menerima format biologis seperti FASTA, validasi format tekstual harus dilakukan sebelum tokenisasi, termasuk karakter yang diizinkan, entri kosong, dan batas ukuran.
Smoke test inferensi
Smoke test menjawab pertanyaan sederhana: dapatkah artefak dimuat dan menghasilkan output yang memenuhi kontrak? Gunakan satu atau beberapa fixture kecil agar tes cepat, lalu periksa:
- Bobot dapat dideserialisasi tanpa tensor hilang atau tidak cocok.
- Inferensi selesai tanpa kehabisan memori untuk ukuran input minimum.
- Shape, dtype, dan nama field output sesuai skema.
- Output tidak mengandung NaN atau infinity.
- Masking bekerja dan elemen padding tidak memengaruhi bagian output yang seharusnya valid.
- Metadata respons memuat ID rilis atau digest model yang benar.
Jangan menggunakan smoke test untuk menyatakan kualitas ilmiah. Model dapat menghasilkan tensor yang valid secara teknis tetapi mengalami regresi kualitas; karena itu dibutuhkan benchmark terpisah.
Uji reproduksibilitas dan quality gate
Membedakan determinisme dan toleransi numerik
Menetapkan seed membantu reproduksibilitas, tetapi tidak selalu membuat eksekusi identik pada seluruh perangkat keras. Paralelisme, urutan reduksi floating-point, kernel akselerator, dan algoritme non-deterministik dapat menghasilkan selisih kecil.
Gunakan dua kelas pengujian:
- Tes deterministik ketat untuk preprocessing, parsing, pemilihan split, dan operasi lain yang memang harus identik. Bandingkan hash atau byte output.
- Tes numerik bertoleransi untuk inferensi floating-point. Bandingkan dengan toleransi absolut dan relatif yang ditetapkan dari analisis domain, bukan angka acak.
actual = run_inference(model, fixture)
expected = load_reference_output()
np.testing.assert_allclose(
actual,
expected,
rtol=policy.relative_tolerance,
atol=policy.absolute_tolerance,
)
Catat perangkat, tipe numerik, runtime, dan mode inferensi yang digunakan untuk membuat output referensi. Jika implementasi memiliki mode deterministik, aktifkan pada tes referensi, tetapi tetap uji jalur produksi yang sebenarnya.
Menguji output stokastik
Model generatif atau sampler tidak tepat diuji dengan menuntut seluruh output sama persis. Untuk jalur dengan seed dan implementasi yang sama, tes dapat memeriksa replay deterministik sebagai pemeriksaan awal. Di luar itu, jalankan beberapa sampel dan nilai sifat distribusinya:
- Proporsi output yang lolos validasi biologis dan struktural.
- Rata-rata, kuantil, atau rentang metrik domain yang disetujui.
- Distribusi panjang, komposisi, atau confidence score.
- Perbedaan terhadap baseline beserta interval ketidakpastiannya.
Jumlah sampel, seed, metode statistik, dan batas kelulusan harus menjadi bagian dari kebijakan benchmark berversi. Sampel yang terlalu sedikit membuat gate tidak stabil; sampel terlalu banyak meningkatkan biaya dan waktu rilis.
Quality gate berbasis benchmark
Quality gate membandingkan kandidat dengan baseline produksi atau kandidat terakhir yang disetujui. Setiap metrik perlu mendefinisikan arah yang lebih baik, agregasi, kelompok data, dan batas regresi. Hindari hanya melihat skor global karena regresi pada subkelompok biologis dapat tertutup oleh rata-rata.
benchmark_policy:
baseline: current-production
required_slices:
- full_set
- short_sequences
- long_sequences
- held_out_families
metrics:
structural_quality:
direction: higher_is_better
regression_limit: from_approved_policy
invalid_output_rate:
direction: lower_is_better
regression_limit: from_approved_policy
require_complete_report: true
Nilai ambang harus ditentukan bersama pemilik ilmiah dan pemilik layanan berdasarkan variabilitas benchmark serta risiko penggunaan. Pipeline cukup mengimplementasikan kebijakan tersebut secara konsisten. Perubahan ambang wajib melalui review dan menghasilkan versi kebijakan baru.
Pisahkan gate menjadi dua tingkat: benchmark kecil untuk pull request dan benchmark penuh pada kandidat rilis. Jika benchmark penuh memerlukan akselerator mahal, jalankan hanya setelah validasi statis, unit test, checksum, dan smoke test lulus.
Provenance, dependensi, container, dan cache
Mencatat provenance
Provenance memungkinkan tim menjawab: artefak ini dibangun dari apa, oleh job mana, dan telah melewati pengujian apa? Catat informasi berikut dalam metadata rilis:
- Commit Git, status working tree, dan identitas pipeline.
- Digest dataset, bobot, konfigurasi, serta output preprocessing.
- Lockfile dependensi dan versi runtime utama.
- Jenis perangkat keras, driver, backend komputasi, serta tipe numerik.
- Perintah build dan evaluasi, seed, ID benchmark, dan laporan hasil.
- Digest container, SBOM, hasil pemindaian kerentanan, dan signature.
Format SBOM seperti SPDX atau CycloneDX dapat digunakan untuk inventaris dependensi. Untuk attestation rantai pasok, tim dapat mengadopsi format yang kompatibel dengan sistem build dan kebijakan organisasinya. Jangan menaruh token, URL bertanda tangan, atau data sensitif di provenance.
Container image sebagai runtime immutable
Container harus memuat kode inferensi dan dependensi runtime, tetapi tidak selalu perlu memuat bobot model yang sangat besar. Ada dua pola:
- Bobot di dalam image: deployment lebih mandiri dan atomik, tetapi image besar, distribusi lambat, serta duplikasi storage tinggi.
- Bobot di object storage: image lebih kecil dan dapat digunakan ulang, tetapi startup membutuhkan pengunduhan serta verifikasi checksum.
Untuk model besar, pola kedua biasanya lebih operasional selama init process mengunduh bobot berdasarkan digest, memverifikasi checksum, dan tidak menerima traffic sebelum model siap. Pin base image serta image produksi dengan digest. Lockfile saja belum menjamin kompatibilitas driver dan akselerator, sehingga staging perlu menggunakan kelas perangkat keras yang representatif.
Strategi cache artefak besar
Jangan menggunakan hash branch atau nama file sebagai cache key. Gunakan SHA-256 artefak agar dua job yang membutuhkan byte sama dapat berbagi cache dengan aman.
- Sediakan cache lokal persisten pada runner khusus akselerator.
- Gunakan object storage sebagai sumber kebenaran, bukan cache CI sementara.
- Unduh ke direktori sementara, verifikasi, lalu rename secara atomik.
- Pasang lock per digest agar beberapa job tidak mengunduh artefak yang sama.
- Terapkan eviction berbasis ukuran atau usia, tetapi lindungi artefak rilis aktif.
- Cache hasil preprocessing berdasarkan digest data, kode transformasi, dan konfigurasi.
- Jangan cache output ketika proses stokastik tidak memasukkan seed dan kebijakan sampler ke dalam key.
Cache yang gagal diverifikasi harus dihapus, bukan dicoba digunakan kembali. Log harus membedakan cache miss, checksum mismatch, kegagalan jaringan, dan kehabisan ruang disk agar diagnosis tidak berhenti pada pesan “gagal memuat model”.
Workflow CI/CD, promosi, dan rollback
Workflow berikut merupakan pseudocode lintas platform CI, bukan konfigurasi untuk vendor tertentu.
on pull_request:
validate_config_and_schemas
run_unit_tests
build_runtime_image
run_smoke_test_with_small_fixture
run_small_benchmark
on release_candidate:
resolve_immutable_manifest
verify_all_checksums
build_and_sign_image
generate_sbom
run_smoke_test_on_target_hardware
run_reproducibility_tests
run_full_benchmark
evaluate_release_policy
publish_candidate_manifest
deploy_exact_digests_to_staging
run_staging_integration_tests
require_approval
promote_manifest_to_production
monitor_and_record_release
Setiap job menerbitkan laporan mesin-terbaca dan ringkasan untuk reviewer. Job berikutnya harus mengonsumsi digest hasil job sebelumnya, bukan membangun ulang image atau mengambil tag yang dapat berubah.
Promosi staging ke produksi
Promosi tidak boleh melakukan training atau build ulang. Staging dan produksi harus menggunakan digest container, bobot, konfigurasi, dan skema yang sama. Perbedaan hanya boleh berada pada konfigurasi lingkungan seperti endpoint observability atau kapasitas replica.
Alur yang aman adalah:
- Daftarkan kandidat rilis dari manifest yang telah lolos gate.
- Deploy digest tersebut ke staging dengan kelas perangkat keras representatif.
- Jalankan tes kontrak API, input nyata yang telah disanitasi, serta uji beban terbatas.
- Promosikan dengan mengganti pointer rilis produksi secara transaksional.
- Gunakan canary atau shadow traffic jika risiko dan arsitektur layanan memerlukannya.
- Pantau error rate, latensi, penggunaan memori, invalid output, dan metrik kualitas yang dapat diamati.
Pastikan log tidak menyimpan sekuens biologis atau payload sensitif tanpa kebijakan yang jelas. Untuk shadow traffic, hasil model kandidat tidak boleh dikembalikan kepada pengguna sampai promosi selesai.
Rollback yang benar-benar dapat dijalankan
Rollback berarti mengembalikan pointer produksi ke manifest rilis sebelumnya, bukan mencari ulang bobot lama atau membangun image dari source. Pertahankan setidaknya artefak dari rilis aktif dan beberapa rilis sebelumnya sesuai kebijakan retensi.
Uji rollback secara berkala. Perhatikan kompatibilitas mundur pada skema API, cache fitur, dan format request. Jika rilis mengubah skema secara tidak kompatibel, gunakan strategi expand-and-contract atau jalankan dua versi endpoint selama masa transisi. Rollback model tidak akan menyelesaikan masalah jika migrasi data pendukung sudah menghapus format lama.
Kesalahan umum dan tips debugging
- Tag mutable dianggap versi: cari digest yang benar pada manifest dan registry.
- Checksum cocok tetapi output berubah: bandingkan konfigurasi, lockfile, hardware, driver, mode numerik, dan preprocessing.
- Tes stokastik sering gagal: periksa ukuran sampel, seed, fluktuasi statistik, dan apakah batas gate terlalu dekat dengan noise benchmark.
- Benchmark membaik secara tidak wajar: audit kebocoran split, duplikasi data, perubahan filtering, dan perubahan implementasi metrik.
- Staging lulus tetapi produksi gagal: bandingkan kelas perangkat keras, batas memori, concurrency, mount cache, dan proses readiness.
- Rollback lambat: pastikan image dan bobot lama tetap tersedia di node atau cache regional serta masih lolos pemeriksaan integritas.
Checklist rilis CI/CD model biologi
- Commit kode, konfigurasi, dataset, split, bobot, dan container memiliki identifier immutable.
- Manifest rilis lengkap, checksum-nya diverifikasi, dan signature valid jika diwajibkan.
- Skema input dan output terversi serta kompatibilitasnya diperiksa.
- Unit test, validasi fixture, dan smoke test inferensi lulus.
- Tidak ada NaN, infinity, tensor dengan shape salah, atau field output hilang.
- Tes deterministik dan perbandingan numerik menggunakan kebijakan toleransi yang disetujui.
- Output stokastik diuji sebagai distribusi dengan seed dan metode evaluasi tercatat.
- Benchmark penuh lulus untuk skor agregat dan slice yang diwajibkan.
- Provenance, lockfile, SBOM, hardware, dan laporan evaluasi tersimpan.
- Container dan bobot dipromosikan berdasarkan digest, bukan tag mutable.
- Staging menggunakan artefak identik dan perangkat keras yang representatif.
- Readiness memastikan model selesai dimuat sebelum menerima traffic.
- Observability produksi mencakup metrik teknis dan indikator kualitas yang tersedia.
- Artefak rilis sebelumnya masih tersedia dan prosedur rollback telah diuji.
Pipeline yang baik tidak mencoba mengulang pelatihan mahal pada setiap perubahan. Ia membangun rantai bukti bahwa setiap byte, konfigurasi, hasil evaluasi, dan lingkungan runtime yang masuk ke produksi adalah kandidat yang telah diuji. Dengan manifest immutable, quality gate berversi, cache berbasis digest, serta promosi tanpa rebuild, rilis model biologi berskala besar menjadi lebih dapat diaudit dan dipulihkan ketika terjadi regresi.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!